Initial contribution from commit 28fcf4edfc8e812332fc2c6bd241fab6e0f56094
from oomph/uss.
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..ceae4de
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# Set default behaviour, in case users don't have core.autocrlf set.
+* text=auto
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ed51d31
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,13 @@
+/workspace
+bin/
+target/
+state/
+*.local.launch
+Copy of *.launch
+*~
+~*.docx
+~*.pptx
+com.chronon.sb.browser.launcher.prefs
+Corel Auto-Preserve/
+.DS_Store
+*.credentials
diff --git a/org.eclipse.userstorage-feature/.project b/org.eclipse.userstorage-feature/.project
new file mode 100644
index 0000000..44799f9
--- /dev/null
+++ b/org.eclipse.userstorage-feature/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.userstorage-feature</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.pde.FeatureBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.FeatureNature</nature>
+	</natures>
+	<filteredResources>
+		<filter>
+			<id>1396938000000</id>
+			<name></name>
+			<type>10</type>
+			<matcher>
+				<id>org.eclipse.ui.ide.multiFilter</id>
+				<arguments>1.0-projectRelativePath-matches-true-false-target</arguments>
+			</matcher>
+		</filter>
+	</filteredResources>
+</projectDescription>
diff --git a/org.eclipse.userstorage-feature/.settings/org.eclipse.ltk.core.refactoring.prefs b/org.eclipse.userstorage-feature/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..2e4a92e
--- /dev/null
+++ b/org.eclipse.userstorage-feature/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Mon Jul 11 16:02:05 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/org.eclipse.userstorage-feature/build.properties b/org.eclipse.userstorage-feature/build.properties
new file mode 100644
index 0000000..88e19fe
--- /dev/null
+++ b/org.eclipse.userstorage-feature/build.properties
@@ -0,0 +1,16 @@
+# Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+# 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:
+#    Eike Stepper - initial API and implementation
+
+# UpdateTrigger = 20150923-1142
+
+bin.includes = feature.xml,\
+               feature.properties
+
+generateSourceReferences = true
+src.includes = pom.xml
diff --git a/org.eclipse.userstorage-feature/feature.properties b/org.eclipse.userstorage-feature/feature.properties
new file mode 100644
index 0000000..f2e1ace
--- /dev/null
+++ b/org.eclipse.userstorage-feature/feature.properties
@@ -0,0 +1,11 @@
+# Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+# 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:
+#    Eike Stepper - initial API and implementation
+
+featureName = Eclipse User Storage
+description = Contains the runtime plugins (core and UI) for accessing the Eclipse User Storage Service.
diff --git a/org.eclipse.userstorage-feature/feature.xml b/org.eclipse.userstorage-feature/feature.xml
new file mode 100644
index 0000000..02aa700
--- /dev/null
+++ b/org.eclipse.userstorage-feature/feature.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+  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:
+    Eike Stepper - initial API and implementation
+-->
+<feature
+      id="org.eclipse.userstorage"
+      label="%featureName"
+      version="1.0.0.qualifier"
+      provider-name="%providerName"
+      license-feature="org.eclipse.userstorage.license"
+      license-feature-version="0.0.0">
+
+   <description>
+      %description
+   </description>
+
+   <copyright url="%copyrightURL">
+      %copyright
+   </copyright>
+
+   <license url="%licenseURL">
+      %license
+   </license>
+
+   <plugin
+         id="org.eclipse.userstorage"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.userstorage.ui"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+</feature>
diff --git a/org.eclipse.userstorage-feature/pom.xml b/org.eclipse.userstorage-feature/pom.xml
new file mode 100644
index 0000000..ff79cd2
--- /dev/null
+++ b/org.eclipse.userstorage-feature/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+  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:
+    Eike Stepper - initial API and implementation
+-->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.eclipse.userstorage</groupId>
+    <artifactId>parent</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+  <groupId>org.eclipse.userstorage.features</groupId>
+  <artifactId>org.eclipse.userstorage</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>eclipse-feature</packaging>
+</project>
diff --git a/org.eclipse.userstorage.license-feature/.project b/org.eclipse.userstorage.license-feature/.project
new file mode 100644
index 0000000..a370849
--- /dev/null
+++ b/org.eclipse.userstorage.license-feature/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.userstorage.license-feature</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.pde.FeatureBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.FeatureNature</nature>
+	</natures>
+	<filteredResources>
+		<filter>
+			<id>1396938000000</id>
+			<name></name>
+			<type>10</type>
+			<matcher>
+				<id>org.eclipse.ui.ide.multiFilter</id>
+				<arguments>1.0-projectRelativePath-matches-true-false-target</arguments>
+			</matcher>
+		</filter>
+	</filteredResources>
+</projectDescription>
diff --git a/org.eclipse.userstorage.license-feature/about.html b/org.eclipse.userstorage.license-feature/about.html
new file mode 100644
index 0000000..d35d5ae
--- /dev/null
+++ b/org.eclipse.userstorage.license-feature/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>June 5, 2007</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
diff --git a/org.eclipse.userstorage.license-feature/build.properties b/org.eclipse.userstorage.license-feature/build.properties
new file mode 100644
index 0000000..ab6f8f4
--- /dev/null
+++ b/org.eclipse.userstorage.license-feature/build.properties
@@ -0,0 +1,20 @@
+# Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+# 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:
+#    Eike Stepper - initial API and implementation
+
+bin.includes = feature.xml,\
+               feature.properties,\
+               epl-v10.html,\
+               about.html,\
+               rootfiles/,\
+               build.properties,\
+               license.html
+src.includes = epl-v10.html,\
+               about.html
+
+root = rootfiles
diff --git a/org.eclipse.userstorage.license-feature/epl-v10.html b/org.eclipse.userstorage.license-feature/epl-v10.html
new file mode 100644
index 0000000..cb1073a
--- /dev/null
+++ b/org.eclipse.userstorage.license-feature/epl-v10.html
@@ -0,0 +1,304 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html xmlns:o="urn:schemas-microsoft-com:office:office"
+xmlns:w="urn:schemas-microsoft-com:office:word"
+xmlns="http://www.w3.org/TR/REC-html40">
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<link rel=File-List
+href="./Eclipse%20EPL%202003_11_10%20Final_files/filelist.xml">
+<title>Eclipse Public License - Version 1.0</title>
+<style>
+<!--
+ /* Font Definitions */
+@font-face
+	{
+	panose-1:2 11 6 4 3 5 4 4 2 4;
+	mso-font-charset:0;
+	mso-font-pitch:variable;
+	mso-font-signature:553679495 -2147483648 8 0 66047 0;}
+ /* Style Definitions */
+p.MsoNormal, li.MsoNormal, div.MsoNormal
+	{mso-style-parent:"";
+	margin:0in;
+	margin-bottom:.0001pt;
+	mso-pagination:widow-orphan;
+	font-size:12.0pt;
+	}
+p
+	{margin-right:0in;
+	mso-margin-top-alt:auto;
+	mso-margin-bottom-alt:auto;
+	margin-left:0in;
+	mso-pagination:widow-orphan;
+	font-size:12.0pt;
+	}
+p.BalloonText, li.BalloonText, div.BalloonText
+	{mso-style-name:"Balloon Text";
+	margin:0in;
+	margin-bottom:.0001pt;
+	mso-pagination:widow-orphan;
+	font-size:8.0pt;
+	
+	}
+@page Section1
+	{size:8.5in 11.0in;
+	margin:1.0in 1.25in 1.0in 1.25in;
+	mso-header-margin:.5in;
+	mso-footer-margin:.5in;
+	mso-paper-source:0;}
+div.Section1
+	{page:Section1;}
+-->
+</style>
+</head>
+
+<body lang="EN-US" style='tab-interval:.5in'>
+
+<div class=Section1>
+
+<p align=center style='text-align:center'><b>Eclipse Public License - v 1.0</b>
+</p>
+
+<p><span style='font-size:10.0pt'>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER
+THE TERMS OF THIS ECLIPSE PUBLIC LICENSE (&quot;AGREEMENT&quot;). ANY USE,
+REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE
+OF THIS AGREEMENT.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>1. DEFINITIONS</span></b> </p>
+
+<p><span style='font-size:10.0pt'>&quot;Contribution&quot; means:</span> </p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+in the case of the initial Contributor, the initial code and documentation
+distributed under this Agreement, and<br clear=left>
+b) in the case of each subsequent Contributor:</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>i)
+changes to the Program, and</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>ii)
+additions to the Program;</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>where
+such changes and/or additions to the Program originate from and are distributed
+by that particular Contributor. A Contribution 'originates' from a Contributor
+if it was added to the Program by such Contributor itself or anyone acting on
+such Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in conjunction
+with the Program under their own license agreement, and (ii) are not derivative
+works of the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>&quot;Contributor&quot; means any person or
+entity that distributes the Program.</span> </p>
+
+<p><span style='font-size:10.0pt'>&quot;Licensed Patents &quot; mean patent
+claims licensable by a Contributor which are necessarily infringed by the use
+or sale of its Contribution alone or when combined with the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>&quot;Program&quot; means the Contributions
+distributed in accordance with this Agreement.</span> </p>
+
+<p><span style='font-size:10.0pt'>&quot;Recipient&quot; means anyone who
+receives the Program under this Agreement, including all Contributors.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>2. GRANT OF RIGHTS</span></b> </p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+Subject to the terms of this Agreement, each Contributor hereby grants Recipient
+a non-exclusive, worldwide, royalty-free copyright license to<span
+style='color:red'> </span>reproduce, prepare derivative works of, publicly
+display, publicly perform, distribute and sublicense the Contribution of such
+Contributor, if any, and such derivative works, in source code and object code
+form.</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b)
+Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide,<span style='color:green'> </span>royalty-free
+patent license under Licensed Patents to make, use, sell, offer to sell, import
+and otherwise transfer the Contribution of such Contributor, if any, in source
+code and object code form. This patent license shall apply to the combination
+of the Contribution and the Program if, at the time the Contribution is added
+by the Contributor, such addition of the Contribution causes such combination
+to be covered by the Licensed Patents. The patent license shall not apply to
+any other combinations which include the Contribution. No hardware per se is
+licensed hereunder. </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>c)
+Recipient understands that although each Contributor grants the licenses to its
+Contributions set forth herein, no assurances are provided by any Contributor
+that the Program does not infringe the patent or other intellectual property
+rights of any other entity. Each Contributor disclaims any liability to Recipient
+for claims brought by any other entity based on infringement of intellectual
+property rights or otherwise. As a condition to exercising the rights and
+licenses granted hereunder, each Recipient hereby assumes sole responsibility
+to secure any other intellectual property rights needed, if any. For example,
+if a third party patent license is required to allow Recipient to distribute
+the Program, it is Recipient's responsibility to acquire that license before
+distributing the Program.</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>d)
+Each Contributor represents that to its knowledge it has sufficient copyright
+rights in its Contribution, if any, to grant the copyright license set forth in
+this Agreement. </span></p>
+
+<p><b><span style='font-size:10.0pt'>3. REQUIREMENTS</span></b> </p>
+
+<p><span style='font-size:10.0pt'>A Contributor may choose to distribute the
+Program in object code form under its own license agreement, provided that:</span>
+</p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+it complies with the terms and conditions of this Agreement; and</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b)
+its license agreement:</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>i)
+effectively disclaims on behalf of all Contributors all warranties and
+conditions, express and implied, including warranties or conditions of title
+and non-infringement, and implied warranties or conditions of merchantability
+and fitness for a particular purpose; </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>ii)
+effectively excludes on behalf of all Contributors all liability for damages,
+including direct, indirect, special, incidental and consequential damages, such
+as lost profits; </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>iii)
+states that any provisions which differ from this Agreement are offered by that
+Contributor alone and not by any other party; and</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>iv)
+states that source code for the Program is available from such Contributor, and
+informs licensees how to obtain it in a reasonable manner on or through a
+medium customarily used for software exchange.<span style='color:blue'> </span></span></p>
+
+<p><span style='font-size:10.0pt'>When the Program is made available in source
+code form:</span> </p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+it must be made available under this Agreement; and </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b) a
+copy of this Agreement must be included with each copy of the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>Contributors may not remove or alter any
+copyright notices contained within the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>Each Contributor must identify itself as the
+originator of its Contribution, if any, in a manner that reasonably allows
+subsequent Recipients to identify the originator of the Contribution. </span></p>
+
+<p><b><span style='font-size:10.0pt'>4. COMMERCIAL DISTRIBUTION</span></b> </p>
+
+<p><span style='font-size:10.0pt'>Commercial distributors of software may
+accept certain responsibilities with respect to end users, business partners
+and the like. While this license is intended to facilitate the commercial use
+of the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create potential
+liability for other Contributors. Therefore, if a Contributor includes the
+Program in a commercial product offering, such Contributor (&quot;Commercial
+Contributor&quot;) hereby agrees to defend and indemnify every other
+Contributor (&quot;Indemnified Contributor&quot;) against any losses, damages and
+costs (collectively &quot;Losses&quot;) arising from claims, lawsuits and other
+legal actions brought by a third party against the Indemnified Contributor to
+the extent caused by the acts or omissions of such Commercial Contributor in
+connection with its distribution of the Program in a commercial product
+offering. The obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In order
+to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
+Contributor in writing of such claim, and b) allow the Commercial Contributor
+to control, and cooperate with the Commercial Contributor in, the defense and
+any related settlement negotiations. The Indemnified Contributor may participate
+in any such claim at its own expense.</span> </p>
+
+<p><span style='font-size:10.0pt'>For example, a Contributor might include the
+Program in a commercial product offering, Product X. That Contributor is then a
+Commercial Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance claims and
+warranties are such Commercial Contributor's responsibility alone. Under this
+section, the Commercial Contributor would have to defend claims against the
+other Contributors related to those performance claims and warranties, and if a
+court requires any other Contributor to pay any damages as a result, the
+Commercial Contributor must pay those damages.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>5. NO WARRANTY</span></b> </p>
+
+<p><span style='font-size:10.0pt'>EXCEPT AS EXPRESSLY SET FORTH IN THIS
+AGREEMENT, THE PROGRAM IS PROVIDED ON AN &quot;AS IS&quot; BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
+WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and distributing the
+Program and assumes all risks associated with its exercise of rights under this
+Agreement , including but not limited to the risks and costs of program errors,
+compliance with applicable laws, damage to or loss of data, programs or
+equipment, and unavailability or interruption of operations. </span></p>
+
+<p><b><span style='font-size:10.0pt'>6. DISCLAIMER OF LIABILITY</span></b> </p>
+
+<p><span style='font-size:10.0pt'>EXCEPT AS EXPRESSLY SET FORTH IN THIS
+AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF
+THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGES.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>7. GENERAL</span></b> </p>
+
+<p><span style='font-size:10.0pt'>If any provision of this Agreement is invalid
+or unenforceable under applicable law, it shall not affect the validity or
+enforceability of the remainder of the terms of this Agreement, and without
+further action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.</span> </p>
+
+<p><span style='font-size:10.0pt'>If Recipient institutes patent litigation
+against any entity (including a cross-claim or counterclaim in a lawsuit)
+alleging that the Program itself (excluding combinations of the Program with
+other software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the date
+such litigation is filed. </span></p>
+
+<p><span style='font-size:10.0pt'>All Recipient's rights under this Agreement
+shall terminate if it fails to comply with any of the material terms or
+conditions of this Agreement and does not cure such failure in a reasonable
+period of time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive. </span></p>
+
+<p><span style='font-size:10.0pt'>Everyone is permitted to copy and distribute
+copies of this Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The Agreement
+Steward reserves the right to publish new versions (including revisions) of
+this Agreement from time to time. No one other than the Agreement Steward has
+the right to modify this Agreement. The Eclipse Foundation is the initial
+Agreement Steward. The Eclipse Foundation may assign the responsibility to
+serve as the Agreement Steward to a suitable separate entity. Each new version
+of the Agreement will be given a distinguishing version number. The Program
+(including Contributions) may always be distributed subject to the version of
+the Agreement under which it was received. In addition, after a new version of
+the Agreement is published, Contributor may elect to distribute the Program
+(including its Contributions) under the new version. Except as expressly stated
+in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to
+the intellectual property of any Contributor under this Agreement, whether
+expressly, by implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved.</span> </p>
+
+<p><span style='font-size:10.0pt'>This Agreement is governed by the laws of the
+State of New York and the intellectual property laws of the United States of
+America. No party to this Agreement will bring a legal action under this
+Agreement more than one year after the cause of action arose. Each party waives
+its rights to a jury trial in any resulting litigation.</span> </p>
+
+<p class=MsoNormal></p>
+
+</div>
+
+</body>
+
+</html>
\ No newline at end of file
diff --git a/org.eclipse.userstorage.license-feature/feature.properties b/org.eclipse.userstorage.license-feature/feature.properties
new file mode 100644
index 0000000..82173d5
--- /dev/null
+++ b/org.eclipse.userstorage.license-feature/feature.properties
@@ -0,0 +1,133 @@
+providerName = Eclipse.org
+
+copyrightURL = copyright.txt
+copyright = Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.\n\
+All rights reserved. This program and the accompanying materials\n\
+are made available under the terms of the Eclipse Public License v1.0\n\
+which accompanies this distribution, and is available at\n\
+http://www.eclipse.org/legal/epl-v10.html\n\
+
+licenseURL=license.html
+license=\
+Eclipse Foundation Software User Agreement\n\
+April 9, 2014\n\
+\n\
+Usage Of Content\n\
+\n\
+THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR\n\
+OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT").\n\
+USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS\n\
+AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR\n\
+NOTICES INDICATED OR REFERENCED BELOW.  BY USING THE CONTENT, YOU\n\
+AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT\n\
+AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS\n\
+OR NOTICES INDICATED OR REFERENCED BELOW.  IF YOU DO NOT AGREE TO THE\n\
+TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS\n\
+OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\
+BELOW, THEN YOU MAY NOT USE THE CONTENT.\n\
+\n\
+Applicable Licenses\n\
+\n\
+Unless otherwise indicated, all Content made available by the\n\
+Eclipse Foundation is provided to you under the terms and conditions of\n\
+the Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is\n\
+provided with this Content and is also available at http://www.eclipse.org/legal/epl-v10.html.\n\
+For purposes of the EPL, "Program" will mean the Content.\n\
+\n\
+Content includes, but is not limited to, source code, object code,\n\
+documentation and other files maintained in the Eclipse Foundation source code\n\
+repository ("Repository") in software modules ("Modules") and made available\n\
+as downloadable archives ("Downloads").\n\
+\n\
+       - Content may be structured and packaged into modules to facilitate delivering,\n\
+         extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"),\n\
+         plug-in fragments ("Fragments"), and features ("Features").\n\
+       - Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java(TM) ARchive)\n\
+         in a directory named "plugins".\n\
+       - A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.\n\
+         Each Feature may be packaged as a sub-directory in a directory named "features".\n\
+         Within a Feature, files named "feature.xml" may contain a list of the names and version\n\
+         numbers of the Plug-ins and/or Fragments associated with that Feature.\n\
+       - Features may also include other Features ("Included Features"). Within a Feature, files\n\
+         named "feature.xml" may contain a list of the names and version numbers of Included Features.\n\
+\n\
+The terms and conditions governing Plug-ins and Fragments should be\n\
+contained in files named "about.html" ("Abouts"). The terms and\n\
+conditions governing Features and Included Features should be contained\n\
+in files named "license.html" ("Feature Licenses"). Abouts and Feature\n\
+Licenses may be located in any directory of a Download or Module\n\
+including, but not limited to the following locations:\n\
+\n\
+       - The top-level (root) directory\n\
+       - Plug-in and Fragment directories\n\
+       - Inside Plug-ins and Fragments packaged as JARs\n\
+       - Sub-directories of the directory named "src" of certain Plug-ins\n\
+       - Feature directories\n\
+\n\
+Note: if a Feature made available by the Eclipse Foundation is installed using the\n\
+Provisioning Technology (as defined below), you must agree to a license ("Feature \n\
+Update License") during the installation process. If the Feature contains\n\
+Included Features, the Feature Update License should either provide you\n\
+with the terms and conditions governing the Included Features or inform\n\
+you where you can locate them. Feature Update Licenses may be found in\n\
+the "license" property of files named "feature.properties" found within a Feature.\n\
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the\n\
+terms and conditions (or references to such terms and conditions) that\n\
+govern your use of the associated Content in that directory.\n\
+\n\
+THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER\n\
+TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.\n\
+SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\
+\n\
+       - Eclipse Distribution License Version 1.0 (available at http://www.eclipse.org/licenses/edl-v1.0.html)\n\
+       - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\
+       - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\
+       - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\
+       - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\
+\n\
+IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\
+TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License\n\
+is provided, please contact the Eclipse Foundation to determine what terms and conditions\n\
+govern that particular Content.\n\
+\n\
+\n\Use of Provisioning Technology\n\
+\n\
+The Eclipse Foundation makes available provisioning software, examples of which include,\n\
+but are not limited to, p2 and the Eclipse Update Manager ("Provisioning Technology") for\n\
+the purpose of allowing users to install software, documentation, information and/or\n\
+other materials (collectively "Installable Software"). This capability is provided with\n\
+the intent of allowing such users to install, extend and update Eclipse-based products.\n\
+Information about packaging Installable Software is available at\n\
+http://eclipse.org/equinox/p2/repository_packaging.html ("Specification").\n\
+\n\
+You may use Provisioning Technology to allow other parties to install Installable Software.\n\
+You shall be responsible for enabling the applicable license agreements relating to the\n\
+Installable Software to be presented to, and accepted by, the users of the Provisioning Technology\n\
+in accordance with the Specification. By using Provisioning Technology in such a manner and\n\
+making it available in accordance with the Specification, you further acknowledge your\n\
+agreement to, and the acquisition of all necessary rights to permit the following:\n\
+\n\
+       1. A series of actions may occur ("Provisioning Process") in which a user may execute\n\
+          the Provisioning Technology on a machine ("Target Machine") with the intent of installing,\n\
+          extending or updating the functionality of an Eclipse-based product.\n\
+       2. During the Provisioning Process, the Provisioning Technology may cause third party\n\
+          Installable Software or a portion thereof to be accessed and copied to the Target Machine.\n\
+       3. Pursuant to the Specification, you will provide to the user the terms and conditions that\n\
+          govern the use of the Installable Software ("Installable Software Agreement") and such\n\
+          Installable Software Agreement shall be accessed from the Target Machine in accordance\n\
+          with the Specification. Such Installable Software Agreement must inform the user of the\n\
+          terms and conditions that govern the Installable Software and must solicit acceptance by\n\
+          the end user in the manner prescribed in such Installable Software Agreement. Upon such\n\
+          indication of agreement by the user, the provisioning Technology will complete installation\n\
+          of the Installable Software.\n\
+\n\
+Cryptography\n\
+\n\
+Content may contain encryption software. The country in which you are\n\
+currently may have restrictions on the import, possession, and use,\n\
+and/or re-export to another country, of encryption software. BEFORE\n\
+using any encryption software, please check the country's laws,\n\
+regulations and policies concerning the import, possession, or use, and\n\
+re-export of encryption software, to see if this is permitted.\n\
+\n\
+Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n
diff --git a/org.eclipse.userstorage.license-feature/feature.xml b/org.eclipse.userstorage.license-feature/feature.xml
new file mode 100644
index 0000000..da2e646
--- /dev/null
+++ b/org.eclipse.userstorage.license-feature/feature.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+  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:
+    Eike Stepper - initial API and implementation
+-->
+<feature
+      id="org.eclipse.userstorage.license"
+      label="Eclipse User Storage License"
+      version="1.0.0.qualifier"
+      provider-name="Eclipse.org">
+
+   <description>
+      Contains the shared license for all Eclipse User Storage features.
+   </description>
+
+   <copyright url="%copyrightURL">
+      %copyright
+   </copyright>
+
+   <license url="%licenseURL">
+      %license
+   </license>
+
+</feature>
diff --git a/org.eclipse.userstorage.license-feature/license.html b/org.eclipse.userstorage.license-feature/license.html
new file mode 100644
index 0000000..c3d34c3
--- /dev/null
+++ b/org.eclipse.userstorage.license-feature/license.html
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Foundation Software User Agreement</title>
+</head>
+
+<body lang="EN-US">
+<h2>Eclipse Foundation Software User Agreement</h2>
+<p>April 9, 2014</p>
+
+<h3>Usage Of Content</h3>
+
+<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+   (COLLECTIVELY &quot;CONTENT&quot;).  USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+   CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW.  BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+   OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+   NOTICES INDICATED OR REFERENCED BELOW.  IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+   CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
+
+<h3>Applicable Licenses</h3>
+
+<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
+   (&quot;EPL&quot;).  A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+   For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
+   repository (&quot;Repository&quot;) in software modules (&quot;Modules&quot;) and made available as downloadable archives (&quot;Downloads&quot;).</p>
+
+<ul>
+       <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content.  Typical modules may include plug-ins (&quot;Plug-ins&quot;), plug-in fragments (&quot;Fragments&quot;), and features (&quot;Features&quot;).</li>
+       <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java&trade; ARchive) in a directory named &quot;plugins&quot;.</li>
+       <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.  Each Feature may be packaged as a sub-directory in a directory named &quot;features&quot;.  Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of the Plug-ins
+      and/or Fragments associated with that Feature.</li>
+       <li>Features may also include other Features (&quot;Included Features&quot;). Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of Included Features.</li>
+</ul>
+
+<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named &quot;about.html&quot; (&quot;Abouts&quot;). The terms and conditions governing Features and
+Included Features should be contained in files named &quot;license.html&quot; (&quot;Feature Licenses&quot;).  Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations:</p>
+
+<ul>
+       <li>The top-level (root) directory</li>
+       <li>Plug-in and Fragment directories</li>
+       <li>Inside Plug-ins and Fragments packaged as JARs</li>
+       <li>Sub-directories of the directory named &quot;src&quot; of certain Plug-ins</li>
+       <li>Feature directories</li>
+</ul>
+
+<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license (&quot;Feature Update License&quot;) during the
+installation process.  If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them.  Feature Update Licenses may be found in the &quot;license&quot; property of files named &quot;feature.properties&quot; found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory.</p>
+
+<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.  SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
+
+<ul>
+       <li>Eclipse Distribution License Version 1.0 (available at <a href="http://www.eclipse.org/licenses/edl-v10.html">http://www.eclipse.org/licenses/edl-v1.0.html</a>)</li>
+       <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
+       <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
+       <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
+       <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
+</ul>
+
+<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT.  If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
+
+
+<h3>Use of Provisioning Technology</h3>
+
+<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
+   Update Manager (&quot;Provisioning Technology&quot;) for the purpose of allowing users to install software, documentation, information and/or
+   other materials (collectively &quot;Installable Software&quot;). This capability is provided with the intent of allowing such users to
+   install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a
+       href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a>
+   (&quot;Specification&quot;).</p>
+
+<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
+   applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
+   in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
+   Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p>
+
+<ol>
+       <li>A series of actions may occur (&quot;Provisioning Process&quot;) in which a user may execute the Provisioning Technology
+       on a machine (&quot;Target Machine&quot;) with the intent of installing, extending or updating the functionality of an Eclipse-based
+       product.</li>
+       <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be
+       accessed and copied to the Target Machine.</li>
+       <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable
+       Software (&quot;Installable Software Agreement&quot;) and such Installable Software Agreement shall be accessed from the Target
+       Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern
+       the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such
+       indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li>
+</ol>
+
+<h3>Cryptography</h3>
+
+<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+   another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+   possession, or use, and re-export of encryption software, to see if this is permitted.</p>
+
+<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p>
+</body>
+</html>
diff --git a/org.eclipse.userstorage.license-feature/pom.xml b/org.eclipse.userstorage.license-feature/pom.xml
new file mode 100644
index 0000000..8a7640d
--- /dev/null
+++ b/org.eclipse.userstorage.license-feature/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+  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:
+    Eike Stepper - initial API and implementation
+-->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.eclipse.userstorage</groupId>
+    <artifactId>parent</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+  <groupId>org.eclipse.userstorage.features</groupId>
+  <artifactId>org.eclipse.userstorage.license</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>eclipse-feature</packaging>
+</project>
diff --git a/org.eclipse.userstorage.license-feature/rootfiles/about.html b/org.eclipse.userstorage.license-feature/rootfiles/about.html
new file mode 100644
index 0000000..d35d5ae
--- /dev/null
+++ b/org.eclipse.userstorage.license-feature/rootfiles/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>June 5, 2007</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
diff --git a/org.eclipse.userstorage.license-feature/rootfiles/epl-v10.html b/org.eclipse.userstorage.license-feature/rootfiles/epl-v10.html
new file mode 100644
index 0000000..cb1073a
--- /dev/null
+++ b/org.eclipse.userstorage.license-feature/rootfiles/epl-v10.html
@@ -0,0 +1,304 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html xmlns:o="urn:schemas-microsoft-com:office:office"
+xmlns:w="urn:schemas-microsoft-com:office:word"
+xmlns="http://www.w3.org/TR/REC-html40">
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<link rel=File-List
+href="./Eclipse%20EPL%202003_11_10%20Final_files/filelist.xml">
+<title>Eclipse Public License - Version 1.0</title>
+<style>
+<!--
+ /* Font Definitions */
+@font-face
+	{
+	panose-1:2 11 6 4 3 5 4 4 2 4;
+	mso-font-charset:0;
+	mso-font-pitch:variable;
+	mso-font-signature:553679495 -2147483648 8 0 66047 0;}
+ /* Style Definitions */
+p.MsoNormal, li.MsoNormal, div.MsoNormal
+	{mso-style-parent:"";
+	margin:0in;
+	margin-bottom:.0001pt;
+	mso-pagination:widow-orphan;
+	font-size:12.0pt;
+	}
+p
+	{margin-right:0in;
+	mso-margin-top-alt:auto;
+	mso-margin-bottom-alt:auto;
+	margin-left:0in;
+	mso-pagination:widow-orphan;
+	font-size:12.0pt;
+	}
+p.BalloonText, li.BalloonText, div.BalloonText
+	{mso-style-name:"Balloon Text";
+	margin:0in;
+	margin-bottom:.0001pt;
+	mso-pagination:widow-orphan;
+	font-size:8.0pt;
+	
+	}
+@page Section1
+	{size:8.5in 11.0in;
+	margin:1.0in 1.25in 1.0in 1.25in;
+	mso-header-margin:.5in;
+	mso-footer-margin:.5in;
+	mso-paper-source:0;}
+div.Section1
+	{page:Section1;}
+-->
+</style>
+</head>
+
+<body lang="EN-US" style='tab-interval:.5in'>
+
+<div class=Section1>
+
+<p align=center style='text-align:center'><b>Eclipse Public License - v 1.0</b>
+</p>
+
+<p><span style='font-size:10.0pt'>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER
+THE TERMS OF THIS ECLIPSE PUBLIC LICENSE (&quot;AGREEMENT&quot;). ANY USE,
+REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE
+OF THIS AGREEMENT.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>1. DEFINITIONS</span></b> </p>
+
+<p><span style='font-size:10.0pt'>&quot;Contribution&quot; means:</span> </p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+in the case of the initial Contributor, the initial code and documentation
+distributed under this Agreement, and<br clear=left>
+b) in the case of each subsequent Contributor:</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>i)
+changes to the Program, and</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>ii)
+additions to the Program;</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>where
+such changes and/or additions to the Program originate from and are distributed
+by that particular Contributor. A Contribution 'originates' from a Contributor
+if it was added to the Program by such Contributor itself or anyone acting on
+such Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in conjunction
+with the Program under their own license agreement, and (ii) are not derivative
+works of the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>&quot;Contributor&quot; means any person or
+entity that distributes the Program.</span> </p>
+
+<p><span style='font-size:10.0pt'>&quot;Licensed Patents &quot; mean patent
+claims licensable by a Contributor which are necessarily infringed by the use
+or sale of its Contribution alone or when combined with the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>&quot;Program&quot; means the Contributions
+distributed in accordance with this Agreement.</span> </p>
+
+<p><span style='font-size:10.0pt'>&quot;Recipient&quot; means anyone who
+receives the Program under this Agreement, including all Contributors.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>2. GRANT OF RIGHTS</span></b> </p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+Subject to the terms of this Agreement, each Contributor hereby grants Recipient
+a non-exclusive, worldwide, royalty-free copyright license to<span
+style='color:red'> </span>reproduce, prepare derivative works of, publicly
+display, publicly perform, distribute and sublicense the Contribution of such
+Contributor, if any, and such derivative works, in source code and object code
+form.</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b)
+Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide,<span style='color:green'> </span>royalty-free
+patent license under Licensed Patents to make, use, sell, offer to sell, import
+and otherwise transfer the Contribution of such Contributor, if any, in source
+code and object code form. This patent license shall apply to the combination
+of the Contribution and the Program if, at the time the Contribution is added
+by the Contributor, such addition of the Contribution causes such combination
+to be covered by the Licensed Patents. The patent license shall not apply to
+any other combinations which include the Contribution. No hardware per se is
+licensed hereunder. </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>c)
+Recipient understands that although each Contributor grants the licenses to its
+Contributions set forth herein, no assurances are provided by any Contributor
+that the Program does not infringe the patent or other intellectual property
+rights of any other entity. Each Contributor disclaims any liability to Recipient
+for claims brought by any other entity based on infringement of intellectual
+property rights or otherwise. As a condition to exercising the rights and
+licenses granted hereunder, each Recipient hereby assumes sole responsibility
+to secure any other intellectual property rights needed, if any. For example,
+if a third party patent license is required to allow Recipient to distribute
+the Program, it is Recipient's responsibility to acquire that license before
+distributing the Program.</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>d)
+Each Contributor represents that to its knowledge it has sufficient copyright
+rights in its Contribution, if any, to grant the copyright license set forth in
+this Agreement. </span></p>
+
+<p><b><span style='font-size:10.0pt'>3. REQUIREMENTS</span></b> </p>
+
+<p><span style='font-size:10.0pt'>A Contributor may choose to distribute the
+Program in object code form under its own license agreement, provided that:</span>
+</p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+it complies with the terms and conditions of this Agreement; and</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b)
+its license agreement:</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>i)
+effectively disclaims on behalf of all Contributors all warranties and
+conditions, express and implied, including warranties or conditions of title
+and non-infringement, and implied warranties or conditions of merchantability
+and fitness for a particular purpose; </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>ii)
+effectively excludes on behalf of all Contributors all liability for damages,
+including direct, indirect, special, incidental and consequential damages, such
+as lost profits; </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>iii)
+states that any provisions which differ from this Agreement are offered by that
+Contributor alone and not by any other party; and</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>iv)
+states that source code for the Program is available from such Contributor, and
+informs licensees how to obtain it in a reasonable manner on or through a
+medium customarily used for software exchange.<span style='color:blue'> </span></span></p>
+
+<p><span style='font-size:10.0pt'>When the Program is made available in source
+code form:</span> </p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+it must be made available under this Agreement; and </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b) a
+copy of this Agreement must be included with each copy of the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>Contributors may not remove or alter any
+copyright notices contained within the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>Each Contributor must identify itself as the
+originator of its Contribution, if any, in a manner that reasonably allows
+subsequent Recipients to identify the originator of the Contribution. </span></p>
+
+<p><b><span style='font-size:10.0pt'>4. COMMERCIAL DISTRIBUTION</span></b> </p>
+
+<p><span style='font-size:10.0pt'>Commercial distributors of software may
+accept certain responsibilities with respect to end users, business partners
+and the like. While this license is intended to facilitate the commercial use
+of the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create potential
+liability for other Contributors. Therefore, if a Contributor includes the
+Program in a commercial product offering, such Contributor (&quot;Commercial
+Contributor&quot;) hereby agrees to defend and indemnify every other
+Contributor (&quot;Indemnified Contributor&quot;) against any losses, damages and
+costs (collectively &quot;Losses&quot;) arising from claims, lawsuits and other
+legal actions brought by a third party against the Indemnified Contributor to
+the extent caused by the acts or omissions of such Commercial Contributor in
+connection with its distribution of the Program in a commercial product
+offering. The obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In order
+to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
+Contributor in writing of such claim, and b) allow the Commercial Contributor
+to control, and cooperate with the Commercial Contributor in, the defense and
+any related settlement negotiations. The Indemnified Contributor may participate
+in any such claim at its own expense.</span> </p>
+
+<p><span style='font-size:10.0pt'>For example, a Contributor might include the
+Program in a commercial product offering, Product X. That Contributor is then a
+Commercial Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance claims and
+warranties are such Commercial Contributor's responsibility alone. Under this
+section, the Commercial Contributor would have to defend claims against the
+other Contributors related to those performance claims and warranties, and if a
+court requires any other Contributor to pay any damages as a result, the
+Commercial Contributor must pay those damages.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>5. NO WARRANTY</span></b> </p>
+
+<p><span style='font-size:10.0pt'>EXCEPT AS EXPRESSLY SET FORTH IN THIS
+AGREEMENT, THE PROGRAM IS PROVIDED ON AN &quot;AS IS&quot; BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
+WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and distributing the
+Program and assumes all risks associated with its exercise of rights under this
+Agreement , including but not limited to the risks and costs of program errors,
+compliance with applicable laws, damage to or loss of data, programs or
+equipment, and unavailability or interruption of operations. </span></p>
+
+<p><b><span style='font-size:10.0pt'>6. DISCLAIMER OF LIABILITY</span></b> </p>
+
+<p><span style='font-size:10.0pt'>EXCEPT AS EXPRESSLY SET FORTH IN THIS
+AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF
+THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGES.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>7. GENERAL</span></b> </p>
+
+<p><span style='font-size:10.0pt'>If any provision of this Agreement is invalid
+or unenforceable under applicable law, it shall not affect the validity or
+enforceability of the remainder of the terms of this Agreement, and without
+further action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.</span> </p>
+
+<p><span style='font-size:10.0pt'>If Recipient institutes patent litigation
+against any entity (including a cross-claim or counterclaim in a lawsuit)
+alleging that the Program itself (excluding combinations of the Program with
+other software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the date
+such litigation is filed. </span></p>
+
+<p><span style='font-size:10.0pt'>All Recipient's rights under this Agreement
+shall terminate if it fails to comply with any of the material terms or
+conditions of this Agreement and does not cure such failure in a reasonable
+period of time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive. </span></p>
+
+<p><span style='font-size:10.0pt'>Everyone is permitted to copy and distribute
+copies of this Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The Agreement
+Steward reserves the right to publish new versions (including revisions) of
+this Agreement from time to time. No one other than the Agreement Steward has
+the right to modify this Agreement. The Eclipse Foundation is the initial
+Agreement Steward. The Eclipse Foundation may assign the responsibility to
+serve as the Agreement Steward to a suitable separate entity. Each new version
+of the Agreement will be given a distinguishing version number. The Program
+(including Contributions) may always be distributed subject to the version of
+the Agreement under which it was received. In addition, after a new version of
+the Agreement is published, Contributor may elect to distribute the Program
+(including its Contributions) under the new version. Except as expressly stated
+in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to
+the intellectual property of any Contributor under this Agreement, whether
+expressly, by implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved.</span> </p>
+
+<p><span style='font-size:10.0pt'>This Agreement is governed by the laws of the
+State of New York and the intellectual property laws of the United States of
+America. No party to this Agreement will bring a legal action under this
+Agreement more than one year after the cause of action arose. Each party waives
+its rights to a jury trial in any resulting litigation.</span> </p>
+
+<p class=MsoNormal></p>
+
+</div>
+
+</body>
+
+</html>
\ No newline at end of file
diff --git a/org.eclipse.userstorage.license-feature/rootfiles/notice.html b/org.eclipse.userstorage.license-feature/rootfiles/notice.html
new file mode 100644
index 0000000..c3d34c3
--- /dev/null
+++ b/org.eclipse.userstorage.license-feature/rootfiles/notice.html
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Foundation Software User Agreement</title>
+</head>
+
+<body lang="EN-US">
+<h2>Eclipse Foundation Software User Agreement</h2>
+<p>April 9, 2014</p>
+
+<h3>Usage Of Content</h3>
+
+<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+   (COLLECTIVELY &quot;CONTENT&quot;).  USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+   CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW.  BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+   OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+   NOTICES INDICATED OR REFERENCED BELOW.  IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+   CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
+
+<h3>Applicable Licenses</h3>
+
+<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
+   (&quot;EPL&quot;).  A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+   For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
+   repository (&quot;Repository&quot;) in software modules (&quot;Modules&quot;) and made available as downloadable archives (&quot;Downloads&quot;).</p>
+
+<ul>
+       <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content.  Typical modules may include plug-ins (&quot;Plug-ins&quot;), plug-in fragments (&quot;Fragments&quot;), and features (&quot;Features&quot;).</li>
+       <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java&trade; ARchive) in a directory named &quot;plugins&quot;.</li>
+       <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.  Each Feature may be packaged as a sub-directory in a directory named &quot;features&quot;.  Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of the Plug-ins
+      and/or Fragments associated with that Feature.</li>
+       <li>Features may also include other Features (&quot;Included Features&quot;). Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of Included Features.</li>
+</ul>
+
+<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named &quot;about.html&quot; (&quot;Abouts&quot;). The terms and conditions governing Features and
+Included Features should be contained in files named &quot;license.html&quot; (&quot;Feature Licenses&quot;).  Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations:</p>
+
+<ul>
+       <li>The top-level (root) directory</li>
+       <li>Plug-in and Fragment directories</li>
+       <li>Inside Plug-ins and Fragments packaged as JARs</li>
+       <li>Sub-directories of the directory named &quot;src&quot; of certain Plug-ins</li>
+       <li>Feature directories</li>
+</ul>
+
+<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license (&quot;Feature Update License&quot;) during the
+installation process.  If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them.  Feature Update Licenses may be found in the &quot;license&quot; property of files named &quot;feature.properties&quot; found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory.</p>
+
+<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.  SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
+
+<ul>
+       <li>Eclipse Distribution License Version 1.0 (available at <a href="http://www.eclipse.org/licenses/edl-v10.html">http://www.eclipse.org/licenses/edl-v1.0.html</a>)</li>
+       <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
+       <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
+       <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
+       <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
+</ul>
+
+<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT.  If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
+
+
+<h3>Use of Provisioning Technology</h3>
+
+<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
+   Update Manager (&quot;Provisioning Technology&quot;) for the purpose of allowing users to install software, documentation, information and/or
+   other materials (collectively &quot;Installable Software&quot;). This capability is provided with the intent of allowing such users to
+   install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a
+       href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a>
+   (&quot;Specification&quot;).</p>
+
+<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
+   applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
+   in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
+   Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p>
+
+<ol>
+       <li>A series of actions may occur (&quot;Provisioning Process&quot;) in which a user may execute the Provisioning Technology
+       on a machine (&quot;Target Machine&quot;) with the intent of installing, extending or updating the functionality of an Eclipse-based
+       product.</li>
+       <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be
+       accessed and copied to the Target Machine.</li>
+       <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable
+       Software (&quot;Installable Software Agreement&quot;) and such Installable Software Agreement shall be accessed from the Target
+       Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern
+       the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such
+       indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li>
+</ol>
+
+<h3>Cryptography</h3>
+
+<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+   another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+   possession, or use, and re-export of encryption software, to see if this is permitted.</p>
+
+<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p>
+</body>
+</html>
diff --git a/org.eclipse.userstorage.releng/.classpath b/org.eclipse.userstorage.releng/.classpath
new file mode 100644
index 0000000..822a97a
--- /dev/null
+++ b/org.eclipse.userstorage.releng/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.userstorage.releng/.gitignore b/org.eclipse.userstorage.releng/.gitignore
new file mode 100644
index 0000000..53a78fa
--- /dev/null
+++ b/org.eclipse.userstorage.releng/.gitignore
@@ -0,0 +1,3 @@
+!/bin/
+#### EGit tends to append a /bin/ entry to the end of this file.
+#### DO NOT COMMIT THAT ENTRY!!!
diff --git a/org.eclipse.userstorage.releng/.project b/org.eclipse.userstorage.releng/.project
new file mode 100644
index 0000000..b3a26d2
--- /dev/null
+++ b/org.eclipse.userstorage.releng/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.userstorage.releng</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+	<filteredResources>
+		<filter>
+			<id>1396938000000</id>
+			<name></name>
+			<type>10</type>
+			<matcher>
+				<id>org.eclipse.ui.ide.multiFilter</id>
+				<arguments>1.0-projectRelativePath-matches-true-false-target</arguments>
+			</matcher>
+		</filter>
+	</filteredResources>
+</projectDescription>
diff --git a/org.eclipse.userstorage.releng/.settings/org.eclipse.core.resources.prefs b/org.eclipse.userstorage.releng/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..9467f98
--- /dev/null
+++ b/org.eclipse.userstorage.releng/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/org.eclipse.userstorage.releng.target=UTF-8
diff --git a/org.eclipse.userstorage.releng/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.userstorage.releng/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..bb20789
--- /dev/null
+++ b/org.eclipse.userstorage.releng/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,410 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+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.doc.comment.support=enabled
+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=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+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=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning
+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.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=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=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+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.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=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=warning
+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=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.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled
+org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,HIGH,LOW,LOW,LOW,LOW,LOW
+org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX,PERF,MEM,POLISH,@generated NOT,@ADDED
+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=1
+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=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_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=false
+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=160
+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=2
+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=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=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=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=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=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=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=do not 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=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_lambda_arrow=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=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=do not 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=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=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not 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_lambda_arrow=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=do not 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=160
+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=2
+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
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/org.eclipse.userstorage.releng/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.userstorage.releng/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..7c1dd68
--- /dev/null
+++ b/org.eclipse.userstorage.releng/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,125 @@
+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=true
+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_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.insert_inferred_type_arguments=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=true
+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=false
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+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_anonymous_class_creation=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup.use_type_arguments=false
+cleanup_profile=_UserStorage
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_UserStorage
+formatter_settings_version=12
+org.eclipse.jdt.ui.exception.name=ex
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=org.eclipse.userstorage;org.eclipse.emf;org.eclipse;com;org;javax;java;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="false" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment"/><template autoinsert\="false" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment"/><template autoinsert\="false" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment"/><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/*\r\n * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * which accompanies this distribution, and is available at\r\n * http\://www.eclipse.org/legal/epl-v10.html\r\n * \r\n * Contributors\:\r\n *    Eike Stepper - initial API and implementation\r\n */</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\r\n * @author Eike Stepper\r\n */</template><template autoinsert\="false" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment"/><template autoinsert\="false" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment"/><template autoinsert\="false" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment"/><template autoinsert\="false" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment"/><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\r\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\r\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\r\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\r\n</template><template autoinsert\="false" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">${exception_var}.printStackTrace();</template><template autoinsert\="false" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">${body_statement}</template><template autoinsert\="false" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+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=false
+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=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+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=true
+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=true
+sp_cleanup.remove_unused_imports=true
+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=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/org.eclipse.userstorage.releng/.settings/org.eclipse.ltk.core.refactoring.prefs b/org.eclipse.userstorage.releng/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..864e30f
--- /dev/null
+++ b/org.eclipse.userstorage.releng/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Thu Feb 04 09:44:24 CET 2010
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/org.eclipse.userstorage.releng/.settings/org.eclipse.pde.prefs b/org.eclipse.userstorage.releng/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..2683a79
--- /dev/null
+++ b/org.eclipse.userstorage.releng/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,32 @@
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.encodings=2
+compilers.p.build.java.compiler=2
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=2
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=2
+compilers.p.discouraged-class=2
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=1
+compilers.p.missing-version-import-package=1
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=2
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=0
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+eclipse.preferences.version=1
diff --git "a/org.eclipse.userstorage.releng/UserStorage Build \050debug\051.launch" "b/org.eclipse.userstorage.releng/UserStorage Build \050debug\051.launch"
new file mode 100644
index 0000000..310d7f0
--- /dev/null
+++ "b/org.eclipse.userstorage.releng/UserStorage Build \050debug\051.launch"
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${maven.root}\bin\mvnDebug.bat"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-Dbuild.id=Unknown&#13;&#10;-Dgit.commit=Unknown&#13;&#10;-Dgit.branch=Unknown&#13;&#10;-DskipTests=true&#13;&#10;-DDtycho.debug.resolver=true&#13;&#10;-DX&#13;&#10;clean&#13;&#10;verify"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${git.clone.uss}"/>
+</launchConfiguration>
diff --git a/org.eclipse.userstorage.releng/UserStorage Build.launch b/org.eclipse.userstorage.releng/UserStorage Build.launch
new file mode 100644
index 0000000..a66a217
--- /dev/null
+++ b/org.eclipse.userstorage.releng/UserStorage Build.launch
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${maven.root}\bin\mvn.bat"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-Dbuild.id=Unknown&#13;&#10;-Dgit.commit=Unknown&#13;&#10;-Dgit.branch=Unknown&#13;&#10;-DskipTests=false&#13;&#10;-Dtycho.debug.resolver=false&#13;&#10;-DX&#13;&#10;clean&#13;&#10;verify"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${git.clone.uss}"/>
+</launchConfiguration>
diff --git a/org.eclipse.userstorage.releng/UserStorage Clean.launch b/org.eclipse.userstorage.releng/UserStorage Clean.launch
new file mode 100644
index 0000000..0315884
--- /dev/null
+++ b/org.eclipse.userstorage.releng/UserStorage Clean.launch
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${maven.root}\bin\mvn.bat"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="clean&#13;&#10;-Dtycho.mode=maven"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${git.clone.uss}"/>
+</launchConfiguration>
diff --git a/org.eclipse.userstorage.releng/UserStorage.setup b/org.eclipse.userstorage.releng/UserStorage.setup
new file mode 100644
index 0000000..3fa3c32
--- /dev/null
+++ b/org.eclipse.userstorage.releng/UserStorage.setup
@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<setup:Project
+    xmi:version="2.0"
+    xmlns:xmi="http://www.omg.org/XMI"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:git="http://www.eclipse.org/oomph/setup/git/1.0"
+    xmlns:jdt="http://www.eclipse.org/oomph/setup/jdt/1.0"
+    xmlns:mylyn="http://www.eclipse.org/oomph/setup/mylyn/1.0"
+    xmlns:predicates="http://www.eclipse.org/oomph/predicates/1.0"
+    xmlns:setup="http://www.eclipse.org/oomph/setup/1.0"
+    xmlns:setup.p2="http://www.eclipse.org/oomph/setup/p2/1.0"
+    xmlns:setup.targlets="http://www.eclipse.org/oomph/setup/targlets/1.0"
+    xsi:schemaLocation="http://www.eclipse.org/oomph/setup/git/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/Git.ecore http://www.eclipse.org/oomph/setup/jdt/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/JDT.ecore http://www.eclipse.org/oomph/setup/mylyn/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/Mylyn.ecore http://www.eclipse.org/oomph/predicates/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/Predicates.ecore http://www.eclipse.org/oomph/setup/targlets/1.0 http://git.eclipse.org/c/oomph/org.eclipse.oomph.git/plain/setups/models/SetupTarglets.ecore"
+    name="userstorage"
+    label="User Storage SDK">
+  <setupTask
+      xsi:type="setup.p2:P2Task"
+      label="JDT + PDE">
+    <requirement
+        name="org.eclipse.jdt.feature.group"/>
+    <requirement
+        name="org.eclipse.pde.feature.group"/>
+    <requirement
+        name="org.eclipse.pde.api.tools.ee.feature.feature.group"
+        optional="true"/>
+  </setupTask>
+  <setupTask
+      xsi:type="setup:CompoundTask"
+      name="Global Preferences">
+    <setupTask
+        xsi:type="setup:CompoundTask"
+        name="org.eclipse.ant.ui">
+      <setupTask
+          xsi:type="setup:PreferenceTask"
+          key="/instance/org.eclipse.ant.ui/problem_classpath"
+          value="ignore"/>
+    </setupTask>
+    <setupTask
+        xsi:type="setup:CompoundTask"
+        name="org.eclipse.jdt.core">
+      <setupTask
+          xsi:type="setup:PreferenceTask"
+          key="/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable"
+          value="ignore"/>
+      <setupTask
+          xsi:type="setup:PreferenceTask"
+          key="/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unclosedCloseable"
+          value="ignore"/>
+    </setupTask>
+    <setupTask
+        xsi:type="setup:CompoundTask"
+        name="org.eclipse.jdt.launching">
+      <setupTask
+          xsi:type="setup:PreferenceTask"
+          key="/instance/org.eclipse.jdt.launching/org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE"
+          value="ignore"/>
+    </setupTask>
+    <setupTask
+        xsi:type="setup:CompoundTask"
+        name="org.eclipse.pde">
+      <setupTask
+          xsi:type="setup:PreferenceTask"
+          disabled="true"
+          key="/instance/org.eclipse.pde/compilers.f.unresolved-features"
+          value="2"/>
+      <setupTask
+          xsi:type="setup:PreferenceTask"
+          key="/instance/org.eclipse.pde/compilers.f.unresolved-plugins"
+          value="2"/>
+    </setupTask>
+    <setupTask
+        xsi:type="setup:CompoundTask"
+        name="org.eclipse.pde.api.tools">
+      <setupTask
+          xsi:type="setup:PreferenceTask"
+          key="/instance/org.eclipse.pde.api.tools/missing_default_api_profile"
+          value="Ignore"/>
+    </setupTask>
+    <setupTask
+        xsi:type="setup:CompoundTask"
+        name="org.eclipse.mylyn.team.ui">
+      <setupTask
+          xsi:type="setup:PreferenceTask"
+          key="/instance/org.eclipse.mylyn.team.ui/org.eclipse.mylyn.team.commit.template"
+          value="[$${task.key}] $${task.description}&#xD;&#xA;&#xD;&#xA;$${task.url}"/>
+    </setupTask>
+  </setupTask>
+  <setupTask
+      xsi:type="setup:EclipseIniTask"
+      option="-Xmx"
+      value="1400m"
+      vm="true"/>
+  <setupTask
+      xsi:type="jdt:JRETask"
+      version="JavaSE-1.6"
+      location="${jre.location-1.6}"/>
+  <setupTask
+      xsi:type="setup:StringSubstitutionTask"
+      name="git.clone.uss"
+      value="${git.clone.uss.location}"
+      documentation="The location of Oomph's Git clone."/>
+  <setupTask
+      xsi:type="git:GitCloneTask"
+      id="git.clone.uss"
+      remoteURI="ssh://${git.user.id}@git.eclipse.org/gitroot/oomph/uss"
+      userID="">
+    <description>User Storage</description>
+  </setupTask>
+  <setupTask
+      xsi:type="setup:VariableTask"
+      name="eclipse.target.platform"
+      defaultValue="Mars"
+      storageURI="scope://Workspace"
+      label="Target Platform">
+    <description>Choose the compatibility level of the target platform</description>
+  </setupTask>
+  <setupTask
+      xsi:type="setup.targlets:TargletTask">
+    <targlet
+        name="User Storage SDK"
+        activeRepositoryList="${eclipse.target.platform}">
+      <annotation
+          source="http:/www.eclipse.org/oomph/targlets/PomArtifactUpdater">
+        <detail
+            key="skipArtifactIDs">
+          <value>false</value>
+        </detail>
+        <detail
+            key="skipVersions">
+          <value>false</value>
+        </detail>
+      </annotation>
+      <annotation
+          source="http:/www.eclipse.org/oomph/targlets/TargetDefinitionGenerator">
+        <detail
+            key="location">
+          <value>${git.clone.uss.location/org.eclipse.userstorage.releng/org.eclipse.userstorage.releng.target}</value>
+        </detail>
+        <detail
+            key="preferredRepositories">
+          <value>http://download.eclipse.org/eclipse/updates/</value>
+        </detail>
+        <detail
+            key="includeAllPlatforms">
+          <value>false</value>
+        </detail>
+        <detail
+            key="includeSource">
+          <value>false</value>
+        </detail>
+      </annotation>
+      <requirement
+          name="org.eclipse.sdk.feature.group"/>
+      <requirement
+          name="org.apache.httpcomponents.httpclient.source"/>
+      <requirement
+          name="org.apache.httpcomponents.httpcore.source"/>
+      <requirement
+          name="*"/>
+      <sourceLocator
+          rootFolder="${git.clone.uss.location}">
+        <predicate
+            xsi:type="predicates:NotPredicate">
+          <operand
+              xsi:type="predicates:FilePredicate"
+              filePattern="prototype.txt"/>
+        </predicate>
+      </sourceLocator>
+      <repositoryList
+          name="Neon">
+        <repository
+            url="http://download.eclipse.org/modeling/emf/cdo/orbit/latest-R"/>
+      </repositoryList>
+      <repositoryList
+          name="Mars">
+        <repository
+            url="http://download.eclipse.org/modeling/emf/cdo/orbit/latest-R"/>
+      </repositoryList>
+    </targlet>
+  </setupTask>
+  <setupTask
+      xsi:type="mylyn:MylynQueriesTask"
+      repositoryURL="https://bugs.eclipse.org/bugs"
+      userID="${bugzilla.id}"
+      password="${eclipse.user.password}">
+    <query summary="API Bugs"
+        url="https://bugs.eclipse.org/bugs/buglist.cgi?product=Community&amp;component=API.eclipse.org&amp;bug_status=UNCONFIRMED&amp;bug_status=NEW&amp;bug_status=ASSIGNED&amp;bug_status=REOPENED"/>
+    <query summary="UserStorage Bugs"
+        url="https://bugs.eclipse.org/bugs/buglist.cgi?product=Oomph&amp;short_desc_type=substring&amp;short_desc=%5BUSS%5D&amp;bug_status=UNCONFIRMED&amp;bug_status=NEW&amp;bug_status=ASSIGNED&amp;bug_status=REOPENED&amp;bug_severity=blocker&amp;bug_severity=critical&amp;bug_severity=major&amp;bug_severity=normal&amp;bug_severity=minor&amp;bug_severity=trivial"/>
+    <query summary="UserStorage Features"
+        url="https://bugs.eclipse.org/bugs/buglist.cgi?product=Oomph&amp;short_desc_type=substring&amp;short_desc=%5BUSS%5D&amp;bug_status=UNCONFIRMED&amp;bug_status=NEW&amp;bug_status=ASSIGNED&amp;bug_status=REOPENED&amp;bug_severity=enhancement"/>
+    <query summary="UserStorage Resolved in 1.0.0"
+        url="https://bugs.eclipse.org/bugs/buglist.cgi?product=Oomph&amp;short_desc_type=substring&amp;short_desc=%5BUSS%5D&amp;bug_status=RESOLVED&amp;bug_status=VERIFIED&amp;bug_status=CLOSED&amp;resolution=FIXED&amp;resolution=DUPLICATE&amp;version=1.0.0"/>
+    <query summary="UserStorage Unspecified Version"
+        url="https://bugs.eclipse.org/bugs/buglist.cgi?product=Oomph&amp;short_desc_type=substring&amp;short_desc=%5BUSS%5D&amp;version=unspecified"/>
+  </setupTask>
+  <setupTask
+      xsi:type="mylyn:MylynBuildsTask"
+      serverURL="https://hudson.eclipse.org/oomph"
+      userID="${bugzilla.id}"
+      password="${eclipse.user.password}">
+    <buildPlan
+        name="uss-integration"/>
+    <buildPlan
+        name="uss-integration-nightly"/>
+  </setupTask>
+  <stream name="master"
+      label="Master">
+    <setupTask
+        xsi:type="setup:EclipseIniTask"
+        option="-Doomph.redirection.uss"
+        value="=http://git.eclipse.org/c/oomph/uss.git/plain/org.eclipse.userstorage.releng/UserStorage.setup->${git.clone.uss.location|uri}/org.eclipse.userstorage.releng/UserStorage.setup"
+        vm="true"
+        documentation="Redirect to the development version of the releng setup model."/>
+  </stream>
+  <logicalProjectContainer
+      xsi:type="setup:ProjectCatalog"
+      href="index:/org.eclipse.setup#//@projectCatalogs[name='org.eclipse']"/>
+</setup:Project>
diff --git a/org.eclipse.userstorage.releng/bin/.gitignore b/org.eclipse.userstorage.releng/bin/.gitignore
new file mode 100644
index 0000000..eae247c
--- /dev/null
+++ b/org.eclipse.userstorage.releng/bin/.gitignore
@@ -0,0 +1 @@
+!*.class
diff --git a/org.eclipse.userstorage.releng/bin/ArtifactRepositoryAdjuster$Properties.class b/org.eclipse.userstorage.releng/bin/ArtifactRepositoryAdjuster$Properties.class
new file mode 100644
index 0000000..0977ce0
--- /dev/null
+++ b/org.eclipse.userstorage.releng/bin/ArtifactRepositoryAdjuster$Properties.class
Binary files differ
diff --git a/org.eclipse.userstorage.releng/bin/ArtifactRepositoryAdjuster.class b/org.eclipse.userstorage.releng/bin/ArtifactRepositoryAdjuster.class
new file mode 100644
index 0000000..5c1c0cd
--- /dev/null
+++ b/org.eclipse.userstorage.releng/bin/ArtifactRepositoryAdjuster.class
Binary files differ
diff --git a/org.eclipse.userstorage.releng/bin/RepositoryComposer$1.class b/org.eclipse.userstorage.releng/bin/RepositoryComposer$1.class
new file mode 100644
index 0000000..e99e7cb
--- /dev/null
+++ b/org.eclipse.userstorage.releng/bin/RepositoryComposer$1.class
Binary files differ
diff --git a/org.eclipse.userstorage.releng/bin/RepositoryComposer$2.class b/org.eclipse.userstorage.releng/bin/RepositoryComposer$2.class
new file mode 100644
index 0000000..1ce9029
--- /dev/null
+++ b/org.eclipse.userstorage.releng/bin/RepositoryComposer$2.class
Binary files differ
diff --git a/org.eclipse.userstorage.releng/bin/RepositoryComposer.class b/org.eclipse.userstorage.releng/bin/RepositoryComposer.class
new file mode 100644
index 0000000..ccc3413
--- /dev/null
+++ b/org.eclipse.userstorage.releng/bin/RepositoryComposer.class
Binary files differ
diff --git a/org.eclipse.userstorage.releng/bin/Version.class b/org.eclipse.userstorage.releng/bin/Version.class
new file mode 100644
index 0000000..1a51444
--- /dev/null
+++ b/org.eclipse.userstorage.releng/bin/Version.class
Binary files differ
diff --git a/org.eclipse.userstorage.releng/hudson/adjustArtifactRepository.sh b/org.eclipse.userstorage.releng/hudson/adjustArtifactRepository.sh
new file mode 100644
index 0000000..07bbc5c
--- /dev/null
+++ b/org.eclipse.userstorage.releng/hudson/adjustArtifactRepository.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+if [[ "$GIT" == "" ]]; then
+  GIT=$WORKSPACE/git
+fi
+
+set -o nounset
+set -o errexit
+
+REPO=$1
+REPO_FINAL=$2
+REPO_NAME=$3
+BUILD_TYPE=$4
+CURDIR=`pwd -P`
+
+cd "$REPO"
+unzip -qq artifacts.jar
+cd "$CURDIR"
+
+java -cp "$GIT/org.eclipse.userstorage.releng/bin/" ArtifactRepositoryAdjuster \
+  "$REPO" \
+  "$REPO_FINAL" \
+  "$REPO_NAME"\
+  "$BUILD_TYPE"
+
+cd "$REPO"
+mv artifacts.out artifacts.xml
+zip -r -9 -qq artifacts.jar artifacts.xml
+rm artifacts.xml
+cd "$CURDIR"
diff --git a/org.eclipse.userstorage.releng/hudson/composeRepositories.sh b/org.eclipse.userstorage.releng/hudson/composeRepositories.sh
new file mode 100644
index 0000000..215a86c
--- /dev/null
+++ b/org.eclipse.userstorage.releng/hudson/composeRepositories.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+if [[ "$GIT" == "" ]]; then
+  GIT=$WORKSPACE/git
+fi
+
+set -o nounset
+set -o errexit
+
+DOWNLOADS_FOLDER=$1
+BUILD_TYPE=$2;
+BUILD_KEY=$3;
+BUILD_LABEL=$4;
+
+java -cp "$GIT/org.eclipse.userstorage.releng/bin/" RepositoryComposer \
+  "$DOWNLOADS_FOLDER" \
+  "$BUILD_TYPE" \
+  "$BUILD_KEY" \
+  "$BUILD_LABEL"
diff --git a/org.eclipse.userstorage.releng/hudson/promote.sh b/org.eclipse.userstorage.releng/hudson/promote.sh
new file mode 100644
index 0000000..b30bcdf
--- /dev/null
+++ b/org.eclipse.userstorage.releng/hudson/promote.sh
@@ -0,0 +1,129 @@
+#!/bin/bash
+
+if [[ "$BUILD_TYPE" == "" || "$BUILD_TYPE" == none ]]; then
+  BUILD_TYPE=nightly
+fi
+
+if [[ "$BUILD_KEY" == "" ]]; then
+  if [[ "$BUILD_TYPE" == milestone ]]; then
+    TYPE="S"
+  elif [[ "$BUILD_TYPE" == nightly ]]; then
+    TYPE="N"
+  fi
+
+  if [[ "$TYPE" != "" ]]; then
+    BUILD_KEY=$TYPE`echo $BUILD_ID | sed 's/\([0-9]*\)-\([0-9]*\)-\([0-9]*\)_\([0-9]*\)-\([0-9]*\)-\([0-9]*\)/\1\2\3-\4\5\6/g'`
+  fi
+fi
+
+if [[ "$BUILD_LABEL" == "" ]]; then
+  BUILD_LABEL=""
+fi
+
+FOLDER=$BUILD_KEY
+if [[ "$BUILD_LABEL" != "" ]]; then
+  FOLDER=$FOLDER-$BUILD_LABEL
+fi
+
+if [[ "$GIT" == "" ]]; then
+  GIT=$WORKSPACE/git
+fi
+
+if [[ "$SCRIPTS" == "" ]]; then
+  SCRIPTS=$GIT/org.eclipse.userstorage.releng/hudson
+fi
+
+if [[ "$DOWNLOADS" == "" ]]; then
+  DOWNLOADS=/home/data/httpd/download.eclipse.org/oomph/uss
+fi
+
+set -o nounset
+set -o errexit
+
+##################################################################################################
+#
+# At this point $WORKSPACE points to the following build folder structure:
+#
+#   $WORKSPACE/
+#   $WORKSPACE/updates/
+#   $WORKSPACE/updates/features/
+#   $WORKSPACE/updates/plugins/
+#   $WORKSPACE/updates/artifacts.jar
+#   $WORKSPACE/updates/content.jar
+#   $WORKSPACE/updates/org.eclipse.userstorage.site.zip
+#
+##################################################################################################
+
+echo ""
+
+PROPERTIES=$WORKSPACE/updates/repository.properties
+echo "branch = $GIT_BRANCH" >> $PROPERTIES
+echo "commit = $GIT_COMMIT" >> $PROPERTIES
+echo "number = $BUILD_NUMBER" >> $PROPERTIES
+echo "key = $BUILD_KEY" >> $PROPERTIES
+echo "label = $BUILD_LABEL" >> $PROPERTIES
+
+BUILDS=$DOWNLOADS/builds
+UPDATES=$DOWNLOADS/updates
+DROPS=$DOWNLOADS/drops
+DROP_TYPE=$DROPS/$BUILD_TYPE
+DROP=$DROP_TYPE/$FOLDER
+
+mkdir -p $DOWNLOADS
+mkdir -p $BUILDS
+mkdir -p $UPDATES
+mkdir -p $DROPS
+mkdir -p $DROP_TYPE
+
+cp -a $PROPERTIES $BUILDS/$BUILD_NUMBER.properties
+
+###################
+# DOWNLOADS/DROPS #
+###################
+
+echo "Promoting $WORKSPACE/updates"
+rm -rf $DROP
+mkdir $DROP
+cp -a $WORKSPACE/updates/* $DROP
+$BASH $SCRIPTS/adjustArtifactRepository.sh \
+  $DROP \
+  $DROP \
+  "User Storage Updates $FOLDER" \
+  $BUILD_TYPE
+
+#####################
+# DOWNLOADS/UPDATES #
+#####################
+
+cd $WORKSPACE
+rm -rf $UPDATES.tmp
+cp -a $UPDATES $UPDATES.tmp
+
+$BASH $SCRIPTS/composeRepositories.sh \
+  "$DOWNLOADS" \
+  "$BUILD_TYPE" \
+  "$BUILD_KEY" \
+  "$BUILD_LABEL"
+
+mkdir -p $UPDATES.tmp/$BUILD_TYPE/latest
+cp -a $DROP/org.eclipse.userstorage.site.zip $UPDATES.tmp/$BUILD_TYPE/latest
+
+mkdir -p $UPDATES.tmp/latest
+cp -a $DROP/org.eclipse.userstorage.site.zip $UPDATES.tmp/latest
+
+mv $UPDATES $UPDATES.bak; mv $UPDATES.tmp $UPDATES
+
+cd $WORKSPACE
+rm -rf $UPDATES.bak
+
+cd $WORKSPACE
+for t in nightly milestone; do
+  for f in $DROPS/$t/*; do
+    if [[ -f $f/REMOVE ]]; then
+      echo "Deleting $f"
+      rm -rf $f
+    fi
+  done
+done
+
+echo ""
diff --git a/org.eclipse.userstorage.releng/hudson/repackage.sh b/org.eclipse.userstorage.releng/hudson/repackage.sh
new file mode 100644
index 0000000..87d0301
--- /dev/null
+++ b/org.eclipse.userstorage.releng/hudson/repackage.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+if [[ "$GIT" == "" ]]; then
+  GIT=$WORKSPACE/git
+fi
+
+if [[ "$PACK_AND_SIGN" == "" ]]; then
+  PACK_AND_SIGN=false
+fi
+
+set -o nounset
+set -o errexit
+
+###########################################################################
+echo ""
+
+rm -rf $WORKSPACE/updates
+mkdir $WORKSPACE/updates
+cp -a $GIT/org.eclipse.userstorage.site/target/repository/* $WORKSPACE/updates
+
+cd $WORKSPACE/updates
+echo "Zipping update site"
+zip -r -9 -qq org.eclipse.userstorage.site.zip * -x plugins/*.pack.gz
+
+echo ""
+
diff --git a/org.eclipse.userstorage.releng/org.eclipse.userstorage.releng.target b/org.eclipse.userstorage.releng/org.eclipse.userstorage.releng.target
new file mode 100644
index 0000000..4e76c66
--- /dev/null
+++ b/org.eclipse.userstorage.releng/org.eclipse.userstorage.releng.target
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?pde version="3.8"?>
+<target name="Generated from User Storage SDK" sequenceNumber="1">
+  <locations>
+    <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="false" type="InstallableUnit">
+      <unit id="org.eclipse.sdk.feature.group" version="0.0.0"/>
+      <repository location="http://download.eclipse.org/eclipse/updates/4.5"/>
+    </location>
+  </locations>
+</target>
diff --git a/org.eclipse.userstorage.releng/pom.xml b/org.eclipse.userstorage.releng/pom.xml
new file mode 100644
index 0000000..49890c3
--- /dev/null
+++ b/org.eclipse.userstorage.releng/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+  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:
+    Eike Stepper - initial API and implementation
+-->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.eclipse.userstorage</groupId>
+    <artifactId>parent</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+  <groupId>org.eclipse.userstorage</groupId>
+  <artifactId>org.eclipse.userstorage.releng</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>eclipse-target-definition</packaging>
+</project>
diff --git a/org.eclipse.userstorage.releng/src/.gitignore b/org.eclipse.userstorage.releng/src/.gitignore
new file mode 100644
index 0000000..eae247c
--- /dev/null
+++ b/org.eclipse.userstorage.releng/src/.gitignore
@@ -0,0 +1 @@
+!*.class
diff --git a/org.eclipse.userstorage.releng/src/ArtifactRepositoryAdjuster.java b/org.eclipse.userstorage.releng/src/ArtifactRepositoryAdjuster.java
new file mode 100644
index 0000000..7c24448
--- /dev/null
+++ b/org.eclipse.userstorage.releng/src/ArtifactRepositoryAdjuster.java
@@ -0,0 +1,263 @@
+
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Stepper
+ */
+public final class ArtifactRepositoryAdjuster
+{
+  private static final String DOWNLOAD_PREFIX = "/home/data/httpd/download.eclipse.org/";
+
+  private static final Pattern REPOSITORY_PATTERN = Pattern.compile("\\s*<repository.*?>\\s*");
+
+  private static final Pattern FEATURE_PATTERN = Pattern.compile(
+      "\\s*<artifact\\s+classifier\\s*=\\s*['\"]org.eclipse.update.feature['\"]\\s+id\\s*=\\s*['\"](org\\.eclipse\\.userstorage.*?)['\"]\\s+version\\s*=\\s*['\"]([^'\"]*)['\"].*?>\\s*");
+
+  private ArtifactRepositoryAdjuster()
+  {
+  }
+
+  public static void main(String[] args) throws Exception
+  {
+    File repositoryFolder = new File(args[0]).getCanonicalFile();
+    File repositoryFolderFinal = new File(args[1]).getCanonicalFile();
+    String repositoryName = args[2];
+    String buildType = args[3];
+
+    File input = new File(repositoryFolder, "artifacts.xml");
+    File output = new File(repositoryFolder, "artifacts.out");
+
+    Version greatestVersion = getGreatestFeatureVersion(input);
+
+    System.out.println("Adjusting " + input);
+    System.out.println("  repository.name = " + repositoryName);
+
+    BufferedReader reader = new BufferedReader(new FileReader(input));
+    BufferedWriter writer = new BufferedWriter(new FileWriter(output));
+
+    String relativePath = repositoryFolderFinal.getAbsolutePath();
+    if (relativePath.startsWith(DOWNLOAD_PREFIX))
+    {
+      relativePath = relativePath.substring(DOWNLOAD_PREFIX.length());
+    }
+
+    if (relativePath.startsWith("/"))
+    {
+      relativePath = relativePath.substring(1);
+    }
+
+    boolean repositoryFound = false;
+    String line;
+
+    while ((line = reader.readLine()) != null)
+    {
+      if (!repositoryFound)
+      {
+        Matcher matcher = REPOSITORY_PATTERN.matcher(line);
+        if (matcher.matches())
+        {
+          line = line.replaceFirst("name=['\"].*?['\"]", "name='" + repositoryName + "'");
+          writeLine(writer, line);
+
+          Properties properties = new Properties(reader);
+
+          boolean mirrored = !"nightly".equals(buildType);
+          if (mirrored)
+          {
+            String mirrorsURL = "http://www.eclipse.org/downloads/download.php?file=/" + relativePath + "&amp;format=xml";
+            System.out.println("  p2.mirrorsURL = " + mirrorsURL);
+            properties.put("p2.mirrorsURL", mirrorsURL);
+          }
+          else
+          {
+            properties.remove("p2.mirrorsURL");
+          }
+
+          String statsURI = "http://download.eclipse.org/stats/userstorage/feature/" + greatestVersion;
+          System.out.println("  p2.statsURI = " + statsURI);
+          properties.put("p2.statsURI", statsURI);
+
+          properties.write(writer);
+          repositoryFound = true;
+          continue;
+        }
+      }
+      else
+      {
+        Matcher matcher = FEATURE_PATTERN.matcher(line);
+        if (matcher.matches())
+        {
+          writeLine(writer, line);
+
+          String id = matcher.group(1);
+          System.out.println("  download.stats = " + id);
+
+          Properties properties = new Properties(reader);
+          properties.put("download.stats", id);
+          properties.write(writer);
+
+          continue;
+        }
+      }
+
+      writeLine(writer, line);
+    }
+
+    writer.close();
+    reader.close();
+  }
+
+  private static Version getGreatestFeatureVersion(File input) throws IOException
+  {
+    Version greatestVersion = null;
+    List<String> lines = readLines(input, "UTF-8");
+    for (String line : lines)
+    {
+      Matcher matcher = FEATURE_PATTERN.matcher(line);
+      if (matcher.matches())
+      {
+        Version version = new Version(matcher.group(2));
+        if (greatestVersion == null || version.isGreaterThan(greatestVersion))
+        {
+          greatestVersion = version;
+        }
+      }
+    }
+
+    return greatestVersion;
+  }
+
+  private static List<String> readLines(File file, String charsetName) throws IOException
+  {
+    List<String> lines = new ArrayList<String>();
+
+    if (file.exists())
+    {
+      InputStream in = null;
+      Reader reader = null;
+      BufferedReader bufferedReader = null;
+
+      try
+      {
+        in = new FileInputStream(file);
+        reader = charsetName == null ? new InputStreamReader(in) : new InputStreamReader(in, charsetName);
+        bufferedReader = new BufferedReader(reader);
+
+        String line;
+        while ((line = bufferedReader.readLine()) != null)
+        {
+          lines.add(line);
+        }
+      }
+      finally
+      {
+        closeSilent(bufferedReader);
+        closeSilent(reader);
+        closeSilent(in);
+      }
+    }
+
+    return lines;
+  }
+
+  private static void closeSilent(Closeable closeable)
+  {
+    try
+    {
+      if (closeable != null)
+      {
+        closeable.close();
+      }
+    }
+    catch (Exception ex)
+    {
+      // Ignore.
+    }
+  }
+
+  private static void writeLine(BufferedWriter writer, String line) throws IOException
+  {
+    writer.write(line);
+    writer.write('\n');
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private static final class Properties extends LinkedHashMap<String, String>
+  {
+    private static final long serialVersionUID = 1L;
+
+    private static final Pattern PROPERTIES_PATTERN = Pattern.compile("(\\s*)<properties\\s+size\\s*=\\s*['\"]([0-9]+)['\"]\\s*>\\s*");
+
+    private static final Pattern PROPERTY_PATTERN = Pattern
+        .compile("(\\s*)<property\\s+name\\s*=\\s*['\"](.*?)['\"]\\s+value\\s*=\\s*['\"](.*?)['\"]\\s*/>\\s*");
+
+    private String propertiesIndent;
+
+    private String propertyIndent;
+
+    public Properties(BufferedReader reader) throws IOException
+    {
+      String propertiesLine = reader.readLine();
+      Matcher propertiesMatcher = PROPERTIES_PATTERN.matcher(propertiesLine);
+      if (!propertiesMatcher.matches())
+      {
+        throw new IllegalStateException("No properties match: " + propertiesLine);
+      }
+
+      propertiesIndent = propertiesMatcher.group(1);
+      int size = Integer.parseInt(propertiesMatcher.group(2));
+
+      for (int i = 0; i < size; i++)
+      {
+        String propertyLine = reader.readLine();
+        Matcher propertyMatcher = PROPERTY_PATTERN.matcher(propertyLine);
+        if (!propertyMatcher.matches())
+        {
+          throw new IllegalStateException("No property match: " + propertyLine);
+        }
+
+        propertyIndent = propertyMatcher.group(1);
+        put(propertyMatcher.group(2), propertyMatcher.group(3));
+      }
+    }
+
+    public void write(BufferedWriter writer) throws IOException
+    {
+      writeLine(writer, propertiesIndent + "<properties size='" + size() + "'>");
+
+      for (Map.Entry<String, String> entry : entrySet())
+      {
+        writeLine(writer, propertyIndent + "<property name='" + entry.getKey() + "' value='" + entry.getValue() + "'/>");
+      }
+    }
+  }
+}
diff --git a/org.eclipse.userstorage.releng/src/RepositoryComposer.java b/org.eclipse.userstorage.releng/src/RepositoryComposer.java
new file mode 100644
index 0000000..ad60e68
--- /dev/null
+++ b/org.eclipse.userstorage.releng/src/RepositoryComposer.java
@@ -0,0 +1,325 @@
+
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.jar.JarOutputStream;
+import java.util.zip.ZipEntry;
+
+/**
+ * @author Stepper
+ */
+public final class RepositoryComposer
+{
+  public static final String PROJECT = "User Storage";
+
+  private static final String REMOVE_MARKER = "REMOVE";
+
+  private static final Comparator<String> ALPHA_COMPARATOR = new Comparator<String>()
+  {
+    @Override
+    public int compare(String n1, String n2)
+    {
+      if (n1 == null)
+      {
+        n1 = "";
+      }
+
+      if (n2 == null)
+      {
+        n2 = "";
+      }
+
+      return n2.compareTo(n1);
+    }
+  };
+
+  private static final Comparator<String> VERSION_COMPARATOR = new Comparator<String>()
+  {
+    @Override
+    public int compare(String n1, String n2)
+    {
+      return new Version(n2).compareTo(new Version(n1));
+    }
+  };
+
+  private RepositoryComposer()
+  {
+  }
+
+  public static void main(String[] args) throws Exception
+  {
+    File downloadsFolder = new File(args[0]).getCanonicalFile();
+    String buildType = args[1];
+    String buildKey = args[2];
+    String buildLabel = args[3];
+
+    String folder = buildKey;
+    if (buildLabel.length() != 0)
+    {
+      folder += "-" + buildLabel;
+    }
+
+    File dropsFolder = new File(downloadsFolder, "drops");
+    File dropTypeFolder = new File(dropsFolder, buildType);
+    File dropFolder = new File(dropTypeFolder, folder);
+
+    File updatesFolder = new File(downloadsFolder, "updates.tmp");
+    File updateTypeFolder = new File(updatesFolder, buildType);
+
+    if ("release".equals(buildType))
+    {
+      composeRepositories(dropTypeFolder, updateTypeFolder, VERSION_COMPARATOR, Integer.MAX_VALUE);
+
+      boolean milestonesChanged = false;
+      File milestonesFolder = new File(dropsFolder, "milestone");
+      File[] children = milestonesFolder.listFiles();
+      if (children != null)
+      {
+        for (File child : children)
+        {
+          if (child.isDirectory() && child.getName().contains("-" + buildLabel + "-"))
+          {
+            scheduleRemoval(child);
+            milestonesChanged = true;
+          }
+        }
+      }
+
+      if (milestonesChanged)
+      {
+        composeMilestoneRepositories(dropsFolder, new File(updatesFolder, "milestone"));
+      }
+    }
+    else if ("milestone".equals(buildType))
+    {
+      composeMilestoneRepositories(dropsFolder, updateTypeFolder);
+    }
+    else if ("nightly".equals(buildType))
+    {
+      composeRepositories(dropTypeFolder, updateTypeFolder, ALPHA_COMPARATOR, 5);
+    }
+
+    composeRepository(updatesFolder, PROJECT + " All", getComposites(updatesFolder));
+    composeRepository(new File(updatesFolder, "latest"), PROJECT + " Latest", Collections.singletonList(dropFolder));
+  }
+
+  private static void composeMilestoneRepositories(File dropsFolder, File updateTypeFolder) throws IOException
+  {
+    File milestonesFolder = new File(dropsFolder, "milestone");
+    if (!composeRepositories(milestonesFolder, updateTypeFolder, ALPHA_COMPARATOR, Integer.MAX_VALUE))
+    {
+      List<File> drops = new ArrayList<File>();
+
+      File releasesFolder = new File(dropsFolder, "release");
+      List<String> names = getSortedChildren(releasesFolder, VERSION_COMPARATOR);
+      if (!names.isEmpty())
+      {
+        drops.add(new File(releasesFolder, names.get(0)));
+      }
+
+      composeRepository(updateTypeFolder, PROJECT + " Milestones", drops);
+      composeRepository(new File(updateTypeFolder, "latest"), PROJECT + " Latest Milestone", drops);
+    }
+  }
+
+  private static boolean composeRepositories(File dropTypeFolder, File updateTypeFolder, Comparator<String> comparator, int max) throws IOException
+  {
+    List<String> names = getSortedChildren(dropTypeFolder, comparator);
+    if (names.isEmpty())
+    {
+      return false;
+    }
+
+    List<File> drops = new ArrayList<File>();
+    int count = 0;
+
+    for (String name : names)
+    {
+      File drop = new File(dropTypeFolder, name);
+      if (++count > max)
+      {
+        scheduleRemoval(drop);
+      }
+      else
+      {
+        drops.add(drop);
+      }
+    }
+
+    String name = dropTypeFolder.getName();
+    if ("release".equals(name))
+    {
+      name = "Releases";
+    }
+    else if ("milestone".equals(name))
+    {
+      name = "Milestones";
+    }
+    else if ("nightly".equals(name))
+    {
+      name = "Nightly Builds";
+    }
+
+    composeRepository(updateTypeFolder, PROJECT + " " + name, drops);
+    composeRepository(new File(updateTypeFolder, "latest"), PROJECT + " Latest " + name.substring(0, name.length() - 1),
+        Collections.singletonList(drops.get(0)));
+    return true;
+  }
+
+  private static void composeRepository(File compositeFolder, String name, List<File> drops) throws IOException
+  {
+    long timestamp = System.currentTimeMillis();
+    writeRepository(compositeFolder, true, name, timestamp, drops);
+    writeRepository(compositeFolder, false, name, timestamp, drops);
+  }
+
+  private static void writeRepository(File compositeFolder, boolean metadata, String name, long timestamp, List<File> drops) throws IOException
+  {
+    String entryName;
+    String fileName;
+    String processingInstruction;
+    String type;
+    if (metadata)
+    {
+      entryName = "compositeContent.xml";
+      fileName = "compositeContent.jar";
+      processingInstruction = "compositeMetadataRepository";
+      type = "org.eclipse.equinox.internal.p2.metadata.repository.CompositeMetadataRepository";
+    }
+    else
+    {
+      entryName = "compositeArtifacts.xml";
+      fileName = "compositeArtifacts.jar";
+      processingInstruction = "compositeArtifactRepository";
+      type = "org.eclipse.equinox.internal.p2.artifact.repository.CompositeArtifactRepository";
+    }
+
+    compositeFolder.mkdirs();
+    File file = new File(compositeFolder, fileName);
+    FileOutputStream fileOutputStream = new FileOutputStream(file);
+    JarOutputStream jarOutputStream = new JarOutputStream(fileOutputStream);
+    jarOutputStream.putNextEntry(new ZipEntry(entryName));
+
+    Writer out = new OutputStreamWriter(jarOutputStream, "UTF-8");
+    BufferedWriter writer = new BufferedWriter(out);
+
+    writeLine(writer, "<?xml version='1.0' encoding='UTF-8'?>");
+    writeLine(writer, "<?" + processingInstruction + " version='1.0.0'?>");
+    writeLine(writer, "<repository name='" + name + "' type='" + type + "' version='1.0.0'>");
+    writeLine(writer, "  <properties size='2'>");
+    writeLine(writer, "    <property name='p2.timestamp' value='" + timestamp + "'/>");
+    writeLine(writer, "    <property name='p2.compressed' value='false'/>");
+    writeLine(writer, "  </properties>");
+    writeLine(writer, "  <children size='" + drops.size() + "'>");
+
+    for (File drop : drops)
+    {
+      String relativePath;
+      if (drop.isAbsolute())
+      {
+        relativePath = getRelativePath(compositeFolder, drop);
+      }
+      else
+      {
+        relativePath = drop.getPath().replace(File.separatorChar, '/');
+      }
+
+      writeLine(writer, "    <child location='" + relativePath + "'/>");
+    }
+
+    writeLine(writer, "  </children>");
+    writeLine(writer, "</repository>");
+    writer.flush();
+
+    jarOutputStream.closeEntry();
+    jarOutputStream.close();
+  }
+
+  private static void writeLine(BufferedWriter writer, String line) throws IOException
+  {
+    writer.write(line);
+    writer.write('\n');
+  }
+
+  private static String getRelativePath(File source, File target)
+  {
+    String targetPath = target.getAbsolutePath();
+    StringBuilder builder = new StringBuilder();
+
+    while (source != null)
+    {
+      String sourcePath = source.getAbsolutePath();
+      if (targetPath.startsWith(sourcePath))
+      {
+        return builder.toString() + targetPath.substring(sourcePath.length() + 1).replace(File.separatorChar, '/');
+      }
+
+      builder.append("../");
+      source = source.getParentFile();
+    }
+
+    throw new IllegalStateException();
+  }
+
+  private static List<File> getComposites(File updatesFolder)
+  {
+    List<File> composites = new ArrayList<File>();
+    addComposite(updatesFolder, composites, "release");
+    addComposite(updatesFolder, composites, "milestone");
+    addComposite(updatesFolder, composites, "nightly");
+    return composites;
+  }
+
+  private static void addComposite(File updatesFolder, List<File> composites, String name)
+  {
+    if (new File(updatesFolder, name).isDirectory())
+    {
+      composites.add(new File(name));
+    }
+  }
+
+  private static List<String> getSortedChildren(File folder, Comparator<String> comparator)
+  {
+    List<String> names = new ArrayList<String>();
+
+    File[] children = folder.listFiles();
+    if (children != null)
+    {
+      for (File child : children)
+      {
+        if (child.isDirectory() && !new File(child, REMOVE_MARKER).exists())
+        {
+          names.add(child.getName());
+        }
+      }
+
+      Collections.sort(names, comparator);
+    }
+
+    return names;
+  }
+
+  private static void scheduleRemoval(File folder) throws IOException
+  {
+    File marker = new File(folder, REMOVE_MARKER);
+    marker.createNewFile();
+  }
+}
diff --git a/org.eclipse.userstorage.releng/src/Version.java b/org.eclipse.userstorage.releng/src/Version.java
new file mode 100644
index 0000000..6eddeed
--- /dev/null
+++ b/org.eclipse.userstorage.releng/src/Version.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+
+/**
+ * @author Eike Stepper
+ */
+public final class Version implements Comparable<Version>
+{
+  private final Integer major;
+
+  private final Integer minor;
+
+  private final Integer micro;
+
+  public Version(String name)
+  {
+    for (int i = 0; i < name.length(); i++)
+    {
+      char c = name.charAt(i);
+      if (!Character.isDigit(c) && c != '.')
+      {
+        name = name.substring(0, i);
+        break;
+      }
+    }
+
+    String[] segments = name.split("\\.");
+    major = Integer.parseInt(segments[0]);
+    minor = Integer.parseInt(segments[1]);
+    micro = Integer.parseInt(segments[2]);
+  }
+
+  public boolean isGreaterThan(Version other)
+  {
+    return compareTo(other) > 0;
+  }
+
+  @Override
+  public int compareTo(Version o)
+  {
+    int result = major.compareTo(o.major);
+    if (result == 0)
+    {
+      result = minor.compareTo(o.minor);
+      if (result == 0)
+      {
+        result = micro.compareTo(o.micro);
+      }
+    }
+
+    return result;
+  }
+
+  @Override
+  public String toString()
+  {
+    return major + "." + minor + "." + micro;
+  }
+}
diff --git a/org.eclipse.userstorage.sdk-feature/.project b/org.eclipse.userstorage.sdk-feature/.project
new file mode 100644
index 0000000..ecb2f23
--- /dev/null
+++ b/org.eclipse.userstorage.sdk-feature/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.userstorage.sdk-feature</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.pde.FeatureBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.FeatureNature</nature>
+	</natures>
+	<filteredResources>
+		<filter>
+			<id>1396938000000</id>
+			<name></name>
+			<type>10</type>
+			<matcher>
+				<id>org.eclipse.ui.ide.multiFilter</id>
+				<arguments>1.0-projectRelativePath-matches-true-false-target</arguments>
+			</matcher>
+		</filter>
+	</filteredResources>
+</projectDescription>
diff --git a/org.eclipse.userstorage.sdk-feature/.settings/org.eclipse.ltk.core.refactoring.prefs b/org.eclipse.userstorage.sdk-feature/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..2e4a92e
--- /dev/null
+++ b/org.eclipse.userstorage.sdk-feature/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Mon Jul 11 16:02:05 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/org.eclipse.userstorage.sdk-feature/build.properties b/org.eclipse.userstorage.sdk-feature/build.properties
new file mode 100644
index 0000000..88e19fe
--- /dev/null
+++ b/org.eclipse.userstorage.sdk-feature/build.properties
@@ -0,0 +1,16 @@
+# Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+# 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:
+#    Eike Stepper - initial API and implementation
+
+# UpdateTrigger = 20150923-1142
+
+bin.includes = feature.xml,\
+               feature.properties
+
+generateSourceReferences = true
+src.includes = pom.xml
diff --git a/org.eclipse.userstorage.sdk-feature/feature.properties b/org.eclipse.userstorage.sdk-feature/feature.properties
new file mode 100644
index 0000000..3c8da6f
--- /dev/null
+++ b/org.eclipse.userstorage.sdk-feature/feature.properties
@@ -0,0 +1,11 @@
+# Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+# 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:
+#    Eike Stepper - initial API and implementation
+
+featureName = Eclipse User Storage SDK
+description = Contains the runtime plugins (core and UI) and source plugins for accessing the Eclipse User Storage Service.
diff --git a/org.eclipse.userstorage.sdk-feature/feature.xml b/org.eclipse.userstorage.sdk-feature/feature.xml
new file mode 100644
index 0000000..c609ef2
--- /dev/null
+++ b/org.eclipse.userstorage.sdk-feature/feature.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+  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:
+    Eike Stepper - initial API and implementation
+-->
+<feature
+      id="org.eclipse.userstorage.sdk"
+      label="%featureName"
+      version="1.0.0.qualifier"
+      provider-name="%providerName"
+      license-feature="org.eclipse.userstorage.license"
+      license-feature-version="0.0.0">
+
+   <description>
+      %description
+   </description>
+
+   <copyright url="%copyrightURL">
+      %copyright
+   </copyright>
+
+   <license url="%licenseURL">
+      %license
+   </license>
+
+   <includes
+         id="org.eclipse.userstorage"
+         version="0.0.0"/>
+
+   <plugin
+         id="org.eclipse.userstorage.sdk"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.userstorage.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.userstorage.tests.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.userstorage.ui.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+</feature>
diff --git a/org.eclipse.userstorage.sdk-feature/pom.xml b/org.eclipse.userstorage.sdk-feature/pom.xml
new file mode 100644
index 0000000..02236bf
--- /dev/null
+++ b/org.eclipse.userstorage.sdk-feature/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+  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:
+    Eike Stepper - initial API and implementation
+-->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.eclipse.userstorage</groupId>
+    <artifactId>parent</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+  <groupId>org.eclipse.userstorage.features</groupId>
+  <artifactId>org.eclipse.userstorage.sdk</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>eclipse-feature</packaging>
+</project>
diff --git a/org.eclipse.userstorage.sdk/.project b/org.eclipse.userstorage.sdk/.project
new file mode 100644
index 0000000..d9abd37
--- /dev/null
+++ b/org.eclipse.userstorage.sdk/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.userstorage.sdk</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+	</natures>
+  <filteredResources>
+    <filter>
+      <id>1396938000000</id>
+      <name></name>
+      <type>10</type>
+      <matcher>
+        <id>org.eclipse.ui.ide.multiFilter</id>
+        <arguments>1.0-projectRelativePath-matches-true-false-target</arguments>
+      </matcher>
+    </filter>
+  </filteredResources>
+</projectDescription>
diff --git a/org.eclipse.userstorage.sdk/.settings/org.eclipse.ltk.core.refactoring.prefs b/org.eclipse.userstorage.sdk/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..864e30f
--- /dev/null
+++ b/org.eclipse.userstorage.sdk/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Thu Feb 04 09:44:24 CET 2010
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/org.eclipse.userstorage.sdk/.settings/org.eclipse.pde.prefs b/org.eclipse.userstorage.sdk/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..2683a79
--- /dev/null
+++ b/org.eclipse.userstorage.sdk/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,32 @@
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.encodings=2
+compilers.p.build.java.compiler=2
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=2
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=2
+compilers.p.discouraged-class=2
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=1
+compilers.p.missing-version-import-package=1
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=2
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=0
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+eclipse.preferences.version=1
diff --git a/org.eclipse.userstorage.sdk/META-INF/MANIFEST.MF b/org.eclipse.userstorage.sdk/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..df64e37
--- /dev/null
+++ b/org.eclipse.userstorage.sdk/META-INF/MANIFEST.MF
@@ -0,0 +1,9 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.userstorage.sdk;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
diff --git a/org.eclipse.userstorage.sdk/about.html b/org.eclipse.userstorage.sdk/about.html
new file mode 100644
index 0000000..d35d5ae
--- /dev/null
+++ b/org.eclipse.userstorage.sdk/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>June 5, 2007</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
diff --git a/org.eclipse.userstorage.sdk/about.ini b/org.eclipse.userstorage.sdk/about.ini
new file mode 100644
index 0000000..c6eaecb
--- /dev/null
+++ b/org.eclipse.userstorage.sdk/about.ini
@@ -0,0 +1,18 @@
+# Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+# 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:
+#    Eike Stepper - initial API and implementation
+
+# Property "aboutText" contains blurb for "About" dialog (translated)
+aboutText=%featureText
+
+# Property "featureImage" contains path to feature image (32x32)
+featureImage=eclipse32.png
+
+# Property "appName" contains name of the application (translated)
+appName=%featureName
+
diff --git a/org.eclipse.userstorage.sdk/about.mappings b/org.eclipse.userstorage.sdk/about.mappings
new file mode 100644
index 0000000..4b420dd
--- /dev/null
+++ b/org.eclipse.userstorage.sdk/about.mappings
@@ -0,0 +1,3 @@
+0=${build.id}
+1=${git.branch}
+2=${git.commit}
diff --git a/org.eclipse.userstorage.sdk/about.properties b/org.eclipse.userstorage.sdk/about.properties
new file mode 100644
index 0000000..44580ff
--- /dev/null
+++ b/org.eclipse.userstorage.sdk/about.properties
@@ -0,0 +1,17 @@
+# Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+# 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:
+#    Eike Stepper - initial API and implementation
+
+featureName = Eclipse User Storage SDK
+featureText = Eclipse User Storage SDK\n\
+\n\
+Version: {featureVersion} (build {0})\n\
+Commit: {2} (branch {1})\n\
+\n\
+Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others. All rights reserved.\n\
+Visit http://www.eclipse.org/userstorage for more information.
diff --git a/org.eclipse.userstorage.sdk/build.properties b/org.eclipse.userstorage.sdk/build.properties
new file mode 100644
index 0000000..a652f83
--- /dev/null
+++ b/org.eclipse.userstorage.sdk/build.properties
@@ -0,0 +1,9 @@
+bin.includes = META-INF/,\
+               about.html,\
+               about.ini,\
+               about.mappings,\
+               about.properties,\
+               eclipse32.png,\
+               plugin.properties
+src.includes = about.html,\
+               pom.xml
diff --git a/org.eclipse.userstorage.sdk/eclipse32.png b/org.eclipse.userstorage.sdk/eclipse32.png
new file mode 100644
index 0000000..bf85680
--- /dev/null
+++ b/org.eclipse.userstorage.sdk/eclipse32.png
Binary files differ
diff --git a/org.eclipse.userstorage.sdk/plugin.properties b/org.eclipse.userstorage.sdk/plugin.properties
new file mode 100644
index 0000000..907d743
--- /dev/null
+++ b/org.eclipse.userstorage.sdk/plugin.properties
@@ -0,0 +1,11 @@
+# Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+# 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:
+#    Eike Stepper - initial API and implementation
+
+pluginName = Eclipse User Storage SDK
+providerName = Eclipse.org
diff --git a/org.eclipse.userstorage.sdk/pom.xml b/org.eclipse.userstorage.sdk/pom.xml
new file mode 100644
index 0000000..984762f
--- /dev/null
+++ b/org.eclipse.userstorage.sdk/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+  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:
+    Eike Stepper - initial API and implementation
+-->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.eclipse.userstorage</groupId>
+    <artifactId>parent</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+  <groupId>org.eclipse.userstorage</groupId>
+  <artifactId>org.eclipse.userstorage.sdk</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>eclipse-plugin</packaging>
+</project>
diff --git a/org.eclipse.userstorage.site/.project b/org.eclipse.userstorage.site/.project
new file mode 100644
index 0000000..fc93b4b
--- /dev/null
+++ b/org.eclipse.userstorage.site/.project
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.userstorage.site</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+	</buildSpec>
+	<natures>
+	</natures>
+	<filteredResources>
+		<filter>
+			<id>1396938000000</id>
+			<name></name>
+			<type>10</type>
+			<matcher>
+				<id>org.eclipse.ui.ide.multiFilter</id>
+				<arguments>1.0-projectRelativePath-matches-true-false-target</arguments>
+			</matcher>
+		</filter>
+	</filteredResources>
+</projectDescription>
diff --git a/org.eclipse.userstorage.site/category.xml b/org.eclipse.userstorage.site/category.xml
new file mode 100644
index 0000000..379c845
--- /dev/null
+++ b/org.eclipse.userstorage.site/category.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<site>
+   <feature id="org.eclipse.userstorage" version="0.0.0">
+      <category name="org.eclipse.userstorage.category"/>
+   </feature>
+   <feature id="org.eclipse.userstorage.sdk" version="0.0.0">
+      <category name="org.eclipse.userstorage.category"/>
+   </feature>
+   <bundle id="org.eclipse.userstorage.tests" version="1.0.0.qualifier">
+      <category name="org.eclipse.userstorage.category"/>
+   </bundle>
+   <category-def name="org.eclipse.userstorage.category" label="User Storage"/>
+</site>
diff --git a/org.eclipse.userstorage.site/pom.xml b/org.eclipse.userstorage.site/pom.xml
new file mode 100644
index 0000000..cb72cb3
--- /dev/null
+++ b/org.eclipse.userstorage.site/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+  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:
+    Eike Stepper - initial API and implementation
+-->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.eclipse.userstorage</groupId>
+    <artifactId>parent</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+  <groupId>org.eclipse.userstorage</groupId>
+  <artifactId>org.eclipse.userstorage.site</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>eclipse-repository</packaging>
+</project>
diff --git a/org.eclipse.userstorage.tests/.classpath b/org.eclipse.userstorage.tests/.classpath
new file mode 100644
index 0000000..ad32c83
--- /dev/null
+++ b/org.eclipse.userstorage.tests/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<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="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.userstorage.tests/.gitignore b/org.eclipse.userstorage.tests/.gitignore
new file mode 100644
index 0000000..b0b57f5
--- /dev/null
+++ b/org.eclipse.userstorage.tests/.gitignore
@@ -0,0 +1,2 @@
+userstorage.credentials
+user.txt
diff --git a/org.eclipse.userstorage.tests/.project b/org.eclipse.userstorage.tests/.project
new file mode 100644
index 0000000..78104fb
--- /dev/null
+++ b/org.eclipse.userstorage.tests/.project
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.userstorage.tests</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+	</natures>
+	<filteredResources>
+		<filter>
+			<id>1396938000000</id>
+			<name></name>
+			<type>10</type>
+			<matcher>
+				<id>org.eclipse.ui.ide.multiFilter</id>
+				<arguments>1.0-projectRelativePath-matches-true-false-target</arguments>
+			</matcher>
+		</filter>
+	</filteredResources>
+</projectDescription>
diff --git a/org.eclipse.userstorage.tests/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.userstorage.tests/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..bb20789
--- /dev/null
+++ b/org.eclipse.userstorage.tests/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,410 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+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.doc.comment.support=enabled
+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=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+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=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning
+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.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=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=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+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.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=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=warning
+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=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.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled
+org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,HIGH,LOW,LOW,LOW,LOW,LOW
+org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX,PERF,MEM,POLISH,@generated NOT,@ADDED
+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=1
+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=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_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=false
+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=160
+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=2
+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=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=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=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=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=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=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=do not 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=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_lambda_arrow=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=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=do not 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=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=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not 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_lambda_arrow=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=do not 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=160
+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=2
+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
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/org.eclipse.userstorage.tests/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.userstorage.tests/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..7c1dd68
--- /dev/null
+++ b/org.eclipse.userstorage.tests/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,125 @@
+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=true
+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_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.insert_inferred_type_arguments=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=true
+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=false
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+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_anonymous_class_creation=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup.use_type_arguments=false
+cleanup_profile=_UserStorage
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_UserStorage
+formatter_settings_version=12
+org.eclipse.jdt.ui.exception.name=ex
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=org.eclipse.userstorage;org.eclipse.emf;org.eclipse;com;org;javax;java;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="false" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment"/><template autoinsert\="false" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment"/><template autoinsert\="false" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment"/><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/*\r\n * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * which accompanies this distribution, and is available at\r\n * http\://www.eclipse.org/legal/epl-v10.html\r\n * \r\n * Contributors\:\r\n *    Eike Stepper - initial API and implementation\r\n */</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\r\n * @author Eike Stepper\r\n */</template><template autoinsert\="false" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment"/><template autoinsert\="false" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment"/><template autoinsert\="false" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment"/><template autoinsert\="false" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment"/><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\r\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\r\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\r\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\r\n</template><template autoinsert\="false" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">${exception_var}.printStackTrace();</template><template autoinsert\="false" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">${body_statement}</template><template autoinsert\="false" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+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=false
+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=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+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=true
+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=true
+sp_cleanup.remove_unused_imports=true
+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=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/org.eclipse.userstorage.tests/.settings/org.eclipse.ltk.core.refactoring.prefs b/org.eclipse.userstorage.tests/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..864e30f
--- /dev/null
+++ b/org.eclipse.userstorage.tests/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Thu Feb 04 09:44:24 CET 2010
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/org.eclipse.userstorage.tests/.settings/org.eclipse.pde.prefs b/org.eclipse.userstorage.tests/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..2683a79
--- /dev/null
+++ b/org.eclipse.userstorage.tests/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,32 @@
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.encodings=2
+compilers.p.build.java.compiler=2
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=2
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=2
+compilers.p.discouraged-class=2
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=1
+compilers.p.missing-version-import-package=1
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=2
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=0
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+eclipse.preferences.version=1
diff --git a/org.eclipse.userstorage.tests/Example.launch b/org.eclipse.userstorage.tests/Example.launch
new file mode 100644
index 0000000..520dcc3
--- /dev/null
+++ b/org.eclipse.userstorage.tests/Example.launch
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/Example.java"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="1"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.userstorage.tests.Example"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.userstorage.tests"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dorg.eclipse.userstorage.credentialsProvider=org.eclipse.userstorage.tests.util.FixedCredentialsProvider&#13;&#10;-Dorg.eclipse.userstorage.session.debug=true"/>
+</launchConfiguration>
diff --git a/org.eclipse.userstorage.tests/JSONTests.launch b/org.eclipse.userstorage.tests/JSONTests.launch
new file mode 100644
index 0000000..114a566
--- /dev/null
+++ b/org.eclipse.userstorage.tests/JSONTests.launch
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/JSONTests.java"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="1"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
+<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
+<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
+<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.userstorage.tests.JSONTests"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.userstorage.tests"/>
+</launchConfiguration>
diff --git a/org.eclipse.userstorage.tests/META-INF/MANIFEST.MF b/org.eclipse.userstorage.tests/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..680e099
--- /dev/null
+++ b/org.eclipse.userstorage.tests/META-INF/MANIFEST.MF
@@ -0,0 +1,23 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.userstorage.tests
+Bundle-Version: 1.0.0.qualifier
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.0.0,4.0.0)",
+ org.apache.httpcomponents.httpclient;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
+ org.apache.httpcomponents.httpcore;bundle-version="[4.0.0,5.0.0)";visibility:=reexport,
+ org.eclipse.userstorage;bundle-version="[1.0.0,2.0.0)";visibility:=reexport,
+ org.eclipse.jetty.server;bundle-version="[9.0.0,10.0.0)";visibility:=reexport,
+ org.eclipse.jetty.servlet;bundle-version="[9.0.0,10.0.0)";visibility:=reexport,
+ org.eclipse.jetty.http;bundle-version="[9.0.0,10.0.0)";visibility:=reexport,
+ org.eclipse.jetty.io;bundle-version="[9.0.0,10.0.0)";visibility:=reexport,
+ org.eclipse.jetty.util;bundle-version="[9.0.0,10.0.0)";visibility:=reexport,
+ javax.servlet;bundle-version="[3.0.0,4.0.0)";visibility:=reexport,
+ org.junit;bundle-version="[4.11.0,5.0.0)";visibility:=reexport
+Export-Package: org.eclipse.userstorage.tests;version="1.0.0";x-internal:=true,
+ org.eclipse.userstorage.tests.util;version="1.0.0";x-internal:=true
+Eclipse-RegisterBuddy: org.eclipse.userstorage
diff --git "a/org.eclipse.userstorage.tests/StorageTests \050Local\051.launch" "b/org.eclipse.userstorage.tests/StorageTests \050Local\051.launch"
new file mode 100644
index 0000000..aa91ff6
--- /dev/null
+++ "b/org.eclipse.userstorage.tests/StorageTests \050Local\051.launch"
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/StorageTests.java"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="1"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
+<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
+<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
+<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.userstorage.tests.StorageTests"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.userstorage.tests"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dorg.eclipse.userstorage.credentialsProvider=org.eclipse.userstorage.tests.util.FixedCredentialsProvider&#13;&#10;-Dorg.eclipse.userstorage.session.debug=true&#13;&#10;-Dorg.eclipse.userstorage.tests.server.debug=false"/>
+</launchConfiguration>
diff --git "a/org.eclipse.userstorage.tests/StorageTests \050Remote\051.launch" "b/org.eclipse.userstorage.tests/StorageTests \050Remote\051.launch"
new file mode 100644
index 0000000..aaf6db3
--- /dev/null
+++ "b/org.eclipse.userstorage.tests/StorageTests \050Remote\051.launch"
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/StorageTests.java"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="1"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
+<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
+<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
+<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.userstorage.tests.StorageTests"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.userstorage.tests"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-DXXXorg.eclipse.userstorage.credentialsProvider=org.eclipse.userstorage.tests.util.TestCredentialsProvider&#13;&#10;-Dorg.eclipse.userstorage.credentialsProvider=org.eclipse.userstorage.tests.util.FixedCredentialsProvider&#13;&#10;-Dorg.eclipse.userstorage.session.debug=true&#13;&#10;-Dorg.eclipse.userstorage.tests.remote=true"/>
+</launchConfiguration>
diff --git a/org.eclipse.userstorage.tests/USSServer.launch b/org.eclipse.userstorage.tests/USSServer.launch
new file mode 100644
index 0000000..236608e
--- /dev/null
+++ b/org.eclipse.userstorage.tests/USSServer.launch
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/USSServer.java"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="1"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.userstorage.tests.util.USSServer"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.userstorage.tests"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dorg.eclipse.userstorage.tests.server.debug=true"/>
+</launchConfiguration>
diff --git a/org.eclipse.userstorage.tests/about.html b/org.eclipse.userstorage.tests/about.html
new file mode 100644
index 0000000..d35d5ae
--- /dev/null
+++ b/org.eclipse.userstorage.tests/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>June 5, 2007</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
diff --git a/org.eclipse.userstorage.tests/build.properties b/org.eclipse.userstorage.tests/build.properties
new file mode 100644
index 0000000..99233b4
--- /dev/null
+++ b/org.eclipse.userstorage.tests/build.properties
@@ -0,0 +1,12 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               about.html,\
+               plugin.properties
+src.includes = about.html,\
+               pom.xml,\
+               StorageTests (Local).launch,\
+               StorageTests (Remote).launch,\
+               JSONTests.launch,\
+               Example.launch
diff --git a/org.eclipse.userstorage.tests/plugin.properties b/org.eclipse.userstorage.tests/plugin.properties
new file mode 100644
index 0000000..d5e1dfa
--- /dev/null
+++ b/org.eclipse.userstorage.tests/plugin.properties
@@ -0,0 +1,11 @@
+# Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+# 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:
+#    Eike Stepper - initial API and implementation
+
+pluginName = Eclipse User Storage Tests
+providerName = Eclipse.org
diff --git a/org.eclipse.userstorage.tests/pom.xml b/org.eclipse.userstorage.tests/pom.xml
new file mode 100644
index 0000000..730a468
--- /dev/null
+++ b/org.eclipse.userstorage.tests/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+  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:
+    Eike Stepper - initial API and implementation
+-->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.eclipse.userstorage</groupId>
+    <artifactId>parent</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+  <groupId>org.eclipse.userstorage</groupId>
+  <artifactId>org.eclipse.userstorage.tests</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>eclipse-test-plugin</packaging>
+</project>
diff --git a/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/AbstractTest.java b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/AbstractTest.java
new file mode 100644
index 0000000..3398e07
--- /dev/null
+++ b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/AbstractTest.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.tests;
+
+import org.eclipse.userstorage.internal.util.IOUtil;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.hamcrest.CoreMatchers;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.TestName;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class AbstractTest extends CoreMatchers
+{
+  private static final String[] FILTERS = { //
+      "org.eclipse.jdt.internal.junit.runner.", //
+      "org.eclipse.jdt.internal.junit.ui.", //
+      "org.eclipse.jdt.internal.junit4.runner.", //
+      "org.junit.", //
+      "sun.reflect.", //
+      "java.lang.reflect.Method.invoke(", //
+      "junit.framework.Assert", //
+      "junit.framework.TestCase", //
+      "junit.framework.TestResult", //
+      "junit.framework.TestResult$1", //
+      "junit.framework.TestSuite", //
+  };
+
+  private static final PrintStream LOG = System.out;
+
+  public static final IProgressMonitor LOGGER = new IProgressMonitor()
+  {
+    private String message = "";
+
+    @Override
+    public void beginTask(String name, int totalWork)
+    {
+      filter(name);
+    }
+
+    @Override
+    public void done()
+    {
+    }
+
+    @Override
+    public void internalWorked(double work)
+    {
+    }
+
+    @Override
+    public boolean isCanceled()
+    {
+      return false;
+    }
+
+    @Override
+    public void setCanceled(boolean value)
+    {
+    }
+
+    @Override
+    public void setTaskName(String name)
+    {
+      filter(name);
+    }
+
+    @Override
+    public void subTask(String name)
+    {
+      filter(name);
+    }
+
+    @Override
+    public void worked(int work)
+    {
+    }
+
+    private void filter(String message)
+    {
+      if (message == null)
+      {
+        message = "";
+      }
+
+      if (!message.equals(this.message))
+      {
+        log(message);
+      }
+
+      this.message = message;
+    }
+  };
+
+  @Rule
+  public final TestWatcher failurePrinter = new FailurePrinter();
+
+  @Rule
+  public final TestName testName = new TestName();
+
+  @Before
+  public void setUp() throws Exception
+  {
+    log("=========================================================================================================================\n" //
+        + testName.getMethodName() + "\n" //
+        + "=========================================================================================================================");
+  }
+
+  @After
+  public void tearDown() throws Exception
+  {
+    log();
+    LOGGER.setTaskName(null);
+  }
+
+  public static void log()
+  {
+    LOG.println();
+  }
+
+  public static void log(Object object)
+  {
+    if (object instanceof Throwable)
+    {
+      Throwable ex = (Throwable)object;
+      printStackTrace(ex);
+    }
+    else
+    {
+      LOG.println(object);
+    }
+  }
+
+  public static void printStackTrace(Throwable ex)
+  {
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    ex.printStackTrace(new PrintStream(baos));
+
+    BufferedReader reader = new BufferedReader(new InputStreamReader(IOUtil.streamUTF(baos.toByteArray())));
+    String line;
+    StringBuilder builder = new StringBuilder();
+
+    try
+    {
+      LOOP: while ((line = reader.readLine()) != null)
+      {
+        for (int i = 0; i < FILTERS.length; i++)
+        {
+          String filter = FILTERS[i];
+          if (line.trim().startsWith("at " + filter))
+          {
+            continue LOOP;
+          }
+        }
+
+        builder.append(line);
+        builder.append('\n');
+      }
+    }
+    catch (IOException ignore)
+    {
+      // Should not happen.
+      //$FALL-THROUGH$
+    }
+
+    System.err.println(builder);
+  }
+
+  public static void fail(String message) throws AssertionError
+  {
+    throw new AssertionError(message);
+  }
+
+  public static org.hamcrest.Matcher<java.lang.Object> isNull()
+  {
+    return org.hamcrest.core.IsNull.nullValue();
+  }
+
+  public static org.hamcrest.Matcher<java.lang.Object> isNotNull()
+  {
+    return org.hamcrest.core.IsNull.notNullValue();
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private static final class FailurePrinter extends TestWatcher
+  {
+    @Override
+    protected void failed(Throwable ex, Description description)
+    {
+      printStackTrace(ex);
+    }
+  }
+}
diff --git a/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/Example.java b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/Example.java
new file mode 100644
index 0000000..b8e41af
--- /dev/null
+++ b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/Example.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.tests;
+
+import org.eclipse.userstorage.IBlob;
+import org.eclipse.userstorage.IStorage;
+import org.eclipse.userstorage.StorageFactory;
+import org.eclipse.userstorage.internal.util.IOUtil;
+import org.eclipse.userstorage.util.FileStorageCache;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author Eike Stepper
+ */
+public class Example
+{
+  public static void main(String[] args) throws IOException
+  {
+    IStorage storage = StorageFactory.DEFAULT.create("pDKTqBfDuNxlAKydhEwxBZPxa4q", new FileStorageCache());
+
+    IBlob blob = storage.getBlob("test_blob");
+    blob.setContentsUTF("A short UTF-8 string value");
+
+    InputStream in = blob.getContents();
+    IOUtil.copy(in, new FileOutputStream("user.txt"));
+    IOUtil.close(in);
+  }
+}
diff --git a/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/JSONTests.java b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/JSONTests.java
new file mode 100644
index 0000000..97d872b
--- /dev/null
+++ b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/JSONTests.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.tests;
+
+import org.eclipse.userstorage.internal.util.IOUtil;
+import org.eclipse.userstorage.internal.util.JSONUtil;
+
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public final class JSONTests extends AbstractTest
+{
+  @Test
+  public void testBuildObject() throws Exception
+  {
+    Map<String, Object> object = new LinkedHashMap<String, Object>();
+    object.put("blob_key", "user_xml");
+    object.put("blob_namespace", "org_eclipse_userstorage");
+    object.put("blob_hash", "8e6706262c374adacd1048c5497e03cb4c5ea585c07d5e36c15150d4f7a40812");
+    object.put("created", 1445368225);
+    object.put("changed", 1445368225);
+    object.put("blob_value", new FileInputStream("about.html"));
+
+    InputStream json = JSONUtil.build(object);
+    dump(json);
+    IOUtil.close(json);
+  }
+
+  @Test
+  public void testParseObject() throws Exception
+  {
+    String response = "{\"blob_key\":\"user_xml\"," //
+        + "\"blob_namespace\":\"org_eclipse_userstorage\"," //
+        + "\"blob_hash\":\"8e6706262c374adacd1048c5497e03cb4c5ea585c07d5e36c15150d4f7a40812\"," //
+        + "\"created\":\"1445368225\"," //
+        + "\"changed\":\"1445368225\"," //
+        + "\"blob_value\":\"PHhtbD48cGFja2FnZSBuYW1lPSJFY2xpcHNlIENsYXNzaWMgMy42LjAiIGRvd25sb2FkQ291bnQ9IjYwNzY2NCIgdXJsPSIvZG93bmxvYWRzL3BhY2thZ2VzL2VjbGlwc2UtY2xhc3NpYy0zNjAvaGVsaW9zciIgZG93bmxvYWR1cmw9Imh0dHA6Ly93d3cuZWNsaXBzZS5vcmcvZG93bmxvYWRzL2Rvd25sb2FkLnBocD9maWxlPS9lY2xpcHNlL2Rvd25sb2Fkcy9kcm9wcy9SLTMuNi0yMDEwMDYwODA5MTEvZWNsaXBzZS1TREstMy42LW1hY29zeC1jYXJib24udGFyLmd6IiBkb3dubG9hZHVybDY0PSIiIHNpemU9IjE2OSBNQiIgaWNvbj0iaHR0cDovL3d3dy5lY2xpcHNlLm9yZy9kb3dubG9hZHMvaW1hZ2VzL2NsYXNzaWMyLmpwZyIvPiAKPC94bWw+\"}";
+
+    Map<String, Object> object = JSONUtil.parse(IOUtil.streamUTF(response), "blob_value");
+    JSONUtil.dump(object);
+
+    System.out.println();
+    InputStream stream = (InputStream)object.get("blob_value");
+    dump(stream);
+  }
+
+  @Test
+  public void testBuildParse() throws Exception
+  {
+    Map<String, Object> objectIn = new LinkedHashMap<String, Object>();
+    objectIn.put("blob_key", "user_xml");
+    objectIn.put("blob_namespace", "org_eclipse_userstorage");
+    objectIn.put("blob_hash", "8e6706262c374adacd1048c5497e03cb4c5ea585c07d5e36c15150d4f7a40812");
+    objectIn.put("created", 1445368225);
+    objectIn.put("changed", 1445368225);
+    objectIn.put("blob_value", new FileInputStream("about.html"));
+
+    InputStream json = JSONUtil.build(objectIn);
+
+    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+    copy(json, buffer);
+    IOUtil.close(json);
+
+    Map<String, Object> objectOut = JSONUtil.parse(IOUtil.streamUTF(buffer.toByteArray()), "blob_value");
+    JSONUtil.dump(objectOut);
+    System.out.println();
+
+    InputStream stream = (InputStream)objectOut.get("blob_value");
+    dump(stream);
+  }
+
+  @Test
+  public void testParseArray() throws Exception
+  {
+    String response = "[{\"key\":\"user_xml\",\"application_token\":\"org_eclipse_oomph\",\"etag\":\"8e6706262c374adacd1048c5497e03cb4c5ea585c07d5e36c15150d4f7a40812\",\"created\":1445368225,\"changed\":1445368225, \"url\":\"https://api.eclipse.org/api/blob/:namespace/:key\" }"
+        + ",{\"key\":\"pref_xml\",\"application_token\":\"org_eclipse_oomph\",\"etag\":\"8e6706262c374adacd1048c5497e03cb4c5ea585c07d5e36c15150d4f7a40812\",\"created\":1445368264,\"changed\":1445368264, \"url\":\"https://api.eclipse.org/api/blob/:namespace/:key\" }]";
+
+    List<Object> array = JSONUtil.parse(IOUtil.streamUTF(response), null);
+    JSONUtil.dump(array);
+  }
+
+  @Test
+  public void testParseArray2() throws Exception
+  {
+    String objectJSON = "{\"blob_key\":\"user_xml\"," //
+        + "\"blob_namespace\":\"org_eclipse_userstorage\"," //
+        + "\"blob_hash\":\"8e6706262c374adacd1048c5497e03cb4c5ea585c07d5e36c15150d4f7a40812\"," //
+        + "\"created\":\"1445368225\"," //
+        + "\"changed\":\"1445368225\"," //
+        + "\"blob_value\":\"PHhtbD48cGFja2FnZSBuYW1lPSJFY2xpcHNlIENsYXNzaWMgMy42LjAiIGRvd25sb2FkQ291bnQ9IjYwNzY2NCIgdXJsPSIvZG93bmxvYWRzL3BhY2thZ2VzL2VjbGlwc2UtY2xhc3NpYy0zNjAvaGVsaW9zciIgZG93bmxvYWR1cmw9Imh0dHA6Ly93d3cuZWNsaXBzZS5vcmcvZG93bmxvYWRzL2Rvd25sb2FkLnBocD9maWxlPS9lY2xpcHNlL2Rvd25sb2Fkcy9kcm9wcy9SLTMuNi0yMDEwMDYwODA5MTEvZWNsaXBzZS1TREstMy42LW1hY29zeC1jYXJib24udGFyLmd6IiBkb3dubG9hZHVybDY0PSIiIHNpemU9IjE2OSBNQiIgaWNvbj0iaHR0cDovL3d3dy5lY2xpcHNlLm9yZy9kb3dubG9hZHMvaW1hZ2VzL2NsYXNzaWMyLmpwZyIvPiAKPC94bWw+\"}";
+
+    String arrayJSON = "[" + objectJSON + ", true, false, null, [1,2,3,4,5,6,7,8,9], " + objectJSON + "]";
+
+    Object array = JSONUtil.parse(IOUtil.streamUTF(arrayJSON), "blob_value");
+    JSONUtil.dump(array);
+  }
+
+  private static void dump(InputStream stream) throws IOException
+  {
+    int c;
+    while ((c = stream.read()) != -1)
+    {
+      System.out.print((char)c);
+    }
+
+    System.out.println();
+  }
+
+  private static void copy(InputStream source, OutputStream target) throws IOException
+  {
+    int c;
+    while ((c = source.read()) != -1)
+    {
+      target.write(c);
+    }
+  }
+}
diff --git a/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/StorageTests.java b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/StorageTests.java
new file mode 100644
index 0000000..6899ba0
--- /dev/null
+++ b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/StorageTests.java
@@ -0,0 +1,840 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.tests;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.eclipse.userstorage.IBlob;
+import org.eclipse.userstorage.IStorage;
+import org.eclipse.userstorage.StorageFactory;
+import org.eclipse.userstorage.internal.Session;
+import org.eclipse.userstorage.internal.StorageService;
+import org.eclipse.userstorage.internal.StorageServiceRegistry;
+import org.eclipse.userstorage.internal.util.IOUtil;
+import org.eclipse.userstorage.spi.Credentials;
+import org.eclipse.userstorage.tests.util.ClientFixture;
+import org.eclipse.userstorage.tests.util.ClientFixture.TestCache;
+import org.eclipse.userstorage.tests.util.FixedCredentialsProvider;
+import org.eclipse.userstorage.tests.util.ServerFixture;
+import org.eclipse.userstorage.tests.util.ServerFixture.BlobInfo;
+import org.eclipse.userstorage.tests.util.USSServer;
+import org.eclipse.userstorage.util.BadApplicationTokenException;
+import org.eclipse.userstorage.util.BadKeyException;
+import org.eclipse.userstorage.util.ConflictException;
+import org.eclipse.userstorage.util.NotFoundException;
+import org.eclipse.userstorage.util.ProtocolException;
+
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public final class StorageTests extends AbstractTest
+{
+  /**
+   * The test application's token.
+   */
+  public static final String APPLICATION_TOKEN = "pDKTqBfDuNxlAKydhEwxBZPxa4q";
+
+  private static final String KEY = "test_blob";
+
+  private static final String WRONG_ETAG = "wrong_etag";
+
+  private ServerFixture serverFixture;
+
+  private ClientFixture clientFixture;
+
+  private StorageFactory factory;
+
+  private TestCache cache;
+
+  @Override
+  public void setUp() throws Exception
+  {
+    super.setUp();
+    StorageServiceRegistry.INSTANCE.stop();
+    StorageServiceRegistry.INSTANCE.start();
+
+    serverFixture = new ServerFixture(APPLICATION_TOKEN);
+    clientFixture = new ClientFixture(serverFixture);
+    factory = clientFixture.getFactory();
+    cache = clientFixture.getCache();
+  }
+
+  @Override
+  public void tearDown() throws Exception
+  {
+    if (clientFixture != null)
+    {
+      clientFixture.dispose();
+      clientFixture = null;
+    }
+
+    if (serverFixture != null)
+    {
+      serverFixture.dispose();
+      serverFixture = null;
+    }
+
+    super.tearDown();
+  }
+
+  @Test
+  public void testApplicationToken() throws Exception
+  {
+    try
+    {
+      factory.create(null);
+      fail("BadApplicationTokenException expected");
+    }
+    catch (BadApplicationTokenException expected)
+    {
+      // SUCCESS
+    }
+
+    try
+    {
+      factory.create("aaaa"); // Too short.
+      fail("BadApplicationTokenException expected");
+    }
+    catch (BadApplicationTokenException expected)
+    {
+      // SUCCESS
+    }
+
+    try
+    {
+      factory.create("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"); // Too long.
+      fail("BadApplicationTokenException expected");
+    }
+    catch (BadApplicationTokenException expected)
+    {
+      // SUCCESS
+    }
+
+    try
+    {
+      factory.create("1aaaaaaaaa"); // Too long.
+      fail("BadApplicationTokenException expected");
+    }
+    catch (BadApplicationTokenException expected)
+    {
+      // SUCCESS
+    }
+
+    factory.create("aaaaa"); // Just short enough.
+    factory.create("aaaaaaaaaaaaaaaaaaaaaaaaaaa"); // Just long enough.
+  }
+
+  @Test
+  public void testKey() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+
+    try
+    {
+      storage.getBlob(null);
+      fail("BadKeyException expected");
+    }
+    catch (BadKeyException expected)
+    {
+      // SUCCESS
+    }
+
+    try
+    {
+      storage.getBlob("aaaa"); // Too short.
+      fail("BadKeyException expected");
+    }
+    catch (BadKeyException expected)
+    {
+      // SUCCESS
+    }
+
+    try
+    {
+      storage.getBlob("aaaaaaaaaaaaaaaaaaaaaaaaaaa"); // Too long.
+      fail("BadKeyException expected");
+    }
+    catch (BadKeyException expected)
+    {
+      // SUCCESS
+    }
+
+    try
+    {
+      storage.getBlob("1aaaaaaaaa"); // Too long.
+      fail("BadKeyException expected");
+    }
+    catch (BadKeyException expected)
+    {
+      // SUCCESS
+    }
+
+    storage.getBlob("aaaaa"); // Just short enough.
+    storage.getBlob("aaaaaaaaaaaaaaaaaaaaaaaaa"); // Just long enough.
+  }
+
+  @Test
+  public void testUserAgent() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    System.setProperty(Session.USER_AGENT_PROPERTY, "malicious/client");
+
+    try
+    {
+      IBlob blob = storage.getBlob("any_blob");
+      blob.getContents();
+      fail("ProtocolException expected");
+    }
+    catch (ProtocolException expected)
+    {
+      assertThat(expected.getStatusCode(), is(403)); // Forbidden.
+    }
+    finally
+    {
+      System.clearProperty(Session.USER_AGENT_PROPERTY);
+    }
+  }
+
+  @Test
+  public void testCreate() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+
+    String value = "A short UTF-8 string value";
+    assertThat(blob.setContentsUTF(value), is(true));
+
+    BlobInfo blobInfo = serverFixture.readServer(blob);
+    assertThat(blobInfo.contents, is(value));
+    assertThat(blobInfo.eTag, is(blob.getETag()));
+  }
+
+  @Test
+  public void testCreateWithWrongETag() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+    blob.setETag(WRONG_ETAG);
+    blob.setContentsUTF("Text 2"); // Update attempt 1
+    assertThat(blob.getETag(), isNotNull());
+  }
+
+  @Test
+  public void testCreateAfterRetrieve() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+
+    try
+    {
+      blob.getContentsUTF();
+      fail("NotFoundException expected");
+    }
+    catch (NotFoundException expected)
+    {
+      // SUCCESS
+    }
+
+    String value = "A short UTF-8 string value";
+    blob.setContentsUTF(value);
+
+    BlobInfo blobInfo = serverFixture.readServer(blob);
+    assertThat(blobInfo.contents, is(value));
+    assertThat(blobInfo.eTag, is(blob.getETag()));
+    assertThat(blobInfo.eTag, is(not(Session.NOT_FOUND_ETAG)));
+  }
+
+  @Test
+  public void testCreateWithCache() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN, cache);
+    IBlob blob = storage.getBlob(KEY);
+
+    String value = "A short UTF-8 string value";
+    assertThat(blob.setContentsUTF(value), is(true));
+    assertThat(clientFixture.readCache(blob.getKey(), null), is(value));
+    assertThat(clientFixture.readCache(blob.getKey(), ".properties"), containsString("etag=" + blob.getETag()));
+  }
+
+  @Test
+  public void testCreateAndUpdate() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+
+    blob.setContentsUTF("Text 1"); // Create
+    blob.setContentsUTF("Text 2"); // Update 1
+    blob.setContentsUTF("Text 3"); // Update 2
+  }
+
+  @Test
+  public void testUpdateWithWrongETag() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+
+    blob.setContentsUTF("Text 1"); // Create
+    blob.setETag(WRONG_ETAG);
+
+    try
+    {
+      blob.setContentsUTF("Text 2"); // Update attempt 1
+      fail("ConflictException expected");
+    }
+    catch (ConflictException expected)
+    {
+      assertThat(expected.getETag(), isNotNull());
+      assertThat(blob.getETag(), isNull());
+    }
+  }
+
+  @Test
+  public void testUpdateFailEarly() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+
+    String value1 = "A short UTF-8 string value";
+    assertThat(blob.setContentsUTF(value1), is(true));
+
+    File tempFile = File.createTempFile("test-", ".txt");
+    IOUtil.writeUTF(tempFile, "Another string value");
+
+    FileInputStream in = null;
+
+    try
+    {
+      Credentials credentials = new Credentials("abc", "wrong");
+      Credentials oldCredentials = FixedCredentialsProvider.setCredentials(credentials);
+
+      try
+      {
+        ((StorageService)storage.getService()).setCredentials(credentials);
+
+        in = new FileInputStream(tempFile);
+        blob.setContents(in);
+        fail("ProtocolException: HTTP/1.1 401 Unauthorized expected");
+      }
+      catch (ProtocolException expected)
+      {
+        assertThat(expected.getStatusCode(), is(401));
+      }
+      finally
+      {
+        FixedCredentialsProvider.setCredentials(oldCredentials);
+      }
+
+      assertThat(tempFile.delete(), is(true));
+    }
+    finally
+    {
+      IOUtil.closeSilent(in);
+
+      if (!tempFile.delete())
+      {
+        tempFile.deleteOnExit();
+      }
+    }
+  }
+
+  @Test
+  public void testRetrieveNotExistent() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob("aaaaaaaaaa");
+    blob.setETag(WRONG_ETAG);
+
+    try
+    {
+      blob.getContents();
+      fail("NotFoundException expected");
+    }
+    catch (NotFoundException expected)
+    {
+      // SUCCESS
+    }
+
+    assertThat(blob.getETag(), isNull());
+  }
+
+  @Test
+  public void testRetrieve() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+
+    String value = "A short UTF-8 string value";
+    blob.setContentsUTF(value);
+
+    assertThat(blob.getContentsUTF(), is(value));
+
+    BlobInfo blobInfo = serverFixture.readServer(blob);
+    assertThat(blobInfo.contents, is(value));
+    assertThat(blobInfo.eTag, is(blob.getETag()));
+  }
+
+  @Test
+  public void testRetrieveWithCache() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN, cache);
+    IBlob blob = storage.getBlob(KEY);
+
+    String value = "A short UTF-8 string value";
+    blob.setContentsUTF(value);
+
+    assertThat(blob.getContentsUTF(), is(value));
+    assertThat(clientFixture.readCache(blob.getKey(), null), is(value));
+    assertThat(clientFixture.readCache(blob.getKey(), ".properties"), containsString("etag=" + blob.getETag()));
+
+    InputStream contents = blob.getContents();
+    assertThat(contents, instanceOf(FileInputStream.class));
+
+    IOUtil.copy(contents, new ByteArrayOutputStream());
+    assertThat(clientFixture.readCache(blob.getKey(), null), is(value));
+    assertThat(clientFixture.readCache(blob.getKey(), ".properties"), containsString("etag=" + blob.getETag()));
+  }
+
+  @Test
+  public void testRetrieveMulti() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+    blob.setContentsUTF("A short UTF-8 string value");
+
+    blob.getContents();
+    blob.getContents();
+    blob.getContents();
+    blob.getContents();
+    blob.getContents();
+  }
+
+  @Test
+  public void testRetrieveKeys() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    storage.getBlob("anykey1").setContentsUTF("A short UTF-8 string value");
+    storage.getBlob("anykey2").setContentsUTF("A short UTF-8 string value");
+    storage.getBlob("anykey3").setContentsUTF("A short UTF-8 string value");
+    storage.getBlob("anykey4").setContentsUTF("A short UTF-8 string value");
+
+    Set<String> keys = new HashSet<String>();
+
+    for (IBlob blob : storage.getBlobs())
+    {
+      System.out.println(blob);
+      keys.add(blob.getKey());
+    }
+
+    assertThat(keys.contains("anykey1"), is(true));
+    assertThat(keys.contains("anykey2"), is(true));
+    assertThat(keys.contains("anykey3"), is(true));
+    assertThat(keys.contains("anykey4"), is(true));
+  }
+
+  @Test
+  public void testConflict() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+
+    String value1 = "A short UTF-8 string value";
+    blob.setContentsUTF(value1);
+
+    // Prepare the conflict.
+    String value2 = "Different content";
+    String eTag2 = serverFixture.writeServer(blob, value2);
+
+    String value3 = "And now a conflicting string";
+
+    try
+    {
+      blob.setContentsUTF(value3);
+      fail("ConflictException expected");
+    }
+    catch (ConflictException expected)
+    {
+      assertThat(expected.getETag(), isNotNull());
+      assertThat(blob.getETag(), isNull());
+    }
+
+    BlobInfo blobInfo = serverFixture.readServer(blob);
+    assertThat(blobInfo.contents, is(value2));
+    assertThat(blobInfo.eTag, is(eTag2));
+  }
+
+  @Test
+  public void testConflictWithCache() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN, cache);
+    IBlob blob = storage.getBlob(KEY);
+
+    String value1 = "A short UTF-8 string value";
+    blob.setContentsUTF(value1);
+
+    // Prepare the conflict.
+    serverFixture.writeServer(blob, "Different content");
+
+    String value3 = "And now a conflicting string";
+
+    try
+    {
+      blob.setContentsUTF(value3);
+      fail("ConflictException expected");
+    }
+    catch (ConflictException expected)
+    {
+      assertThat(expected.getETag(), isNotNull());
+      assertThat(blob.getETag(), isNull());
+    }
+
+    try
+    {
+      clientFixture.readCache(blob.getKey(), null);
+      fail("FileNotFoundException expected");
+    }
+    catch (FileNotFoundException expected)
+    {
+      // SUCCESS
+    }
+
+    try
+    {
+      clientFixture.readCache(blob.getKey(), ".properties");
+      fail("FileNotFoundException expected");
+    }
+    catch (FileNotFoundException expected)
+    {
+      // SUCCESS
+    }
+  }
+
+  @Test
+  public void testConflictResolution1() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+
+    String value1 = "A short UTF-8 string value";
+    blob.setContentsUTF(value1);
+
+    // Prepare the conflict.
+    String value2 = "Different content";
+    String eTag2 = serverFixture.writeServer(blob, value2);
+
+    assertThat(blob.getContentsUTF(), is(value2)); // Retrieve the latest server version.
+    assertThat(blob.getETag(), is(eTag2));
+
+    String value3 = "And now a non-conflicting string";
+    blob.setContentsUTF(value3);
+
+    BlobInfo blobInfo = serverFixture.readServer(blob);
+    assertThat(blobInfo.contents, is(value3));
+    assertThat(blobInfo.eTag, is(blob.getETag()));
+  }
+
+  @Test
+  public void testConflictResolution1WithCache() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN, cache);
+    IBlob blob = storage.getBlob(KEY);
+
+    String value1 = "A short UTF-8 string value";
+    blob.setContentsUTF(value1);
+
+    // Prepare the conflict.
+    String value2 = "Different content";
+    String eTag2 = serverFixture.writeServer(blob, value2);
+
+    assertThat(blob.getContentsUTF(), is(value2)); // Retrieve the latest server version.
+    assertThat(blob.getETag(), is(eTag2));
+
+    String value3 = "And now a non-conflicting string";
+    blob.setContentsUTF(value3);
+    assertThat(clientFixture.readCache(blob.getKey(), null), is(value3));
+    assertThat(clientFixture.readCache(blob.getKey(), ".properties"), containsString("etag=" + blob.getETag()));
+  }
+
+  @Test
+  public void testConflictResolution2() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+
+    String value1 = "A short UTF-8 string value";
+    blob.setContentsUTF(value1);
+
+    // Prepare the conflict.
+    String value2 = "Different content";
+    String eTag2 = serverFixture.writeServer(blob, value2);
+
+    String value3 = "And now a conflicting string";
+
+    try
+    {
+      blob.setContentsUTF(value3);
+      fail("ConflictException expected");
+    }
+    catch (ConflictException expected)
+    {
+      assertThat(expected.getETag(), isNotNull());
+      assertThat(blob.getETag(), isNull());
+      blob.setETag(eTag2);
+    }
+
+    blob.setContentsUTF(value3);
+
+    BlobInfo blobInfo = serverFixture.readServer(blob);
+    assertThat(blobInfo.contents, is(value3));
+    assertThat(blobInfo.eTag, is(blob.getETag()));
+  }
+
+  @Test
+  public void testConflictResolution2WithCache() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN, cache);
+    IBlob blob = storage.getBlob(KEY);
+
+    String value1 = "A short UTF-8 string value";
+    blob.setContentsUTF(value1);
+
+    // Prepare the conflict.
+    String value2 = "Different content";
+    String eTag2 = serverFixture.writeServer(blob, value2);
+
+    String value3 = "And now a conflicting string";
+
+    try
+    {
+      blob.setContentsUTF(value3);
+      fail("ConflictException expected");
+    }
+    catch (ConflictException expected)
+    {
+      assertThat(expected.getETag(), isNotNull());
+      assertThat(blob.getETag(), isNull());
+
+      blob.setETag(eTag2); // Delete cache.
+    }
+
+    try
+    {
+      clientFixture.readCache(blob.getKey(), null);
+      fail("FileNotFoundException expected");
+    }
+    catch (FileNotFoundException expected)
+    {
+      // SUCCESS
+    }
+
+    try
+    {
+      clientFixture.readCache(blob.getKey(), ".properties");
+      fail("FileNotFoundException expected");
+    }
+    catch (FileNotFoundException expected)
+    {
+      // SUCCESS
+    }
+
+    blob.setContentsUTF(value3);
+    assertThat(clientFixture.readCache(blob.getKey(), null), is(value3));
+    assertThat(clientFixture.readCache(blob.getKey(), ".properties"), containsString("etag=" + blob.getETag()));
+  }
+
+  @Test
+  public void testAuthenticateFailure() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+
+    Credentials credentials = new Credentials("abcd", "wrong123");
+    Credentials oldCredentials = FixedCredentialsProvider.setCredentials(credentials);
+
+    try
+    {
+      ((StorageService)storage.getService()).setCredentials(credentials);
+
+      String value1 = "A short UTF-8 string value";
+      assertThat(blob.setContentsUTF(value1), is(true));
+
+      fail("ProtocolException: HTTP/1.1 401 Unauthorized expected");
+    }
+    catch (ProtocolException expected)
+    {
+      assertThat(expected.getStatusCode(), is(401));
+    }
+    finally
+    {
+      FixedCredentialsProvider.setCredentials(oldCredentials);
+    }
+  }
+
+  @Test
+  public void testReauthenticate() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+
+    String value = "A short UTF-8 string value";
+    blob.setContentsUTF(value);
+
+    if (serverFixture.hasLocalServer())
+    {
+      Map<String, USSServer.Session> sessions = serverFixture.getServer().getSessions();
+      assertThat(sessions.size(), is(1));
+      sessions.clear();
+    }
+
+    assertThat(blob.getContentsUTF(), is(value));
+
+    BlobInfo blobInfo = serverFixture.readServer(blob);
+    assertThat(blobInfo.contents, is(value));
+    assertThat(blobInfo.eTag, is(blob.getETag()));
+
+    if (serverFixture.hasLocalServer())
+    {
+      Map<String, USSServer.Session> sessions = serverFixture.getServer().getSessions();
+      assertThat(sessions.size(), is(1));
+    }
+  }
+
+  @Test
+  public void testDelete() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+
+    String value = "A short UTF-8 string value";
+    blob.setContentsUTF(value);
+    assertThat(blob.getContentsUTF(), is(value));
+
+    blob.delete();
+
+    BlobInfo blobInfo = serverFixture.readServer(blob);
+    assertThat(blobInfo, isNull());
+
+    try
+    {
+      blob.getContentsUTF();
+      fail("NotFoundException expected");
+    }
+    catch (NotFoundException expected)
+    {
+      // SUCCESS
+    }
+  }
+
+  @Test
+  public void testDeleteWithoutETag() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+
+    String value = "A short UTF-8 string value";
+    blob.setContentsUTF(value);
+    assertThat(blob.getContentsUTF(), is(value));
+
+    blob.setETag(null);
+    blob.delete();
+
+    BlobInfo blobInfo = serverFixture.readServer(blob);
+    assertThat(blobInfo, isNull());
+
+    try
+    {
+      blob.getContentsUTF();
+      fail("NotFoundException expected");
+    }
+    catch (NotFoundException expected)
+    {
+      // SUCCESS
+    }
+  }
+
+  @Test
+  public void testDeleteWithCache() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN, cache);
+    IBlob blob = storage.getBlob(KEY);
+
+    String value = "A short UTF-8 string value";
+    blob.setContentsUTF(value);
+    assertThat(blob.getContentsUTF(), is(value));
+
+    blob.delete();
+
+    try
+    {
+      clientFixture.readCache(blob.getKey(), null);
+      fail("FileNotFoundException expected");
+    }
+    catch (FileNotFoundException expected)
+    {
+      // SUCCESS
+    }
+
+    try
+    {
+      clientFixture.readCache(blob.getKey(), ".properties");
+      fail("FileNotFoundException expected");
+    }
+    catch (FileNotFoundException expected)
+    {
+      // SUCCESS
+    }
+  }
+
+  @Test
+  public void testDeleteAll() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    assertThat(storage.getBlob(KEY).setContentsUTF("A short UTF-8 string value"), is(true));
+
+    boolean deleted = storage.deleteAllBlobs();
+    assertThat(deleted, is(true));
+    assertThat(storage.getBlobs().iterator().hasNext(), is(false));
+  }
+
+  @Test
+  public void testDeleteNotExistent() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+
+    boolean deleted = blob.delete();
+    assertThat(deleted, is(false));
+  }
+
+  @Test
+  public void testDeleteNotExistentWithWrongETag() throws Exception
+  {
+    IStorage storage = factory.create(APPLICATION_TOKEN);
+    IBlob blob = storage.getBlob(KEY);
+    blob.setETag(WRONG_ETAG);
+
+    boolean deleted = blob.delete();
+    assertThat(deleted, is(false));
+  }
+}
diff --git a/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/ClientFixture.java b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/ClientFixture.java
new file mode 100644
index 0000000..fae91e3
--- /dev/null
+++ b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/ClientFixture.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.tests.util;
+
+import org.eclipse.userstorage.StorageFactory;
+import org.eclipse.userstorage.internal.util.IOUtil;
+import org.eclipse.userstorage.spi.ISettings;
+import org.eclipse.userstorage.util.FileStorageCache;
+import org.eclipse.userstorage.util.Settings.MemorySettings;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author Eike Stepper
+ */
+public class ClientFixture extends Fixture
+{
+  private static final File CACHE = new File(TEST_FOLDER, "cache");
+
+  private final String applicationToken;
+
+  private final StorageFactory factory;
+
+  private final TestCache cache;
+
+  public ClientFixture(ServerFixture serverFixture) throws Exception
+  {
+    applicationToken = serverFixture.getApplicationToken();
+    String serviceURI = serverFixture.getService().getServiceURI().toString();
+
+    ISettings settings = new MemorySettings();
+    settings.setValue(applicationToken, serviceURI);
+
+    factory = new StorageFactory(settings);
+    cache = createCache();
+  }
+
+  public String getApplicationToken()
+  {
+    return applicationToken;
+  }
+
+  public final StorageFactory getFactory()
+  {
+    return factory;
+  }
+
+  public final TestCache getCache()
+  {
+    return cache;
+  }
+
+  public final String readCache(String key, String extension) throws IOException
+  {
+    try
+    {
+      return IOUtil.readUTF(cache.getFile(applicationToken, key, extension));
+    }
+    catch (RuntimeException ex)
+    {
+      Throwable cause = ex.getCause();
+      if (cause instanceof IOException)
+      {
+        throw (IOException)cause;
+      }
+
+      throw ex;
+    }
+  }
+
+  protected TestCache createCache()
+  {
+    IOUtil.deleteFiles(CACHE);
+    return new TestCache(CACHE);
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static final class TestCache extends FileStorageCache
+  {
+    public TestCache(File folder)
+    {
+      super(folder);
+    }
+
+    @Override
+    public File getFile(String applicationToken, String key, String extension)
+    {
+      return super.getFile(applicationToken, key, extension);
+    }
+  }
+}
diff --git a/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/FixedCredentialsProvider.java b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/FixedCredentialsProvider.java
new file mode 100644
index 0000000..1d76cfa
--- /dev/null
+++ b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/FixedCredentialsProvider.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.tests.util;
+
+import org.eclipse.userstorage.IStorageService;
+import org.eclipse.userstorage.spi.Credentials;
+import org.eclipse.userstorage.spi.ICredentialsProvider;
+
+/**
+ * @author Eike Stepper
+ */
+public class FixedCredentialsProvider implements ICredentialsProvider
+{
+  public static final Credentials DEFAULT_CREDENTIALS = new Credentials("eclipse_test_123456789", "plaintext123456789");
+
+  private static Credentials credentials = DEFAULT_CREDENTIALS;
+
+  public FixedCredentialsProvider()
+  {
+  }
+
+  @Override
+  public Credentials provideCredentials(IStorageService service, boolean reauthentication)
+  {
+    return credentials;
+  }
+
+  public static Credentials setCredentials(Credentials credentials)
+  {
+    Credentials oldCredentials = FixedCredentialsProvider.credentials;
+    FixedCredentialsProvider.credentials = credentials;
+    return oldCredentials;
+  }
+}
diff --git a/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/Fixture.java b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/Fixture.java
new file mode 100644
index 0000000..d72d695
--- /dev/null
+++ b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/Fixture.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.tests.util;
+
+import java.io.File;
+
+/**
+ * @author Eike Stepper
+ */
+public class Fixture
+{
+  public static final boolean REMOTE = Boolean.getBoolean("org.eclipse.userstorage.tests.remote");
+
+  public static final File TEST_FOLDER = new File(System.getProperty("java.io.tmpdir"), "uss-tests");
+
+  public Fixture()
+  {
+  }
+
+  public void dispose() throws Exception
+  {
+  }
+}
diff --git a/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/ServerFixture.java b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/ServerFixture.java
new file mode 100644
index 0000000..abb90ed
--- /dev/null
+++ b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/ServerFixture.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.tests.util;
+
+import org.eclipse.userstorage.IBlob;
+import org.eclipse.userstorage.IStorage;
+import org.eclipse.userstorage.IStorageService;
+import org.eclipse.userstorage.StorageFactory;
+import org.eclipse.userstorage.internal.Activator;
+import org.eclipse.userstorage.internal.util.IOUtil;
+import org.eclipse.userstorage.internal.util.StringUtil;
+import org.eclipse.userstorage.spi.ISettings;
+import org.eclipse.userstorage.tests.util.USSServer.NOOPLogger;
+import org.eclipse.userstorage.tests.util.USSServer.User;
+import org.eclipse.userstorage.util.NotFoundException;
+import org.eclipse.userstorage.util.Settings.MemorySettings;
+
+import org.eclipse.jetty.util.log.Log;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.UUID;
+
+/**
+ * @author Eike Stepper
+ */
+public class ServerFixture extends Fixture
+{
+  public static final File SERVER_FOLDER = new File(TEST_FOLDER, "server");
+
+  private final String applicationToken;
+
+  private USSServer server;
+
+  private User user;
+
+  private IStorageService.Dynamic service;
+
+  public ServerFixture(String applicationToken) throws Exception
+  {
+    this.applicationToken = applicationToken;
+
+    configureServerLogging();
+    if (manageBundleLifecycle())
+    {
+      Activator.start();
+    }
+
+    if (REMOTE)
+    {
+      service = IStorageService.Registry.INSTANCE.addService("Eclipse.org (Staging)", StringUtil.newURI("https://api-staging.eclipse.org/"));
+
+      System.out.println();
+      System.out.println("### Reset Begin ###");
+      createFactory(applicationToken).create(applicationToken).deleteAllBlobs();
+      System.out.println("### Reset Done ###");
+      System.out.println();
+    }
+    else
+    {
+      IOUtil.deleteFiles(SERVER_FOLDER);
+
+      server = new USSServer(8080, SERVER_FOLDER);
+      user = server.addUser(FixedCredentialsProvider.DEFAULT_CREDENTIALS);
+      server.getApplicationTokens().add(applicationToken);
+      int port = server.start();
+
+      service = IStorageService.Registry.INSTANCE.addService("Local", StringUtil.newURI("http://localhost:" + port));
+    }
+  }
+
+  public final String getApplicationToken()
+  {
+    return applicationToken;
+  }
+
+  public final boolean hasLocalServer()
+  {
+    return server != null;
+  }
+
+  public final USSServer getServer()
+  {
+    return server;
+  }
+
+  public final User getUser()
+  {
+    return user;
+  }
+
+  public final IStorageService.Dynamic getService()
+  {
+    return service;
+  }
+
+  public final StorageFactory createFactory(String applicationToken) throws Exception
+  {
+    ISettings settings = new MemorySettings();
+    settings.setValue(applicationToken, service.getServiceURI().toString());
+
+    return new StorageFactory(settings);
+  }
+
+  public final BlobInfo readServer(IBlob blob) throws Exception
+  {
+    BlobInfo result = new BlobInfo();
+
+    String applicationToken = blob.getStorage().getApplicationToken();
+    String key = blob.getKey();
+
+    if (hasLocalServer())
+    {
+      try
+      {
+        File blobFile = server.getUserFile(user, applicationToken, key, USSServer.BLOB_EXTENSION);
+        File etagFile = server.getUserFile(user, applicationToken, key, USSServer.ETAG_EXTENSION);
+        if (!blobFile.isFile() || !etagFile.isFile())
+        {
+          return null;
+        }
+
+        result.contents = IOUtil.readUTF(blobFile);
+        result.eTag = IOUtil.readUTF(etagFile);
+      }
+      catch (RuntimeException ex)
+      {
+        Throwable cause = ex.getCause();
+        if (cause instanceof IOException)
+        {
+          throw (IOException)cause;
+        }
+
+        throw ex;
+      }
+    }
+    else
+    {
+      try
+      {
+        StorageFactory factory = createFactory(applicationToken);
+        IStorage tmpStorage = factory.create(applicationToken);
+        IBlob tmpBlob = tmpStorage.getBlob(key);
+
+        result.contents = tmpBlob.getContentsUTF();
+        if (result.contents == null)
+        {
+          return null;
+        }
+
+        result.eTag = tmpBlob.getETag();
+      }
+      catch (NotFoundException ex)
+      {
+        return null;
+      }
+    }
+
+    return result;
+  }
+
+  public final String writeServer(IBlob blob, String value) throws Exception
+  {
+    String applicationToken = blob.getStorage().getApplicationToken();
+    String key = blob.getKey();
+
+    if (hasLocalServer())
+    {
+      String eTag = UUID.randomUUID().toString();
+      IOUtil.writeUTF(server.getUserFile(user, applicationToken, key, USSServer.ETAG_EXTENSION), eTag);
+      IOUtil.writeUTF(server.getUserFile(user, applicationToken, key, USSServer.BLOB_EXTENSION), value);
+      return eTag;
+    }
+
+    StorageFactory factory = createFactory(applicationToken);
+    IStorage tmpStorage = factory.create(applicationToken);
+    IBlob tmpBlob = tmpStorage.getBlob(key);
+    tmpBlob.setETag(blob.getETag());
+    tmpBlob.setContentsUTF(value);
+    return tmpBlob.getETag();
+  }
+
+  @Override
+  public void dispose() throws Exception
+  {
+    user = null;
+
+    if (service != null)
+    {
+      service.remove();
+      service = null;
+    }
+
+    if (server != null)
+    {
+      server.stop();
+      server = null;
+    }
+
+    if (manageBundleLifecycle())
+    {
+      Activator.stop();
+    }
+
+    super.dispose();
+  }
+
+  protected void configureServerLogging()
+  {
+    Log.setLog(new NOOPLogger());
+  }
+
+  protected boolean manageBundleLifecycle()
+  {
+    return true;
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static final class BlobInfo
+  {
+    public String eTag;
+
+    public String contents;
+  }
+}
diff --git a/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/TestCredentialsProvider.java b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/TestCredentialsProvider.java
new file mode 100644
index 0000000..ca94a2a
--- /dev/null
+++ b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/TestCredentialsProvider.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.tests.util;
+
+import org.eclipse.userstorage.IStorageService;
+import org.eclipse.userstorage.internal.util.IOUtil;
+import org.eclipse.userstorage.spi.Credentials;
+import org.eclipse.userstorage.spi.ICredentialsProvider;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+
+import java.awt.Container;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.GridLayout;
+import java.awt.MouseInfo;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+/**
+ * @author Eike Stepper
+ */
+public class TestCredentialsProvider implements ICredentialsProvider
+{
+  private static final File CREDENTIALS_FILE = new File(System.getProperty("userstorage.credentials.file", "userstorage.credentials"));
+
+  public TestCredentialsProvider()
+  {
+  }
+
+  @Override
+  public Credentials provideCredentials(IStorageService service, boolean reauthentication)
+  {
+    if (CREDENTIALS_FILE.exists())
+    {
+      System.out.println("Reading credentials from file " + CREDENTIALS_FILE);
+      System.out.println();
+
+      return (Credentials)IOUtil.readObject(CREDENTIALS_FILE);
+    }
+
+    Credentials credentials = new LoginDialog().getCredentials();
+    if (credentials == null)
+    {
+      throw new RuntimeException("No credentials entered!");
+    }
+
+    System.out.println("Storing credentials in file " + CREDENTIALS_FILE);
+    System.out.println();
+
+    IOUtil.writeObject(CREDENTIALS_FILE, credentials);
+
+    return credentials;
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private static class LoginDialog extends JDialog
+  {
+    private static final long serialVersionUID = 1L;
+
+    private Credentials credentials;
+
+    public LoginDialog()
+    {
+      setTitle("Login");
+      setModal(true);
+
+      final JTextField userField = new JTextField(15);
+      final JPasswordField passwordField = new JPasswordField(15);
+
+      Container contentPane = getContentPane();
+      contentPane.setLayout(new GridLayout(3, 2));
+      contentPane.add(new JLabel("Username:"));
+      contentPane.add(userField);
+      contentPane.add(new JLabel("Password:"));
+      contentPane.add(passwordField);
+
+      JButton okButton = new JButton("OK");
+      okButton.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          String username = userField.getText();
+          String password = new String(passwordField.getPassword());
+          if (!isEmpty(username) && !isEmpty(password))
+          {
+            credentials = new Credentials(username, password);
+          }
+
+          close();
+        }
+      });
+
+      JButton cancelButton = new JButton("Cancel");
+      cancelButton.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          close();
+        }
+      });
+
+      contentPane.add(okButton);
+      contentPane.add(cancelButton);
+
+      userField.setText("eclipse_test_123456789");
+      passwordField.requestFocus();
+
+      pack();
+      setCenterLocation();
+      setVisible(true);
+    }
+
+    public Credentials getCredentials()
+    {
+      return credentials;
+    }
+
+    private void setCenterLocation()
+    {
+      try
+      {
+        Point mousePoint = MouseInfo.getPointerInfo().getLocation();
+        for (GraphicsDevice device : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices())
+        {
+          Rectangle bounds = device.getDefaultConfiguration().getBounds();
+          if (bounds.contains(mousePoint))
+          {
+            setLocation((bounds.width - getWidth()) / 2 + bounds.x, (bounds.height - getHeight()) / 2 + bounds.y);
+            break;
+          }
+        }
+      }
+      catch (Exception ex)
+      {
+        //$FALL-THROUGH$
+      }
+    }
+
+    private void close()
+    {
+      setVisible(false);
+      dispose();
+    }
+
+    private static boolean isEmpty(String str)
+    {
+      return str == null || str.length() == 0;
+    }
+  }
+}
diff --git a/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/USSServer.java b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/USSServer.java
new file mode 100644
index 0000000..6af036f
--- /dev/null
+++ b/org.eclipse.userstorage.tests/src/org/eclipse/userstorage/tests/util/USSServer.java
@@ -0,0 +1,904 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.tests.util;
+
+import org.eclipse.userstorage.internal.util.IOUtil;
+import org.eclipse.userstorage.internal.util.JSONUtil;
+import org.eclipse.userstorage.internal.util.StringUtil;
+import org.eclipse.userstorage.spi.Credentials;
+import org.eclipse.userstorage.tests.StorageTests;
+
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jetty.http.HttpMethod;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * @author Eike Stepper
+ */
+public final class USSServer
+{
+  public static final String BLOB_EXTENSION = ".blob";
+
+  public static final String ETAG_EXTENSION = ".etag";
+
+  private static final boolean DEBUG = Boolean.getBoolean("org.eclipse.userstorage.tests.server.debug");
+
+  private final USSHandler handler = new USSHandler();
+
+  private final Set<String> applicationTokens = new HashSet<String>();
+
+  private final Map<String, User> users = new HashMap<String, User>();
+
+  private final Map<String, Session> sessions = new HashMap<String, Session>();
+
+  private final File folder;
+
+  private final int startPort;
+
+  private int port;
+
+  private Server server;
+
+  public USSServer(int startPort, File folder)
+  {
+    this.startPort = startPort;
+    this.folder = folder;
+  }
+
+  public int getPort()
+  {
+    return port;
+  }
+
+  public File getFolder()
+  {
+    return folder;
+  }
+
+  public Set<String> getApplicationTokens()
+  {
+    return applicationTokens;
+  }
+
+  public Map<String, User> getUsers()
+  {
+    return users;
+  }
+
+  public User addUser(Credentials credentials)
+  {
+    return addUser(credentials.getUsername(), credentials.getPassword());
+  }
+
+  public User addUser(String username, String password)
+  {
+    User user = new User(username, password);
+    users.put(user.getUsername(), user);
+    return user;
+  }
+
+  public File getUserFile(User user, String applicationToken, String key, String extension)
+  {
+    return new File(getApplicationFolder(user, applicationToken), key + StringUtil.safe(extension));
+  }
+
+  public File getApplicationFolder(User user, String applicationToken)
+  {
+    return new File(new File(folder, user.getUsername()), applicationToken);
+  }
+
+  public Map<String, Session> getSessions()
+  {
+    return sessions;
+  }
+
+  public int start() throws Exception
+  {
+    Exception exception = new Exception("No free port");
+
+    for (port = startPort; port < 65535; port++)
+    {
+      server = new Server(port);
+      server.setHandler(handler);
+
+      try
+      {
+        server.start();
+        return port;
+      }
+      catch (Exception ex)
+      {
+        exception = ex;
+
+        try
+        {
+          server.stop();
+        }
+        catch (Exception ignore)
+        {
+          //$FALL-THROUGH$
+        }
+        finally
+        {
+          server = null;
+        }
+      }
+    }
+
+    throw exception;
+  }
+
+  public void stop() throws Exception
+  {
+    if (server != null)
+    {
+      server.stop();
+      server = null;
+    }
+  }
+
+  public void join() throws InterruptedException
+  {
+    if (server != null)
+    {
+      server.join();
+    }
+  }
+
+  protected void login(HttpServletRequest request, HttpServletResponse response) throws IOException
+  {
+    Map<String, Object> requestObject = JSONUtil.parse(request.getInputStream(), null);
+
+    String username = (String)requestObject.get("username");
+    String password = (String)requestObject.get("password");
+
+    User user = users.get(username);
+    if (user == null || password == null || !password.equals(user.getPassword()))
+    {
+      response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+      return;
+    }
+
+    response.setStatus(HttpServletResponse.SC_OK);
+    response.setContentType("application/json");
+
+    Session session = addSession(user);
+    Cookie cookie = new Cookie("SESSION", session.getID());
+    cookie.setPath("/");
+    response.addCookie(cookie);
+
+    Map<String, Object> responseObject = new LinkedHashMap<String, Object>();
+    responseObject.put("sessid", session.getID());
+    responseObject.put("token", session.getCSRFToken());
+    InputStream body = JSONUtil.build(responseObject);
+
+    try
+    {
+      ServletOutputStream out = response.getOutputStream();
+      IOUtil.copy(body, out);
+      out.flush();
+    }
+    finally
+    {
+      IOUtil.closeSilent(body);
+    }
+  }
+
+  protected void retrieveProperties(HttpServletRequest request, HttpServletResponse response, File applicationFolder) throws IOException
+  {
+    String applicationToken = applicationFolder.getName();
+
+    int pageSize = getIntParameter(request, "pageSize", 20);
+    if (pageSize < 1 || pageSize > 100)
+    {
+      response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid page size");
+      return;
+    }
+
+    int page = getIntParameter(request, "page", 20);
+    if (page < 1)
+    {
+      response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid page");
+      return;
+    }
+
+    boolean empty = true;
+
+    StringBuilder builder = new StringBuilder();
+    builder.append('[');
+
+    File[] files = applicationFolder.listFiles();
+    if (files != null)
+    {
+      int first = (page - 1) * pageSize + 1;
+      System.out.println("##### " + first);
+      int i = 0;
+
+      for (File file : files)
+      {
+        String name = file.getName();
+        if (name.endsWith(ETAG_EXTENSION))
+        {
+          if (++i >= first)
+          {
+            String key = name.substring(0, name.length() - ETAG_EXTENSION.length());
+            System.out.println("##### " + key);
+            String etag = IOUtil.readUTF(file);
+
+            if (empty)
+            {
+              empty = false;
+            }
+            else
+            {
+              builder.append(",");
+            }
+
+            builder.append("{\"application_token\":\"");
+            builder.append(applicationToken);
+            builder.append("\",\"key\":\"");
+            builder.append(key);
+            builder.append("\",\"etag\":\"");
+            builder.append(etag);
+            builder.append("\"}");
+
+            if (--pageSize == 0)
+            {
+              break;
+            }
+          }
+        }
+      }
+    }
+
+    builder.append(']');
+    System.out.println(builder);
+
+    response.setStatus(HttpServletResponse.SC_OK);
+    response.setContentType("application/json");
+
+    InputStream body = IOUtil.streamUTF(builder.toString());
+
+    try
+    {
+      ServletOutputStream out = response.getOutputStream();
+      IOUtil.copy(body, out);
+      out.flush();
+    }
+    finally
+    {
+      IOUtil.closeSilent(body);
+    }
+  }
+
+  protected void retrieveBlob(HttpServletRequest request, HttpServletResponse response, File blobFile, File etagFile, boolean exists) throws IOException
+  {
+    if (!exists)
+    {
+      response.sendError(HttpServletResponse.SC_NOT_FOUND);
+      return;
+    }
+
+    String etag = IOUtil.readUTF(etagFile);
+    String ifNoneMatch = getETag(request, "If-None-Match");
+    if (ifNoneMatch != null && ifNoneMatch.equals(etag))
+    {
+      response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+      return;
+    }
+
+    response.setStatus(HttpServletResponse.SC_OK);
+    response.setContentType("application/json");
+    response.setHeader("ETag", "\"" + etag + "\"");
+
+    InputStream body = JSONUtil.build(Collections.singletonMap("value", new FileInputStream(blobFile)));
+
+    try
+    {
+      ServletOutputStream out = response.getOutputStream();
+      IOUtil.copy(body, out);
+      out.flush();
+    }
+    finally
+    {
+      IOUtil.closeSilent(body);
+    }
+  }
+
+  protected void updateBlob(HttpServletRequest request, HttpServletResponse response, File blobFile, File etagFile, boolean exists) throws IOException
+  {
+    String ifMatch = getETag(request, "If-Match");
+
+    if (exists)
+    {
+      String etag = IOUtil.readUTF(etagFile);
+
+      if (StringUtil.isEmpty(ifMatch) || !ifMatch.equals(etag))
+      {
+        response.setHeader("ETag", "\"" + etag + "\"");
+        response.sendError(HttpServletResponse.SC_CONFLICT);
+        return;
+      }
+    }
+
+    String etag = UUID.randomUUID().toString();
+
+    IOUtil.mkdirs(blobFile.getParentFile());
+    FileOutputStream out = new FileOutputStream(blobFile);
+    InputStream body = null;
+
+    try
+    {
+      Map<String, Object> requestObject = JSONUtil.parse(request.getInputStream(), "value");
+      body = (InputStream)requestObject.get("value");
+
+      IOUtil.copy(body, out);
+    }
+    finally
+    {
+      IOUtil.closeSilent(body);
+      IOUtil.close(out);
+    }
+
+    IOUtil.writeUTF(etagFile, etag);
+
+    response.setStatus(exists ? HttpServletResponse.SC_OK : HttpServletResponse.SC_CREATED);
+    response.setHeader("ETag", "\"" + etag + "\"");
+  }
+
+  protected void deleteBlob(HttpServletRequest request, HttpServletResponse response, File blobFile, File etagFile, boolean exists) throws IOException
+  {
+    if (exists)
+    {
+      String etag = IOUtil.readUTF(etagFile);
+      String ifMatch = getETag(request, "If-Match");
+      if (ifMatch != null && !ifMatch.equals(etag))
+      {
+        response.sendError(HttpServletResponse.SC_CONFLICT);
+        return;
+      }
+    }
+    else
+    {
+      response.sendError(HttpServletResponse.SC_NOT_FOUND);
+      return;
+    }
+
+    IOUtil.delete(blobFile);
+    IOUtil.delete(etagFile);
+
+    response.setStatus(HttpServletResponse.SC_NO_CONTENT);
+  }
+
+  private Session getSession(HttpServletRequest request)
+  {
+    String csrfToken = request.getHeader("X-CSRF-Token");
+    if (csrfToken != null)
+    {
+      Cookie[] cookies = request.getCookies();
+      if (cookies != null)
+      {
+        for (Cookie cookie : cookies)
+        {
+          if ("SESSION".equals(cookie.getName()))
+          {
+            String sessionID = cookie.getValue();
+            Session session = sessions.get(sessionID);
+
+            if (session != null && session.getCSRFToken().equals(csrfToken))
+            {
+              return session;
+            }
+
+            break;
+          }
+        }
+      }
+    }
+
+    return null;
+  }
+
+  private Session addSession(User user)
+  {
+    Session session = new Session(user);
+    sessions.put(session.getID(), session);
+    return session;
+  }
+
+  private static String getETag(HttpServletRequest request, String headerName)
+  {
+    String eTag = request.getHeader(headerName);
+    if (eTag != null)
+    {
+      // Remove the quotes.
+      eTag = eTag.substring(1, eTag.length() - 1);
+    }
+
+    return eTag;
+  }
+
+  @SuppressWarnings("restriction")
+  private static String getReasonPhrase(int status)
+  {
+    try
+    {
+      return org.apache.http.impl.EnglishReasonPhraseCatalog.INSTANCE.getReason(status, null);
+    }
+    catch (Throwable ex)
+    {
+      return "";
+    }
+  }
+
+  private static int getIntParameter(HttpServletRequest request, String name, int defaultValue)
+  {
+    String parameter = request.getParameter(name);
+    if (parameter != null)
+    {
+      try
+      {
+        return Integer.parseInt(parameter);
+      }
+      catch (NumberFormatException ex)
+      {
+        //$FALL-THROUGH$
+      }
+    }
+
+    return defaultValue;
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  private class USSHandler extends AbstractHandler
+  {
+    @Override
+    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+    {
+      try
+      {
+        baseRequest.setHandled(true);
+
+        String userAgent = request.getHeader("User-Agent");
+        if (!org.eclipse.userstorage.internal.Session.USER_AGENT_ID.equals(userAgent))
+        {
+          response.sendError(HttpServletResponse.SC_FORBIDDEN, "Invalid User-Agent");
+          return;
+        }
+
+        String method = request.getMethod();
+        String path = request.getPathInfo();
+
+        if (DEBUG)
+        {
+          StringBuilder builder = new StringBuilder();
+          builder.append(method);
+          builder.append(" ");
+          builder.append(path);
+          builder.append('\n');
+
+          Enumeration<String> headerNames = request.getHeaderNames();
+          while (headerNames.hasMoreElements())
+          {
+            String headerName = headerNames.nextElement();
+            Enumeration<String> headers = request.getHeaders(headerName);
+            while (headers.hasMoreElements())
+            {
+              String header = headers.nextElement();
+              builder.append("   ");
+              builder.append(headerName);
+              builder.append(": ");
+              builder.append(header);
+              builder.append('\n');
+            }
+          }
+
+          System.out.print(builder);
+          System.out.flush();
+        }
+
+        if (path != null && method != null)
+        {
+          handle(method, path, request, response);
+
+          if (DEBUG)
+          {
+            int status = response.getStatus();
+            String reasonPhrase = getReasonPhrase(status);
+
+            StringBuilder builder = new StringBuilder();
+            builder.append(request.getProtocol());
+            builder.append(" ");
+            builder.append(status);
+            if (!StringUtil.isEmpty(reasonPhrase))
+            {
+              builder.append(" ");
+              builder.append(reasonPhrase);
+            }
+
+            builder.append('\n');
+
+            for (String headerName : response.getHeaderNames())
+            {
+              for (String header : response.getHeaders(headerName))
+              {
+                builder.append("   ");
+                builder.append(headerName);
+                builder.append(": ");
+                builder.append(header);
+                builder.append('\n');
+              }
+            }
+
+            System.out.println(builder);
+          }
+        }
+      }
+      catch (IOException ex)
+      {
+        ex.printStackTrace();
+        throw ex;
+      }
+      catch (RuntimeException ex)
+      {
+        ex.printStackTrace();
+        throw ex;
+      }
+    }
+
+    private void handle(String method, String path, HttpServletRequest request, HttpServletResponse response) throws IOException
+    {
+      if (path.equals("/api/user/login") && HttpMethod.POST.is(method))
+      {
+        login(request, response);
+        return;
+      }
+
+      Session session = getSession(request);
+      if (session == null)
+      {
+        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+        return;
+      }
+
+      if (path.startsWith("/api/blob"))
+      {
+        User user = session.getUser();
+        Path segments = new Path(path);
+
+        String applicationToken = segments.segment(2);
+        if (!applicationTokens.contains(applicationToken))
+        {
+          response.sendError(HttpServletResponse.SC_NOT_FOUND);
+          return;
+        }
+
+        if (segments.segmentCount() < 4)
+        {
+          if (HttpMethod.GET.is(method))
+          {
+            File applicationFolder = getApplicationFolder(user, applicationToken);
+            retrieveProperties(request, response, applicationFolder);
+            return;
+          }
+
+          response.sendError(HttpServletResponse.SC_FORBIDDEN);
+          return;
+        }
+
+        String key = segments.segment(3);
+        File blobFile = getUserFile(user, applicationToken, key, BLOB_EXTENSION);
+        File etagFile = getUserFile(user, applicationToken, key, ETAG_EXTENSION);
+        boolean exists = etagFile.exists();
+
+        if (HttpMethod.GET.is(method))
+        {
+          retrieveBlob(request, response, blobFile, etagFile, exists);
+          return;
+        }
+
+        if (HttpMethod.PUT.is(method))
+        {
+          updateBlob(request, response, blobFile, etagFile, exists);
+          return;
+        }
+
+        if (HttpMethod.DELETE.is(method))
+        {
+          deleteBlob(request, response, blobFile, etagFile, exists);
+          return;
+        }
+
+        return;
+      }
+
+      response.sendError(HttpServletResponse.SC_FORBIDDEN);
+    }
+  }
+
+  /**
+  * @author Eike Stepper
+  */
+  public static final class User
+  {
+    private final String username;
+
+    private final byte[] password;
+
+    public User(String username, String password)
+    {
+      this.username = username;
+      this.password = StringUtil.encrypt(password);
+    }
+
+    public String getUsername()
+    {
+      return username;
+    }
+
+    public String getPassword()
+    {
+      return StringUtil.decrypt(password);
+    }
+
+    @Override
+    public String toString()
+    {
+      return username;
+    }
+
+    @Override
+    public int hashCode()
+    {
+      return username.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+      if (this == obj)
+      {
+        return true;
+      }
+
+      if (obj == null)
+      {
+        return false;
+      }
+
+      if (getClass() != obj.getClass())
+      {
+        return false;
+      }
+
+      User other = (User)obj;
+      if (username == null)
+      {
+        if (other.username != null)
+        {
+          return false;
+        }
+      }
+      else if (!username.equals(other.username))
+      {
+        return false;
+      }
+
+      return true;
+    }
+  }
+
+  /**
+  * @author Eike Stepper
+  */
+  public static final class Session
+  {
+    private final String id;
+
+    private final String csrfToken;
+
+    private final User user;
+
+    public Session(User user)
+    {
+      id = UUID.randomUUID().toString();
+      csrfToken = UUID.randomUUID().toString();
+      this.user = user;
+    }
+
+    public String getID()
+    {
+      return id;
+    }
+
+    public String getCSRFToken()
+    {
+      return csrfToken;
+    }
+
+    public User getUser()
+    {
+      return user;
+    }
+
+    @Override
+    public int hashCode()
+    {
+      return id.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+      if (this == obj)
+      {
+        return true;
+      }
+
+      if (obj == null)
+      {
+        return false;
+      }
+
+      if (getClass() != obj.getClass())
+      {
+        return false;
+      }
+
+      Session other = (Session)obj;
+      if (id == null)
+      {
+        if (other.id != null)
+        {
+          return false;
+        }
+      }
+      else if (!id.equals(other.id))
+      {
+        return false;
+      }
+
+      return true;
+    }
+
+    @Override
+    public String toString()
+    {
+      return id + " -> " + user;
+    }
+  }
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class NOOPLogger implements Logger
+  {
+    @Override
+    public String getName()
+    {
+      return "noop";
+    }
+
+    @Override
+    public void warn(String msg, Object... args)
+    {
+    }
+
+    @Override
+    public void warn(Throwable thrown)
+    {
+    }
+
+    @Override
+    public void warn(String msg, Throwable thrown)
+    {
+    }
+
+    @Override
+    public void info(String msg, Object... args)
+    {
+    }
+
+    @Override
+    public void info(Throwable thrown)
+    {
+    }
+
+    @Override
+    public void info(String msg, Throwable thrown)
+    {
+    }
+
+    @Override
+    public boolean isDebugEnabled()
+    {
+      return false;
+    }
+
+    @Override
+    public void setDebugEnabled(boolean enabled)
+    {
+    }
+
+    @Override
+    public void debug(String msg, Object... args)
+    {
+    }
+
+    @Override
+    public void debug(Throwable thrown)
+    {
+    }
+
+    @Override
+    public void debug(String msg, Throwable thrown)
+    {
+    }
+
+    @Override
+    public void debug(String msg, long value)
+    {
+    }
+
+    @Override
+    public Logger getLogger(String name)
+    {
+      return this;
+    }
+
+    @Override
+    public void ignore(Throwable ignored)
+    {
+    }
+  }
+
+  public static void main(String[] args) throws Exception
+  {
+    Log.setLog(new NOOPLogger());
+
+    USSServer server = new USSServer(8080, new File(System.getProperty("java.io.tmpdir"), "uss-server"));
+    server.addUser(FixedCredentialsProvider.DEFAULT_CREDENTIALS);
+
+    Set<String> applicationTokens = server.getApplicationTokens();
+    applicationTokens.add(StorageTests.APPLICATION_TOKEN);
+    applicationTokens.add("cNhDr0INs8T109P8h6E1r_GvU3I"); // Oomph
+
+    System.out.println(server.getFolder());
+    System.out.println("Listening on port " + server.start());
+    server.join();
+  }
+}
diff --git a/org.eclipse.userstorage.ui/.classpath b/org.eclipse.userstorage.ui/.classpath
new file mode 100644
index 0000000..ad32c83
--- /dev/null
+++ b/org.eclipse.userstorage.ui/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<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="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.userstorage.ui/.project b/org.eclipse.userstorage.ui/.project
new file mode 100644
index 0000000..e8649ab
--- /dev/null
+++ b/org.eclipse.userstorage.ui/.project
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.userstorage.ui</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+	</natures>
+	<filteredResources>
+		<filter>
+			<id>1396938000000</id>
+			<name></name>
+			<type>10</type>
+			<matcher>
+				<id>org.eclipse.ui.ide.multiFilter</id>
+				<arguments>1.0-projectRelativePath-matches-true-false-target</arguments>
+			</matcher>
+		</filter>
+	</filteredResources>
+</projectDescription>
diff --git a/org.eclipse.userstorage.ui/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.userstorage.ui/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..bb20789
--- /dev/null
+++ b/org.eclipse.userstorage.ui/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,410 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+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.doc.comment.support=enabled
+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=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+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=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning
+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.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=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=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+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.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=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=warning
+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=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.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled
+org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,HIGH,LOW,LOW,LOW,LOW,LOW
+org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX,PERF,MEM,POLISH,@generated NOT,@ADDED
+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=1
+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=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_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=false
+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=160
+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=2
+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=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=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=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=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=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=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=do not 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=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_lambda_arrow=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=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=do not 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=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=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not 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_lambda_arrow=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=do not 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=160
+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=2
+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
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/org.eclipse.userstorage.ui/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.userstorage.ui/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..7c1dd68
--- /dev/null
+++ b/org.eclipse.userstorage.ui/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,125 @@
+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=true
+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_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.insert_inferred_type_arguments=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=true
+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=false
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+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_anonymous_class_creation=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup.use_type_arguments=false
+cleanup_profile=_UserStorage
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_UserStorage
+formatter_settings_version=12
+org.eclipse.jdt.ui.exception.name=ex
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=org.eclipse.userstorage;org.eclipse.emf;org.eclipse;com;org;javax;java;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="false" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment"/><template autoinsert\="false" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment"/><template autoinsert\="false" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment"/><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/*\r\n * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * which accompanies this distribution, and is available at\r\n * http\://www.eclipse.org/legal/epl-v10.html\r\n * \r\n * Contributors\:\r\n *    Eike Stepper - initial API and implementation\r\n */</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\r\n * @author Eike Stepper\r\n */</template><template autoinsert\="false" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment"/><template autoinsert\="false" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment"/><template autoinsert\="false" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment"/><template autoinsert\="false" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment"/><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\r\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\r\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\r\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\r\n</template><template autoinsert\="false" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">${exception_var}.printStackTrace();</template><template autoinsert\="false" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">${body_statement}</template><template autoinsert\="false" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+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=false
+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=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+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=true
+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=true
+sp_cleanup.remove_unused_imports=true
+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=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/org.eclipse.userstorage.ui/.settings/org.eclipse.ltk.core.refactoring.prefs b/org.eclipse.userstorage.ui/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..864e30f
--- /dev/null
+++ b/org.eclipse.userstorage.ui/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Thu Feb 04 09:44:24 CET 2010
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/org.eclipse.userstorage.ui/.settings/org.eclipse.pde.prefs b/org.eclipse.userstorage.ui/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..2683a79
--- /dev/null
+++ b/org.eclipse.userstorage.ui/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,32 @@
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.encodings=2
+compilers.p.build.java.compiler=2
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=2
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=2
+compilers.p.discouraged-class=2
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=1
+compilers.p.missing-version-import-package=1
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=2
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=0
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+eclipse.preferences.version=1
diff --git a/org.eclipse.userstorage.ui/META-INF/MANIFEST.MF b/org.eclipse.userstorage.ui/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..e8d283e
--- /dev/null
+++ b/org.eclipse.userstorage.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,17 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.userstorage.ui;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-ActivationPolicy: lazy
+Bundle-Activator: org.eclipse.userstorage.ui.internal.Activator
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.0.0,4.0.0)",
+ org.eclipse.ui;bundle-version="[3.0.0,4.0.0)",
+ org.apache.httpcomponents.httpclient;bundle-version="[4.0.0,5.0.0)",
+ org.apache.httpcomponents.httpcore;bundle-version="[4.0.0,5.0.0)",
+ org.eclipse.userstorage;bundle-version="[1.0.0,2.0.0)";visibility:=reexport
+Export-Package: org.eclipse.userstorage.ui;version="1.0.0",
+ org.eclipse.userstorage.ui.internal;version="1.0.0";x-internal:=true
diff --git a/org.eclipse.userstorage.ui/User Storage IDE.launch b/org.eclipse.userstorage.ui/User Storage IDE.launch
new file mode 100644
index 0000000..9ece2f1
--- /dev/null
+++ b/org.eclipse.userstorage.ui/User Storage IDE.launch
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.pde.ui.RuntimeWorkbench">
+<booleanAttribute key="append.args" value="true"/>
+<booleanAttribute key="askclear" value="true"/>
+<booleanAttribute key="automaticAdd" value="true"/>
+<booleanAttribute key="automaticValidate" value="false"/>
+<stringAttribute key="bootstrap" value=""/>
+<stringAttribute key="checked" value="[NONE]"/>
+<booleanAttribute key="clearConfig" value="false"/>
+<booleanAttribute key="clearws" value="false"/>
+<booleanAttribute key="clearwslog" value="false"/>
+<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/User Storage IDE"/>
+<booleanAttribute key="default" value="true"/>
+<booleanAttribute key="includeOptional" value="true"/>
+<stringAttribute key="location" value="${workspace_loc}/../ws-UserStorageIDE"/>
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
+</listAttribute>
+<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dorg.eclipse.userstorage.ui.showServices=false&#13;&#10;-Dorg.eclipse.userstorage.ui.showTestButton=true&#13;&#10;-DXXXorg.eclipse.userstorage.serviceURI=http://localhost:8080/&#13;&#10;-DXXXorg.eclipse.userstorage.termsOfUseLink="/>
+<stringAttribute key="pde.version" value="3.3"/>
+<stringAttribute key="product" value="org.eclipse.sdk.ide"/>
+<booleanAttribute key="show_selected_only" value="false"/>
+<stringAttribute key="templateConfig" value="${target_home}\configuration\config.ini"/>
+<booleanAttribute key="tracing" value="false"/>
+<booleanAttribute key="useCustomFeatures" value="false"/>
+<booleanAttribute key="useDefaultConfig" value="true"/>
+<booleanAttribute key="useDefaultConfigArea" value="true"/>
+<booleanAttribute key="useProduct" value="true"/>
+</launchConfiguration>
diff --git a/org.eclipse.userstorage.ui/about.html b/org.eclipse.userstorage.ui/about.html
new file mode 100644
index 0000000..d35d5ae
--- /dev/null
+++ b/org.eclipse.userstorage.ui/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>June 5, 2007</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
diff --git a/org.eclipse.userstorage.ui/about.mappings b/org.eclipse.userstorage.ui/about.mappings
new file mode 100644
index 0000000..4b420dd
--- /dev/null
+++ b/org.eclipse.userstorage.ui/about.mappings
@@ -0,0 +1,3 @@
+0=${build.id}
+1=${git.branch}
+2=${git.commit}
diff --git a/org.eclipse.userstorage.ui/build.properties b/org.eclipse.userstorage.ui/build.properties
new file mode 100644
index 0000000..74d8a0e
--- /dev/null
+++ b/org.eclipse.userstorage.ui/build.properties
@@ -0,0 +1,11 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               icons/,\
+               about.html,\
+               plugin.xml,\
+               plugin.properties,\
+               about.mappings
+src.includes = about.html,\
+               pom.xml
diff --git a/org.eclipse.userstorage.ui/icons/DynamicService.gif b/org.eclipse.userstorage.ui/icons/DynamicService.gif
new file mode 100644
index 0000000..c933629
--- /dev/null
+++ b/org.eclipse.userstorage.ui/icons/DynamicService.gif
Binary files differ
diff --git a/org.eclipse.userstorage.ui/icons/LoginBanner.png b/org.eclipse.userstorage.ui/icons/LoginBanner.png
new file mode 100644
index 0000000..baf1611
--- /dev/null
+++ b/org.eclipse.userstorage.ui/icons/LoginBanner.png
Binary files differ
diff --git a/org.eclipse.userstorage.ui/icons/Service.gif b/org.eclipse.userstorage.ui/icons/Service.gif
new file mode 100644
index 0000000..a15861d
--- /dev/null
+++ b/org.eclipse.userstorage.ui/icons/Service.gif
Binary files differ
diff --git a/org.eclipse.userstorage.ui/plugin.properties b/org.eclipse.userstorage.ui/plugin.properties
new file mode 100644
index 0000000..cc3658c
--- /dev/null
+++ b/org.eclipse.userstorage.ui/plugin.properties
@@ -0,0 +1,11 @@
+# Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+# 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:
+#    Eike Stepper - initial API and implementation
+
+pluginName = Eclipse User Storage UI
+providerName = Eclipse.org
diff --git a/org.eclipse.userstorage.ui/plugin.xml b/org.eclipse.userstorage.ui/plugin.xml
new file mode 100644
index 0000000..bbb7894
--- /dev/null
+++ b/org.eclipse.userstorage.ui/plugin.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<!--
+  Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+  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:
+    Eike Stepper - initial API and implementation
+-->
+
+<plugin>
+
+   <extension point="org.eclipse.userstorage.credentialsProviders">
+      <credentialsProvider class="org.eclipse.userstorage.ui.internal.DialogCredentialsProvider"/>
+   </extension>
+
+   <extension point="org.eclipse.ui.preferencePages">
+      <page category="org.eclipse.ui.preferencePages.Workbench"
+            class="org.eclipse.userstorage.ui.internal.ServicesPreferencePage"
+            id="org.eclipse.userstorage.ui.ServicesPreferencePage"
+            name="User Storage Service"/>
+   </extension>
+
+</plugin>
diff --git a/org.eclipse.userstorage.ui/pom.xml b/org.eclipse.userstorage.ui/pom.xml
new file mode 100644
index 0000000..afddc54
--- /dev/null
+++ b/org.eclipse.userstorage.ui/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+  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:
+    Eike Stepper - initial API and implementation
+-->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.eclipse.userstorage</groupId>
+    <artifactId>parent</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+  <groupId>org.eclipse.userstorage</groupId>
+  <artifactId>org.eclipse.userstorage.ui</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>eclipse-plugin</packaging>
+</project>
diff --git a/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/AbstractDialog.java b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/AbstractDialog.java
new file mode 100644
index 0000000..6c71027
--- /dev/null
+++ b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/AbstractDialog.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.ui;
+
+import org.eclipse.userstorage.internal.util.StringUtil;
+import org.eclipse.userstorage.ui.internal.Activator;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+import java.lang.reflect.Field;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class AbstractDialog extends TitleAreaDialog
+{
+  private static final String DIALOG_WIDTH = getDialogConstant("DIALOG_WIDTH", "DIALOG_WIDTH");
+
+  private static final String DIALOG_HEIGHT = getDialogConstant("DIALOG_HEIGHT", "DIALOG_HEIGHT");
+
+  private static final String DIALOG_FONT_DATA = getDialogConstant("DIALOG_FONT_DATA", "DIALOG_FONT_NAME");
+
+  private static final String DIALOG_MESSAGE = "DIALOG_MESSAGE";
+
+  private static final int WIDTH_MIN = 350;
+
+  private static final int WIDTH_MAX = 5000;
+
+  private static final int WIDTH_INC1 = 250;
+
+  private static final int WIDTH_INC2 = WIDTH_INC1 / 10;
+
+  private static final Field messageLabelField;
+
+  static
+  {
+    Field field = null;
+
+    try
+    {
+      field = TitleAreaDialog.class.getDeclaredField("messageLabel");
+      field.setAccessible(true);
+    }
+    catch (Throwable ex)
+    {
+      field = null;
+    }
+
+    messageLabelField = field;
+  }
+
+  public AbstractDialog(Shell parentShell)
+  {
+    super(parentShell);
+    setShellStyle(SWT.SHELL_TRIM | SWT.BORDER | SWT.APPLICATION_MODAL);
+  }
+
+  @Override
+  public boolean close()
+  {
+    Shell shell = getShell();
+    if (shell != null && !shell.isDisposed())
+    {
+      IDialogSettings settings = getDialogBoundsSettings();
+      if (settings != null)
+      {
+        String message = getMessage();
+
+        int strategy = getDialogBoundsStrategy();
+        if ((strategy & DIALOG_PERSISTSIZE) != 0)
+        {
+          settings.put(DIALOG_MESSAGE, message);
+        }
+      }
+    }
+
+    return super.close();
+  }
+
+  protected IDialogSettings getPluginSettings()
+  {
+    return null;
+  }
+
+  protected String getDialogSettingsName()
+  {
+    return getClass().getSimpleName();
+  }
+
+  @Override
+  protected IDialogSettings getDialogBoundsSettings()
+  {
+    IDialogSettings settings = getPluginSettings();
+    if (settings == null)
+    {
+      return null;
+    }
+
+    String sectionName = getDialogSettingsName();
+    if (sectionName == null)
+    {
+      return null;
+    }
+
+    IDialogSettings section = settings.getSection(sectionName);
+    if (section == null)
+    {
+      section = settings.addNewSection(sectionName);
+    }
+
+    return section;
+  }
+
+  @Override
+  protected int getDialogBoundsStrategy()
+  {
+    return DIALOG_PERSISTSIZE;
+  }
+
+  @Override
+  protected Point getInitialSize()
+  {
+    Shell shell = getShell();
+    Point result = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
+
+    Point minimum = getMinimumSize();
+    result.x = Math.max(result.x, minimum.x);
+    result.y = Math.max(result.y, minimum.y);
+
+    if ((getDialogBoundsStrategy() & DIALOG_PERSISTSIZE) != 0)
+    {
+      IDialogSettings settings = getDialogBoundsSettings();
+      if (settings != null)
+      {
+        if (hasSameFont(settings) && hasSameMessage(settings))
+        {
+          try
+          {
+            int width = settings.getInt(DIALOG_WIDTH);
+            if (width != DIALOG_DEFAULT_BOUNDS)
+            {
+              result.x = width;
+            }
+          }
+          catch (NumberFormatException ex)
+          {
+            //$FALL-THROUGH$
+          }
+
+          try
+          {
+            int height = settings.getInt(DIALOG_HEIGHT);
+            if (height != DIALOG_DEFAULT_BOUNDS)
+            {
+              result.y = height;
+            }
+          }
+          catch (NumberFormatException ex)
+          {
+            //$FALL-THROUGH$
+          }
+
+          return result;
+        }
+      }
+    }
+
+    Text messageLabel;
+
+    try
+    {
+      messageLabel = (Text)messageLabelField.get(this);
+    }
+    catch (Throwable ex)
+    {
+      return result;
+    }
+
+    String message = messageLabel.getText();
+    messageLabel.setText("\n\n");
+
+    int messageHeight = messageLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
+    messageLabel.setText(message);
+
+    result.x = WIDTH_MIN;
+    while (result.x < WIDTH_MAX)
+    {
+      result.x += WIDTH_INC1;
+      shell.setSize(result);
+
+      Point messageSize = messageLabel.computeSize(messageLabel.getSize().x, SWT.DEFAULT);
+      if (messageSize.y <= messageHeight)
+      {
+        break;
+      }
+    }
+
+    result.x -= WIDTH_INC1;
+    while (result.x < WIDTH_MAX)
+    {
+      result.x += WIDTH_INC2;
+      shell.setSize(result);
+
+      Point messageSize = messageLabel.computeSize(messageLabel.getSize().x, SWT.DEFAULT);
+      if (messageSize.y <= messageHeight)
+      {
+        break;
+      }
+    }
+
+    result = shell.computeSize(result.x + WIDTH_INC2, SWT.DEFAULT, true);
+    return result;
+  }
+
+  protected Point getMinimumSize()
+  {
+    return new Point(WIDTH_MIN, 0);
+  }
+
+  @Override
+  protected Control createDialogArea(Composite parent)
+  {
+    Shell shell = getShell();
+
+    ImageDescriptor descriptor = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/LoginBanner.png");
+    final Image titleImage = descriptor.createImage(shell.getDisplay());
+
+    shell.addDisposeListener(new DisposeListener()
+    {
+      @Override
+      public void widgetDisposed(DisposeEvent e)
+      {
+        titleImage.dispose();
+      }
+    });
+
+    setTitleImage(titleImage);
+    return super.createDialogArea(parent);
+  }
+
+  private boolean hasSameFont(IDialogSettings settings)
+  {
+    String previousFontData = settings.get(DIALOG_FONT_DATA);
+    if (StringUtil.isEmpty(previousFontData))
+    {
+      return false;
+    }
+
+    FontData[] fontDatas = JFaceResources.getDialogFont().getFontData();
+    if (fontDatas.length == 0)
+    {
+      return false;
+    }
+
+    String currentFontData = fontDatas[0].toString();
+    return previousFontData.equalsIgnoreCase(currentFontData);
+  }
+
+  private boolean hasSameMessage(IDialogSettings settings)
+  {
+    String previousMessage = settings.get(DIALOG_MESSAGE);
+    if (StringUtil.isEmpty(previousMessage))
+    {
+      return false;
+    }
+
+    String currentMessage = getMessage();
+    return previousMessage.equals(currentMessage);
+  }
+
+  private static String getDialogConstant(String name, String defaultValue)
+  {
+    try
+    {
+      Field field = Dialog.class.getDeclaredField(name);
+      field.setAccessible(true);
+
+      return (String)field.get(null);
+    }
+    catch (Throwable ex)
+    {
+      //$FALL-THROUGH$
+    }
+
+    return defaultValue;
+  }
+}
diff --git a/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/ServiceSelectorComposite.java b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/ServiceSelectorComposite.java
new file mode 100644
index 0000000..f8e04be
--- /dev/null
+++ b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/ServiceSelectorComposite.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.ui;
+
+import org.eclipse.userstorage.IStorageService;
+import org.eclipse.userstorage.ui.internal.ServicesContentProvider;
+import org.eclipse.userstorage.ui.internal.ServicesPreferencePage;
+
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.jface.viewers.ComboViewer;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+
+/**
+ * @author Eike Stepper
+ */
+public class ServiceSelectorComposite extends Composite
+{
+  private final StructuredViewer viewer;
+
+  private final Link link;
+
+  private IStorageService selectedService;
+
+  public ServiceSelectorComposite(Composite parent, int style)
+  {
+    super(parent, style);
+
+    GridLayout gridLayout = new GridLayout(2, false);
+    gridLayout.marginWidth = 0;
+    gridLayout.marginHeight = 0;
+    setLayout(gridLayout);
+
+    ServicesContentProvider contentProvider = new ServicesContentProvider()
+    {
+      @Override
+      public void serviceAdded(IStorageService service)
+      {
+        super.serviceAdded(service);
+        ServiceSelectorComposite.this.serviceAdded(service);
+      }
+
+      @Override
+      public void serviceRemoved(IStorageService service)
+      {
+        super.serviceRemoved(service);
+        ServiceSelectorComposite.this.serviceRemoved(service);
+      }
+    };
+
+    viewer = createViewer(this);
+    viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+    viewer.setContentProvider(contentProvider);
+    viewer.setInput(IStorageService.Registry.INSTANCE);
+    viewer.addSelectionChangedListener(new ISelectionChangedListener()
+    {
+      @Override
+      public void selectionChanged(SelectionChangedEvent event)
+      {
+        selectedService = getViewerSelection();
+      }
+    });
+
+    link = new Link(this, SWT.NONE);
+    link.setText("<a>Configure</a>");
+    link.addSelectionListener(new SelectionAdapter()
+    {
+      @Override
+      public void widgetSelected(SelectionEvent e)
+      {
+        IStorageService service = getViewerSelection();
+
+        PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(getShell(), ServicesPreferencePage.ID, null, service);
+        dialog.open();
+      }
+    });
+  }
+
+  public final IStorageService getSelectedService()
+  {
+    return selectedService;
+  }
+
+  public final void setSelectedService(IStorageService service)
+  {
+    if (service != selectedService)
+    {
+      selectedService = service;
+      viewer.setSelection(new StructuredSelection(service));
+    }
+  }
+
+  @Override
+  public boolean setFocus()
+  {
+    return viewer.getControl().setFocus();
+  }
+
+  @Override
+  public void setEnabled(boolean enabled)
+  {
+    super.setEnabled(enabled);
+    viewer.getControl().setEnabled(enabled);
+    link.setEnabled(enabled);
+  }
+
+  protected void serviceAdded(IStorageService service)
+  {
+    // Do nothing.
+  }
+
+  protected void serviceRemoved(IStorageService service)
+  {
+    // Do nothing.
+  }
+
+  protected StructuredViewer createViewer(Composite parent)
+  {
+    return new ComboViewer(parent, SWT.READ_ONLY);
+  }
+
+  private IStorageService getViewerSelection()
+  {
+    IStructuredSelection selection = (IStructuredSelection)viewer.getSelection();
+    return (IStorageService)selection.getFirstElement();
+  }
+
+  public static boolean isShowServices()
+  {
+    String property = System.getProperty("org.eclipse.userstorage.ui.showServices", "auto");
+    if ("auto".equalsIgnoreCase(property))
+    {
+      return IStorageService.Registry.INSTANCE.getServices().length > 1;
+    }
+
+    return Boolean.parseBoolean(property);
+  }
+}
diff --git a/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/StorageConfigurationComposite.java b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/StorageConfigurationComposite.java
new file mode 100644
index 0000000..c075a06
--- /dev/null
+++ b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/StorageConfigurationComposite.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.ui;
+
+import org.eclipse.userstorage.IStorage;
+import org.eclipse.userstorage.IStorageService;
+import org.eclipse.userstorage.internal.StorageServiceRegistry;
+
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * @author Eike Stepper
+ */
+public class StorageConfigurationComposite extends ServiceSelectorComposite
+{
+  private final IStorage storage;
+
+  private IStorageService defaultService;
+
+  public StorageConfigurationComposite(Composite parent, int style, IStorage storage)
+  {
+    super(parent, style);
+    this.storage = storage;
+
+    defaultService = storage.getService();
+    performDefaults();
+  }
+
+  public final IStorage getStorage()
+  {
+    return storage;
+  }
+
+  public final boolean isDirty()
+  {
+    IStorageService selectedService = getSelectedService();
+    return selectedService != defaultService;
+  }
+
+  public final boolean performDefaults()
+  {
+    if (isDirty())
+    {
+      setSelectedService(defaultService);
+      return true;
+    }
+
+    return false;
+  }
+
+  public final boolean performApply()
+  {
+    if (isDirty())
+    {
+      defaultService = getSelectedService();
+      storage.setService(defaultService);
+      return true;
+    }
+
+    return false;
+  }
+
+  @Override
+  protected void serviceRemoved(IStorageService service)
+  {
+    IStorageService selectedService = getSelectedService();
+    if (service == selectedService)
+    {
+      service = StorageServiceRegistry.INSTANCE.getFirstService();
+      setSelectedService(service);
+    }
+  }
+}
diff --git a/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/Activator.java b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/Activator.java
new file mode 100644
index 0000000..89265a4
--- /dev/null
+++ b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/Activator.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.ui.internal;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+import org.osgi.framework.BundleContext;
+
+/**
+ * @author Eike Stepper
+ */
+public class Activator extends AbstractUIPlugin
+{
+  public static final String PLUGIN_ID = "org.eclipse.userstorage.ui"; //$NON-NLS-1$
+
+  private static Activator plugin;
+
+  public Activator()
+  {
+  }
+
+  @Override
+  public void start(BundleContext context) throws Exception
+  {
+    super.start(context);
+    plugin = this;
+  }
+
+  @Override
+  public void stop(BundleContext context) throws Exception
+  {
+    plugin = null;
+    super.stop(context);
+  }
+
+  public static Activator getDefault()
+  {
+    return plugin;
+  }
+
+  public static void log(IStatus status)
+  {
+    getDefault().getLog().log(status);
+  }
+
+  public static void log(Throwable t, int severity)
+  {
+    log(getStatus(t, severity));
+  }
+
+  public static String log(Throwable t)
+  {
+    IStatus status = getStatus(t);
+    log(status);
+    return status.getMessage();
+  }
+
+  public static IStatus getStatus(Object obj)
+  {
+    if (obj instanceof CoreException)
+    {
+      CoreException coreException = (CoreException)obj;
+      return coreException.getStatus();
+    }
+
+    if (obj instanceof Throwable)
+    {
+      Throwable t = (Throwable)obj;
+      return getStatus(t, IStatus.ERROR);
+    }
+
+    return new Status(IStatus.INFO, PLUGIN_ID, obj.toString(), null);
+  }
+
+  public static IStatus getStatus(Throwable t, int severity)
+  {
+    String msg = t.getLocalizedMessage();
+    if (msg == null || msg.length() == 0)
+    {
+      msg = t.getClass().getName();
+    }
+
+    return new Status(severity, PLUGIN_ID, msg, t);
+  }
+}
diff --git a/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/AddServiceDialog.java b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/AddServiceDialog.java
new file mode 100644
index 0000000..acaf415
--- /dev/null
+++ b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/AddServiceDialog.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.ui.internal;
+
+import org.eclipse.userstorage.IStorageService;
+import org.eclipse.userstorage.internal.util.StringUtil;
+import org.eclipse.userstorage.ui.AbstractDialog;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * @author Eike Stepper
+ */
+public class AddServiceDialog extends AbstractDialog implements ModifyListener
+{
+  private Text serviceLabelText;
+
+  private Text serviceURIText;
+
+  private Text createAccountURIText;
+
+  private Text editAccountURIText;
+
+  private Text recoverPasswordURIText;
+
+  private Text termsOfUseLinkText;
+
+  private Button okButton;
+
+  private String serviceLabel;
+
+  private URI serviceURI;
+
+  private URI createAccountURI;
+
+  private URI editAccountURI;
+
+  private URI recoverPasswordURI;
+
+  private String termsOfUseLink;
+
+  public AddServiceDialog(Shell parentShell)
+  {
+    super(parentShell);
+  }
+
+  public String getServiceLabel()
+  {
+    return serviceLabel;
+  }
+
+  public URI getServiceURI()
+  {
+    return serviceURI;
+  }
+
+  public URI getCreateAccountURI()
+  {
+    return createAccountURI;
+  }
+
+  public URI getEditAccountURI()
+  {
+    return editAccountURI;
+  }
+
+  public URI getRecoverPasswordURI()
+  {
+    return recoverPasswordURI;
+  }
+
+  public String getTermsOfUseLink()
+  {
+    return termsOfUseLink;
+  }
+
+  @Override
+  protected IDialogSettings getPluginSettings()
+  {
+    return Activator.getDefault().getDialogSettings();
+  }
+
+  @Override
+  protected Point getMinimumSize()
+  {
+    return new Point(600, 350);
+  }
+
+  @Override
+  protected void configureShell(Shell newShell)
+  {
+    super.configureShell(newShell);
+    newShell.setText("User Storage Service");
+  }
+
+  @Override
+  protected Control createDialogArea(Composite parent)
+  {
+    setTitle("Add Service");
+    setMessage("Enter a service label and a unique service URI.");
+    initializeDialogUnits(parent);
+
+    Composite area = (Composite)super.createDialogArea(parent);
+
+    GridLayout containerGridLayout = new GridLayout();
+    containerGridLayout.numColumns = 2;
+
+    Composite container = new Composite(area, SWT.NONE);
+    container.setLayoutData(new GridData(GridData.FILL_BOTH));
+    container.setLayout(containerGridLayout);
+
+    Label serviceLabelLabel = new Label(container, SWT.NONE);
+    serviceLabelLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+    serviceLabelLabel.setText("Service label:");
+
+    serviceLabelText = new Text(container, SWT.BORDER);
+    serviceLabelText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+    serviceLabelText.addModifyListener(this);
+
+    Label serviceURILabel = new Label(container, SWT.NONE);
+    serviceURILabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+    serviceURILabel.setText("Service URI:");
+
+    serviceURIText = new Text(container, SWT.BORDER);
+    serviceURIText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+    serviceURIText.addModifyListener(this);
+
+    Label createAccountURILabel = new Label(container, SWT.NONE);
+    createAccountURILabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+    createAccountURILabel.setText("Create account URI:");
+
+    createAccountURIText = new Text(container, SWT.BORDER);
+    createAccountURIText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+    createAccountURIText.addModifyListener(this);
+
+    Label editAccountURILabel = new Label(container, SWT.NONE);
+    editAccountURILabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+    editAccountURILabel.setText("Edit account URI:");
+
+    editAccountURIText = new Text(container, SWT.BORDER);
+    editAccountURIText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+    editAccountURIText.addModifyListener(this);
+
+    Label recoverPasswordURILabel = new Label(container, SWT.NONE);
+    recoverPasswordURILabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+    recoverPasswordURILabel.setText("Recover password URI:");
+
+    recoverPasswordURIText = new Text(container, SWT.BORDER);
+    recoverPasswordURIText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+    recoverPasswordURIText.addModifyListener(this);
+
+    Label termsOfUseLinkLabel = new Label(container, SWT.NONE);
+    termsOfUseLinkLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+    termsOfUseLinkLabel.setText("Terms of Use Link:");
+
+    termsOfUseLinkText = new Text(container, SWT.BORDER);
+    termsOfUseLinkText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+    termsOfUseLinkText.addModifyListener(this);
+
+    return area;
+  }
+
+  @Override
+  protected void createButtonsForButtonBar(Composite parent)
+  {
+    okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+    okButton.setEnabled(false);
+
+    createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+  }
+
+  @Override
+  public void modifyText(ModifyEvent e)
+  {
+    okButton.setEnabled(true);
+    setErrorMessage(null);
+
+    serviceLabel = serviceLabelText.getText();
+
+    try
+    {
+      String text = serviceURIText.getText();
+      if (StringUtil.isEmpty(text))
+      {
+        serviceURI = null;
+      }
+      else
+      {
+        serviceURI = new URI(text);
+
+        if (IStorageService.Registry.INSTANCE.getService(serviceURI) != null)
+        {
+          setErrorMessage("The service URI is not unique.");
+          okButton.setEnabled(false);
+          return;
+        }
+      }
+    }
+    catch (URISyntaxException ex)
+    {
+      setErrorMessage("The service URI is invalid.");
+      okButton.setEnabled(false);
+      return;
+    }
+
+    try
+    {
+      String text = createAccountURIText.getText();
+      createAccountURI = StringUtil.isEmpty(text) ? null : new URI(text);
+    }
+    catch (URISyntaxException ex)
+    {
+      setErrorMessage("The create account URI is invalid.");
+      okButton.setEnabled(false);
+      return;
+    }
+
+    try
+    {
+      String text = editAccountURIText.getText();
+      editAccountURI = StringUtil.isEmpty(text) ? null : new URI(text);
+    }
+    catch (URISyntaxException ex)
+    {
+      setErrorMessage("The edit account URI is invalid.");
+      okButton.setEnabled(false);
+      return;
+    }
+
+    try
+    {
+      String text = recoverPasswordURIText.getText();
+      recoverPasswordURI = StringUtil.isEmpty(text) ? null : new URI(text);
+    }
+    catch (URISyntaxException ex)
+    {
+      setErrorMessage("The recover password URI is invalid.");
+      okButton.setEnabled(false);
+      return;
+    }
+
+    String text = termsOfUseLinkText.getText();
+    termsOfUseLink = StringUtil.isEmpty(text) ? null : text;
+
+    if (StringUtil.isEmpty(serviceLabel))
+    {
+      okButton.setEnabled(false);
+      return;
+    }
+
+    if (serviceURI == null)
+    {
+      okButton.setEnabled(false);
+      return;
+    }
+  }
+}
diff --git a/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/CredentialsComposite.java b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/CredentialsComposite.java
new file mode 100644
index 0000000..db0fa0f
--- /dev/null
+++ b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/CredentialsComposite.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.ui.internal;
+
+import org.eclipse.userstorage.IStorageService;
+import org.eclipse.userstorage.internal.StorageService;
+import org.eclipse.userstorage.internal.util.StringUtil;
+import org.eclipse.userstorage.spi.Credentials;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Text;
+
+import java.net.URI;
+import java.util.concurrent.Callable;
+
+/**
+ * @author Eike Stepper
+ */
+public class CredentialsComposite extends Composite
+{
+  public static final Point INITIAL_SIZE = new Point(600, 500);
+
+  private final Callable<URI> createAccountURIProvider = new Callable<URI>()
+  {
+    @Override
+    public URI call() throws Exception
+    {
+      return service.getCreateAccountURI();
+    }
+  };
+
+  private final Callable<URI> editAccountURIProvider = new Callable<URI>()
+  {
+    @Override
+    public URI call() throws Exception
+    {
+      return service.getEditAccountURI();
+    }
+  };
+
+  private final Callable<URI> recoverPasswordURIProvider = new Callable<URI>()
+  {
+    @Override
+    public URI call() throws Exception
+    {
+      return service.getRecoverPasswordURI();
+    }
+  };
+
+  private final ModifyListener modifyListener = new ModifyListener()
+  {
+    @Override
+    public void modifyText(ModifyEvent e)
+    {
+      credentials = new Credentials(usernameText.getText(), passwordText.getText());
+      updateEnablement();
+    }
+  };
+
+  private final boolean showServiceCredentials;
+
+  private IStorageService service;
+
+  private Credentials credentials;
+
+  private Label usernameLabel;
+
+  private Text usernameText;
+
+  private Label passwordLabel;
+
+  private Text passwordText;
+
+  private Label horizontalSpacer;
+
+  private boolean termsOfUseAgreed;
+
+  private Button termsOfUseButton;
+
+  private MultiLink termsOfUseMultiLink;
+
+  private Label verticalSpacer;
+
+  private Link createAccountLink;
+
+  private Link editAccountLink;
+
+  private Link recoverPasswordLink;
+
+  private boolean valid;
+
+  public CredentialsComposite(Composite parent, int style, int marginWidth, int marginHeight, boolean showServiceCredentials)
+  {
+    super(parent, style);
+    this.showServiceCredentials = showServiceCredentials;
+
+    GridLayout layout = UIUtil.createGridLayout(getGridColumns());
+    layout.marginWidth = marginWidth;
+    layout.marginHeight = marginHeight;
+    setLayout(layout);
+
+    createUI(this, layout.numColumns);
+    setCredentials(null);
+  }
+
+  public IStorageService getService()
+  {
+    return service;
+  }
+
+  public void setService(IStorageService service)
+  {
+    this.service = service;
+    if (service != null)
+    {
+      String termsOfUse = service.getTermsOfUseLink();
+      if (StringUtil.isEmpty(termsOfUse))
+      {
+        hideTermsOfUse();
+      }
+      else
+      {
+        int columns = getGridColumns();
+
+        horizontalSpacer.setVisible(true);
+        horizontalSpacer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
+
+        termsOfUseButton.setVisible(true);
+        termsOfUseButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+        termsOfUseMultiLink.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, false, columns - 2, 1));
+        termsOfUseMultiLink.setVisible(true);
+        termsOfUseMultiLink.setText(termsOfUse);
+
+        verticalSpacer.setVisible(true);
+        verticalSpacer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, columns, 1));
+      }
+
+      if (showServiceCredentials)
+      {
+        setCredentials(((StorageService)service).getCredentials());
+        setTermsOfUseAgreed(((StorageService)service).isTermsOfUseAgreed());
+      }
+    }
+    else
+    {
+      hideTermsOfUse();
+
+      if (showServiceCredentials)
+      {
+        setCredentials(null);
+        setTermsOfUseAgreed(false);
+      }
+    }
+
+    updateEnablement();
+    layout();
+  }
+
+  public boolean isTermsOfUseAgreed()
+  {
+    return termsOfUseAgreed;
+  }
+
+  public void setTermsOfUseAgreed(boolean termsOfUseAgreed)
+  {
+    this.termsOfUseAgreed = termsOfUseAgreed;
+    termsOfUseButton.setSelection(termsOfUseAgreed);
+    updateEnablement();
+  }
+
+  public Credentials getCredentials()
+  {
+    return credentials;
+  }
+
+  public void setCredentials(Credentials credentials)
+  {
+    this.credentials = credentials;
+    if (credentials != null)
+    {
+      usernameText.setText(StringUtil.safe(credentials.getUsername()));
+      passwordText.setText(StringUtil.safe(credentials.getPassword()));
+    }
+    else
+    {
+      usernameText.setText(StringUtil.EMPTY);
+      passwordText.setText(StringUtil.EMPTY);
+    }
+  }
+
+  public int getGridColumns()
+  {
+    return 3;
+  }
+
+  public boolean isValid()
+  {
+    return valid;
+  }
+
+  @Override
+  public void setEnabled(boolean enabled)
+  {
+    super.setEnabled(true);
+    usernameLabel.setEnabled(enabled);
+    usernameText.setEnabled(enabled);
+    passwordLabel.setEnabled(enabled);
+    passwordText.setEnabled(enabled);
+    createAccountLink.setEnabled(enabled);
+    editAccountLink.setEnabled(enabled);
+    recoverPasswordLink.setEnabled(enabled);
+  }
+
+  protected void createUI(Composite parent, int columns)
+  {
+    usernameLabel = new Label(parent, SWT.NONE);
+    usernameLabel.setText("User name:");
+    usernameText = new Text(parent, SWT.BORDER);
+    usernameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, columns - 1, 1));
+    usernameText.addModifyListener(modifyListener);
+
+    passwordLabel = new Label(parent, SWT.NONE);
+    passwordLabel.setText("Password:");
+    passwordText = new Text(parent, SWT.BORDER | SWT.PASSWORD);
+    passwordText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, columns - 1, 1));
+    passwordText.addModifyListener(modifyListener);
+
+    horizontalSpacer = new Label(parent, SWT.NONE);
+    termsOfUseButton = new Button(parent, SWT.CHECK);
+    termsOfUseButton.addSelectionListener(new SelectionAdapter()
+    {
+      @Override
+      public void widgetSelected(SelectionEvent e)
+      {
+        termsOfUseAgreed = termsOfUseButton.getSelection();
+        updateEnablement();
+      }
+    });
+
+    termsOfUseMultiLink = new MultiLink.ForSystemBrowser(parent, SWT.WRAP);
+    verticalSpacer = new Label(parent, SWT.NONE);
+
+    createAccountLink = createLink(parent, columns, "Create an account", createAccountURIProvider);
+    editAccountLink = createLink(parent, columns, "Edit your account", editAccountURIProvider);
+    recoverPasswordLink = createLink(parent, columns, "Recover your password", recoverPasswordURIProvider);
+
+    hideTermsOfUse();
+  }
+
+  protected void validate()
+  {
+  }
+
+  private void updateEnablement()
+  {
+    boolean enabled = isEnabled() && service != null;
+
+    enableLink(createAccountLink, createAccountURIProvider, enabled);
+    enableLink(editAccountLink, editAccountURIProvider, enabled);
+    enableLink(recoverPasswordLink, recoverPasswordURIProvider, enabled);
+
+    if (enabled)
+    {
+      String termsOfUseLink = service.getTermsOfUseLink();
+      if (!StringUtil.isEmpty(termsOfUseLink))
+      {
+        if (!termsOfUseAgreed)
+        {
+          valid = false;
+          validate();
+          return;
+        }
+      }
+    }
+
+    valid = enabled;
+    validate();
+  }
+
+  private Link createLink(Composite parent, int columns, final String label, final Callable<URI> uriProvider)
+  {
+    new Label(parent, SWT.NONE); // Skip first column.
+
+    final Link link = new Link(parent, SWT.NONE);
+    link.setText("<a>" + label + "</a>");
+    link.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, columns - 1, 1));
+    link.addSelectionListener(new SelectionAdapter()
+    {
+      @Override
+      public void widgetSelected(SelectionEvent e)
+      {
+        if (link.isEnabled())
+        {
+          try
+          {
+            String uri = uriProvider.call().toString();
+            SystemBrowser.openSafe(getShell(), uri, "Go to " + uri + " to " + label.toLowerCase() + ".");
+          }
+          catch (Exception ex)
+          {
+            Activator.log(ex);
+          }
+        }
+      }
+    });
+
+    return link;
+  }
+
+  private void enableLink(Link link, Callable<URI> uriProvider, boolean enabled)
+  {
+    try
+    {
+      link.setEnabled(enabled && uriProvider.call() != null);
+    }
+    catch (Exception ex)
+    {
+      //$FALL-THROUGH$
+    }
+  }
+
+  private void hideTermsOfUse()
+  {
+    horizontalSpacer.setVisible(false);
+    horizontalSpacer.setLayoutData(emptyGridData(1, 1));
+
+    termsOfUseButton.setVisible(false);
+    termsOfUseButton.setLayoutData(emptyGridData(1, 1));
+
+    termsOfUseMultiLink.setVisible(false);
+    termsOfUseMultiLink.setLayoutData(emptyGridData(getGridColumns() - 2, 1));
+    termsOfUseMultiLink.setText(StringUtil.EMPTY);
+
+    verticalSpacer.setVisible(false);
+    verticalSpacer.setLayoutData(emptyGridData(getGridColumns(), 1));
+  }
+
+  private static GridData emptyGridData(int horizontalSpan, int verticalSpan)
+  {
+    GridData gridData = new GridData(0, 0);
+    gridData.horizontalSpan = horizontalSpan;
+    gridData.verticalSpan = verticalSpan;
+    return gridData;
+  }
+}
diff --git a/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/CredentialsDialog.java b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/CredentialsDialog.java
new file mode 100644
index 0000000..33f11e7
--- /dev/null
+++ b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/CredentialsDialog.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.ui.internal;
+
+import org.eclipse.userstorage.IStorageService;
+import org.eclipse.userstorage.internal.StorageService;
+import org.eclipse.userstorage.internal.util.StringUtil;
+import org.eclipse.userstorage.spi.Credentials;
+import org.eclipse.userstorage.ui.AbstractDialog;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * @author Eike Stepper
+ */
+public class CredentialsDialog extends AbstractDialog
+{
+  private final IStorageService service;
+
+  private final boolean reauthentication;
+
+  private Credentials credentials;
+
+  private CredentialsComposite credentialsComposite;
+
+  private Button okButton;
+
+  public CredentialsDialog(Shell parentShell, IStorageService service, boolean reauthentication)
+  {
+    super(parentShell);
+    this.service = service;
+    this.reauthentication = reauthentication;
+  }
+
+  public final IStorageService getService()
+  {
+    return service;
+  }
+
+  public final Credentials getCredentials()
+  {
+    return credentials;
+  }
+
+  @Override
+  protected IDialogSettings getPluginSettings()
+  {
+    return Activator.getDefault().getDialogSettings();
+  }
+
+  @Override
+  protected void configureShell(Shell newShell)
+  {
+    super.configureShell(newShell);
+
+    String shellText = "User Storage Service";
+
+    String authority = service.getServiceURI().getAuthority();
+    if (authority != null && authority.endsWith(".eclipse.org"))
+    {
+      shellText = "Eclipse " + shellText;
+    }
+
+    newShell.setText(shellText);
+  }
+
+  @Override
+  protected Control createDialogArea(Composite parent)
+  {
+    setTitle("Login");
+    if (reauthentication)
+    {
+      setErrorMessage("You could not be logged in to your " + service.getServiceLabel() + " account. Please try again.");
+    }
+    else
+    {
+      setMessage("Enter the login information for your " + service.getServiceLabel() + " account.");
+    }
+
+    initializeDialogUnits(parent);
+    Composite area = (Composite)super.createDialogArea(parent);
+
+    credentialsComposite = new CredentialsComposite(area, SWT.NONE, 10, 10, true)
+    {
+      @Override
+      protected void validate()
+      {
+        validatePage();
+      }
+    };
+
+    credentialsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+    credentialsComposite.setService(service);
+    Dialog.applyDialogFont(credentialsComposite);
+
+    return area;
+  }
+
+  @Override
+  protected void createButtonsForButtonBar(Composite parent)
+  {
+    super.createButtonsForButtonBar(parent);
+    okButton = getButton(IDialogConstants.OK_ID);
+    validatePage();
+  }
+
+  @Override
+  protected void okPressed()
+  {
+    ((StorageService)service).setTermsOfUseAgreed(credentialsComposite.isTermsOfUseAgreed());
+    credentials = credentialsComposite.getCredentials();
+    super.okPressed();
+  }
+
+  protected boolean isPageValid()
+  {
+    String termsOfUseLink = service.getTermsOfUseLink();
+    if (!StringUtil.isEmpty(termsOfUseLink))
+    {
+      boolean termsOfUseAgreed = credentialsComposite.isTermsOfUseAgreed();
+      if (!termsOfUseAgreed)
+      {
+        return false;
+      }
+    }
+
+    Credentials credentials = credentialsComposite.getCredentials();
+    if (credentials == null)
+    {
+      return false;
+    }
+
+    if (StringUtil.isEmpty(credentials.getUsername()))
+    {
+      return false;
+    }
+
+    if (StringUtil.isEmpty(credentials.getPassword()))
+    {
+      return false;
+    }
+
+    return true;
+  }
+
+  private void validatePage()
+  {
+    if (okButton != null)
+    {
+      boolean valid = credentialsComposite.isValid();
+      okButton.setEnabled(valid);
+    }
+  }
+}
diff --git a/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/DialogCredentialsProvider.java b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/DialogCredentialsProvider.java
new file mode 100644
index 0000000..0594865
--- /dev/null
+++ b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/DialogCredentialsProvider.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.ui.internal;
+
+import org.eclipse.userstorage.IStorageService;
+import org.eclipse.userstorage.spi.Credentials;
+import org.eclipse.userstorage.spi.ICredentialsProvider;
+
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * @author Eike Stepper
+ */
+public final class DialogCredentialsProvider implements ICredentialsProvider
+{
+  public static final DialogCredentialsProvider INSTANCE = new DialogCredentialsProvider();
+
+  @Override
+  public Credentials provideCredentials(final IStorageService service, final boolean reauthentication)
+  {
+    final Credentials[] credentials = { null };
+
+    try
+    {
+      final Shell shell = UIUtil.getShell();
+      shell.getDisplay().syncExec(new Runnable()
+      {
+        @Override
+        public void run()
+        {
+          CredentialsDialog dialog = new CredentialsDialog(shell, service, reauthentication);
+          if (dialog.open() == CredentialsDialog.OK)
+          {
+            credentials[0] = dialog.getCredentials();
+          }
+        }
+      });
+    }
+    catch (Throwable ex)
+    {
+      Activator.log(ex);
+    }
+
+    return credentials[0];
+  }
+}
diff --git a/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/MultiLink.java b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/MultiLink.java
new file mode 100644
index 0000000..ed633b3
--- /dev/null
+++ b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/MultiLink.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.ui.internal;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Link;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class MultiLink extends Composite
+{
+  private static final Pattern PATTERN = Pattern.compile("<a href=[\"']([^\"']+)[\"']>([^<]+)</a>");
+
+  private final Map<String, String> hrefs = new HashMap<String, String>();
+
+  private Link link;
+
+  private String text;
+
+  public MultiLink(Composite parent, int style)
+  {
+    super(parent, SWT.NONE);
+    setLayout(new FillLayout());
+
+    link = new Link(this, style);
+    link.addSelectionListener(new SelectionAdapter()
+    {
+      @Override
+      public void widgetSelected(SelectionEvent e)
+      {
+        String label = e.text;
+
+        String href = hrefs.get(label);
+        if (href != null)
+        {
+          linkSelected(label, href);
+        }
+      }
+    });
+  }
+
+  public String getText()
+  {
+    return text;
+  }
+
+  public void setText(String text)
+  {
+    this.text = text;
+
+    hrefs.clear();
+    StringBuffer buffer = new StringBuffer();
+
+    Matcher matcher = PATTERN.matcher(text);
+    while (matcher.find())
+    {
+      String href = matcher.group(1);
+      String label = matcher.group(2);
+      hrefs.put(label, href);
+      matcher.appendReplacement(buffer, "<a>" + label + "</a>");
+    }
+
+    matcher.appendTail(buffer);
+    link.setText(buffer.toString());
+  }
+
+  @Override
+  public void setEnabled(boolean enabled)
+  {
+    super.setEnabled(enabled);
+    link.setEnabled(enabled);
+  }
+
+  @Override
+  public void setVisible(boolean visible)
+  {
+    super.setVisible(visible);
+    link.setVisible(visible);
+  }
+
+  @Override
+  public boolean setFocus()
+  {
+    return link.setFocus();
+  }
+
+  protected abstract void linkSelected(String label, String href);
+
+  /**
+   * @author Eike Stepper
+   */
+  public static class ForSystemBrowser extends MultiLink
+  {
+    public ForSystemBrowser(Composite parent, int style)
+    {
+      super(parent, style);
+    }
+
+    @Override
+    protected void linkSelected(String label, String href)
+    {
+      SystemBrowser.openSafe(getShell(), href, "Go to " + href + " to read the " + label + ".");
+    }
+  }
+}
diff --git a/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/ServicesContentProvider.java b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/ServicesContentProvider.java
new file mode 100644
index 0000000..5ffd239
--- /dev/null
+++ b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/ServicesContentProvider.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.ui.internal;
+
+import org.eclipse.userstorage.IStorageService;
+import org.eclipse.userstorage.IStorageService.Registry;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.widgets.Control;
+
+import java.util.Arrays;
+
+/**
+ * @author Eike Stepper
+ */
+public class ServicesContentProvider implements IStructuredContentProvider, IStorageService.Registry.Listener
+{
+  private static final Object[] NO_ELEMENTS = {};
+
+  private Viewer viewer;
+
+  private IStorageService.Registry registry;
+
+  public ServicesContentProvider()
+  {
+  }
+
+  @Override
+  public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
+  {
+    dispose();
+
+    this.viewer = viewer;
+    registry = (Registry)newInput;
+
+    if (registry != null)
+    {
+      registry.addListener(this);
+    }
+  }
+
+  @Override
+  public void serviceAdded(IStorageService service)
+  {
+    refreshViewer();
+  }
+
+  @Override
+  public void serviceRemoved(IStorageService service)
+  {
+    refreshViewer();
+  }
+
+  @Override
+  public Object[] getElements(Object inputElement)
+  {
+    if (registry != null)
+    {
+      IStorageService[] services = registry.getServices();
+      Arrays.sort(services);
+      return services;
+    }
+
+    return NO_ELEMENTS;
+  }
+
+  @Override
+  public void dispose()
+  {
+    if (registry != null)
+    {
+      registry.removeListener(this);
+    }
+  }
+
+  private void refreshViewer()
+  {
+    if (viewer != null)
+    {
+      final Control control = viewer.getControl();
+      control.getDisplay().asyncExec(new Runnable()
+      {
+        @Override
+        public void run()
+        {
+          if (!control.isDisposed())
+          {
+            viewer.refresh();
+          }
+        }
+      });
+    }
+  }
+}
diff --git a/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/ServicesLabelProvider.java b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/ServicesLabelProvider.java
new file mode 100644
index 0000000..18af586
--- /dev/null
+++ b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/ServicesLabelProvider.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.ui.internal;
+
+import org.eclipse.userstorage.IStorageService;
+
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * @author Eike Stepper
+ */
+public class ServicesLabelProvider extends LabelProvider
+{
+  private final Image serviceImage = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Service.gif").createImage();
+
+  private final Image dynamicServiceImage = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/DynamicService.gif").createImage();
+
+  public ServicesLabelProvider()
+  {
+  }
+
+  @Override
+  public Image getImage(Object element)
+  {
+    if (element instanceof IStorageService.Dynamic)
+    {
+      return dynamicServiceImage;
+    }
+
+    return serviceImage;
+  }
+
+  @Override
+  public String getText(Object element)
+  {
+    return ((IStorageService)element).getServiceLabel();
+  }
+
+  @Override
+  public void dispose()
+  {
+    dynamicServiceImage.dispose();
+    serviceImage.dispose();
+    super.dispose();
+  }
+}
diff --git a/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/ServicesPreferencePage.java b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/ServicesPreferencePage.java
new file mode 100644
index 0000000..a154ae2
--- /dev/null
+++ b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/ServicesPreferencePage.java
@@ -0,0 +1,494 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.ui.internal;
+
+import org.eclipse.userstorage.IBlob;
+import org.eclipse.userstorage.IStorage;
+import org.eclipse.userstorage.IStorageService;
+import org.eclipse.userstorage.IStorageService.Registry;
+import org.eclipse.userstorage.StorageFactory;
+import org.eclipse.userstorage.internal.StorageService;
+import org.eclipse.userstorage.internal.util.StringUtil;
+import org.eclipse.userstorage.spi.Credentials;
+import org.eclipse.userstorage.ui.ServiceSelectorComposite;
+
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.layout.TableColumnLayout;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * @author Eike Stepper
+ */
+public class ServicesPreferencePage extends PreferencePage implements IWorkbenchPreferencePage
+{
+  public static final String ID = "org.eclipse.userstorage.ui.ServicesPreferencePage";
+
+  private static final Registry REGISTRY = IStorageService.Registry.INSTANCE;
+
+  private Map<IStorageService, Credentials> credentialsMap = new HashMap<IStorageService, Credentials>();
+
+  private Map<IStorageService, Boolean> termsOfUseAgreedMap = new HashMap<IStorageService, Boolean>();
+
+  private TableViewer servicesViewer;
+
+  private CredentialsComposite credentialsComposite;
+
+  private Button addButton;
+
+  private Button removeButton;
+
+  private Button testButton;
+
+  private IStorageService selectedService;
+
+  private boolean skipValidate;
+
+  public ServicesPreferencePage()
+  {
+    super("User Storage Service");
+  }
+
+  @Override
+  public void init(IWorkbench workbench)
+  {
+    // Do nothing.
+  }
+
+  @Override
+  public void applyData(Object data)
+  {
+    if (data instanceof IStorageService)
+    {
+      IStorageService service = (IStorageService)data;
+      setSelectedService(service);
+    }
+  }
+
+  @Override
+  public void createControl(Composite parent)
+  {
+    super.createControl(parent);
+    updateEnablement();
+  }
+
+  @Override
+  protected Control createContents(final Composite parent)
+  {
+    final ServicesContentProvider contentProvider = ServiceSelectorComposite.isShowServices() ? new ServicesContentProvider() : null;
+
+    final Composite mainArea = createArea(parent, 2);
+    mainArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+    Composite leftArea = createArea(mainArea, 1);
+    leftArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+    if (contentProvider != null)
+    {
+      Label servicesLabel = new Label(leftArea, SWT.NONE);
+      servicesLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+      servicesLabel.setText("Services:");
+
+      TableColumnLayout tableLayout = new TableColumnLayout();
+      Composite tableComposite = new Composite(leftArea, SWT.NONE);
+      tableComposite.setLayout(tableLayout);
+      tableComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+      servicesViewer = new TableViewer(tableComposite, SWT.BORDER);
+      servicesViewer.setContentProvider(contentProvider);
+      servicesViewer.setLabelProvider(new ServicesLabelProvider());
+      servicesViewer.setInput(REGISTRY);
+      servicesViewer.addSelectionChangedListener(new ISelectionChangedListener()
+      {
+        @Override
+        public void selectionChanged(SelectionChangedEvent event)
+        {
+          IStructuredSelection selection = (IStructuredSelection)event.getSelection();
+          setSelectedService((IStorageService)selection.getFirstElement());
+        }
+      });
+
+      TableColumn tableColumn = new TableColumn(servicesViewer.getTable(), SWT.LEFT);
+      tableLayout.setColumnData(tableColumn, new ColumnWeightData(100));
+
+      new Label(leftArea, SWT.NONE);
+    }
+
+    credentialsComposite = new CredentialsComposite(leftArea, SWT.NONE, 0, 0, false)
+    {
+      @Override
+      protected void validate()
+      {
+        if (selectedService != null && !skipValidate)
+        {
+          Credentials credentials = getCredentials();
+          boolean termsOfUseAgreed = isTermsOfUseAgreed();
+          update(credentials, termsOfUseAgreed);
+        }
+      }
+    };
+
+    credentialsComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+
+    if (contentProvider != null)
+    {
+      Composite rightArea = createArea(mainArea, 1);
+      rightArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+
+      new Label(rightArea, SWT.NONE);
+
+      addButton = new Button(rightArea, SWT.NONE);
+      addButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+      addButton.setText("Add...");
+      addButton.addSelectionListener(new SelectionAdapter()
+      {
+        @Override
+        public void widgetSelected(SelectionEvent e)
+        {
+          AddServiceDialog dialog = new AddServiceDialog(getShell());
+          if (dialog.open() == AddServiceDialog.OK)
+          {
+            String serviceLabel = dialog.getServiceLabel();
+            URI serviceURI = dialog.getServiceURI();
+            URI createAccountURI = dialog.getCreateAccountURI();
+            URI editAccountURI = dialog.getEditAccountURI();
+            URI recoverPasswordURI = dialog.getRecoverPasswordURI();
+            String termsOfUseLink = dialog.getTermsOfUseLink();
+
+            REGISTRY.addService(serviceLabel, serviceURI, createAccountURI, editAccountURI, recoverPasswordURI, termsOfUseLink);
+          }
+        }
+      });
+
+      removeButton = new Button(rightArea, SWT.NONE);
+      removeButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+      removeButton.setText("Remove");
+      removeButton.addSelectionListener(new SelectionAdapter()
+      {
+        @Override
+        public void widgetSelected(SelectionEvent e)
+        {
+          if (selectedService instanceof IStorageService.Dynamic)
+          {
+            IStorageService.Dynamic dynamicService = (IStorageService.Dynamic)selectedService;
+            Object[] elements = contentProvider.getElements(null);
+            final int currentIndex = getCurrentIndex(elements, dynamicService);
+
+            if (MessageDialog.openQuestion(getShell(), "Remove Service",
+                "Do you really want to remove the '" + dynamicService.getServiceLabel() + "' service?"))
+            {
+              dynamicService.remove();
+
+              final Control control = servicesViewer.getControl();
+              control.getDisplay().asyncExec(new Runnable()
+              {
+                @Override
+                public void run()
+                {
+                  if (!control.isDisposed())
+                  {
+                    Object[] elements = contentProvider.getElements(null);
+                    if (elements.length != 0)
+                    {
+                      int newIndex = currentIndex;
+                      if (newIndex >= elements.length)
+                      {
+                        newIndex = elements.length - 1;
+                      }
+
+                      setSelectedService((IStorageService)elements[newIndex]);
+                    }
+                  }
+                }
+              });
+            }
+          }
+        }
+
+        private int getCurrentIndex(Object[] elements, IStorageService service)
+        {
+          for (int i = 0; i < elements.length; i++)
+          {
+            Object element = elements[i];
+            if (element == service)
+            {
+              return i;
+            }
+          }
+
+          return 0;
+        }
+      });
+
+      Button refreshButton = new Button(rightArea, SWT.NONE);
+      refreshButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+      refreshButton.setText("Refresh");
+      refreshButton.addSelectionListener(new SelectionAdapter()
+      {
+        @Override
+        public void widgetSelected(SelectionEvent e)
+        {
+          REGISTRY.refresh();
+        }
+      });
+    }
+
+    Object[] elements = contentProvider == null ? REGISTRY.getServices() : contentProvider.getElements(null);
+    if (elements.length != 0)
+    {
+      setSelectedService((IStorageService)elements[0]);
+    }
+
+    if (Boolean.getBoolean("org.eclipse.userstorage.ui.showTestButton"))
+    {
+      testButton = new Button(leftArea, SWT.PUSH);
+      testButton.setText("Test");
+      testButton.addSelectionListener(new SelectionAdapter()
+      {
+        @Override
+        public void widgetSelected(SelectionEvent e)
+        {
+          try
+          {
+            IStorage storage = StorageFactory.DEFAULT.create("pDKTqBfDuNxlAKydhEwxBZPxa4q");
+            IBlob blob = storage.getBlob("ui_test");
+            blob.setContentsUTF("Test 123");
+            performDefaults();
+            MessageDialog.openInformation(getShell(), "Test", "Test succeeded.");
+          }
+          catch (Exception ex)
+          {
+            performDefaults();
+            ErrorDialog.openError(getShell(), "Test", "Test failed.", Activator.getStatus(ex));
+          }
+        }
+      });
+    }
+
+    return mainArea;
+  }
+
+  @Override
+  protected void performDefaults()
+  {
+    credentialsMap.clear();
+    termsOfUseAgreedMap.clear();
+
+    try
+    {
+      skipValidate = true;
+
+      IStorageService service = selectedService;
+      selectedService = null;
+      setSelectedService(service);
+    }
+    finally
+    {
+      skipValidate = false;
+    }
+
+    updateEnablement();
+  }
+
+  @Override
+  protected Point doComputeSize()
+  {
+    return CredentialsComposite.INITIAL_SIZE;
+  }
+
+  @Override
+  public boolean performOk()
+  {
+    for (Map.Entry<IStorageService, Credentials> entry : credentialsMap.entrySet())
+    {
+      IStorageService service = entry.getKey();
+      Credentials credentials = entry.getValue();
+      ((StorageService)service).setCredentials(credentials);
+    }
+
+    for (Entry<IStorageService, Boolean> entry : termsOfUseAgreedMap.entrySet())
+    {
+      IStorageService service = entry.getKey();
+      Boolean termsOfUseAgreed = entry.getValue();
+      ((StorageService)service).setTermsOfUseAgreed(Boolean.TRUE.equals(termsOfUseAgreed));
+    }
+
+    updateEnablement();
+    return true;
+  }
+
+  private Composite createArea(Composite parent, int columns)
+  {
+    GridLayout layout = new GridLayout(columns, false);
+    layout.marginWidth = 0;
+    layout.marginHeight = 0;
+
+    final Composite main = new Composite(parent, SWT.NONE);
+    main.setLayout(layout);
+    return main;
+  }
+
+  private void setSelectedService(IStorageService service)
+  {
+    if (service != selectedService)
+    {
+      selectedService = service;
+
+      if (selectedService != null)
+      {
+        Credentials credentials = credentialsMap.get(selectedService);
+        if (credentials == null)
+        {
+          credentials = ((StorageService)selectedService).getCredentials();
+          if (credentials != null)
+          {
+            credentialsMap.put(selectedService, credentials);
+          }
+        }
+
+        Boolean termsOfUseAgreed = termsOfUseAgreedMap.get(selectedService);
+        if (termsOfUseAgreed == null)
+        {
+          termsOfUseAgreed = ((StorageService)selectedService).isTermsOfUseAgreed();
+          termsOfUseAgreedMap.put(selectedService, termsOfUseAgreed);
+        }
+
+        try
+        {
+          skipValidate = true;
+
+          credentialsComposite.setService(selectedService);
+          credentialsComposite.setCredentials(credentials);
+          credentialsComposite.setTermsOfUseAgreed(termsOfUseAgreed);
+        }
+        finally
+        {
+          skipValidate = false;
+        }
+
+        update(credentials, termsOfUseAgreed);
+
+        if (removeButton != null)
+        {
+          removeButton.setEnabled(selectedService instanceof IStorageService.Dynamic);
+        }
+
+        if (servicesViewer != null)
+        {
+          servicesViewer.setSelection(new StructuredSelection(selectedService));
+        }
+      }
+      else
+      {
+        credentialsComposite.setService(null);
+        credentialsComposite.setCredentials(null);
+
+        if (removeButton != null)
+        {
+          removeButton.setEnabled(false);
+        }
+      }
+    }
+  }
+
+  private void update(Credentials credentials, boolean termsOfUseAgreed)
+  {
+    credentialsMap.put(selectedService, credentials);
+    termsOfUseAgreedMap.put(selectedService, termsOfUseAgreed);
+    updateEnablement();
+  }
+
+  private void updateEnablement()
+  {
+    boolean dirty = false;
+
+    for (IStorageService service : REGISTRY.getServices())
+    {
+      Credentials localCredentials = credentialsMap.get(service);
+      String localUsername = "";
+      String localPassword = "";
+      if (localCredentials != null)
+      {
+        localUsername = StringUtil.safe(localCredentials.getUsername());
+        localPassword = StringUtil.safe(localCredentials.getPassword());
+      }
+      else
+      {
+        continue;
+      }
+
+      Credentials credentials = ((StorageService)service).getCredentials();
+      String username = "";
+      String password = "";
+      if (credentials != null)
+      {
+        username = StringUtil.safe(credentials.getUsername());
+        password = StringUtil.safe(credentials.getPassword());
+      }
+
+      if (!localUsername.equals(username) || !localPassword.equals(password))
+      {
+        dirty = true;
+        break;
+      }
+    }
+
+    if (!dirty)
+    {
+      for (IStorageService service : REGISTRY.getServices())
+      {
+        boolean localTermsOfUseAgreed = Boolean.TRUE.equals(termsOfUseAgreedMap.get(service));
+        boolean termsOfUseAgreed = ((StorageService)service).isTermsOfUseAgreed();
+        if (localTermsOfUseAgreed != termsOfUseAgreed)
+        {
+          dirty = true;
+          break;
+        }
+      }
+    }
+
+    Button defaultsButton = getDefaultsButton();
+    if (defaultsButton != null)
+    {
+      defaultsButton.setEnabled(dirty);
+    }
+
+    Button applyButton = getApplyButton();
+    if (applyButton != null)
+    {
+      applyButton.setEnabled(dirty);
+    }
+  }
+}
diff --git a/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/SystemBrowser.java b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/SystemBrowser.java
new file mode 100644
index 0000000..0021d4b
--- /dev/null
+++ b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/SystemBrowser.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.ui.internal;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Shell;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.StringTokenizer;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class SystemBrowser
+{
+  private static final String[] NO_COMMANDS = {};
+
+  // Don't use "explorer" as it forks another process and returns a confusing exit value.
+  private static final String[] WIN_COMMANDS = NO_COMMANDS;
+
+  private static final String[] MAC_COMMANDS = { "open" };
+
+  private static final String[] LINUX_COMMANDS = { "kde-open", "gnome-open", "xdg-open", "sensible-browser" };
+
+  public static void openSafe(Shell shell, String url, String defaultMessage)
+  {
+    if (!open(url))
+    {
+      MessageDialog.openInformation(shell, "System Browser Not Found", defaultMessage);
+    }
+  }
+
+  public static boolean open(String url)
+  {
+    try
+    {
+      for (String command : getOpenCommands())
+      {
+        if (open(command, url))
+        {
+          return true;
+        }
+      }
+    }
+    catch (Throwable ex)
+    {
+      //$FALL-THROUGH$
+    }
+
+    try
+    {
+      java.awt.Desktop desktop = java.awt.Desktop.getDesktop();
+      desktop.browse(new URI(url));
+      return true;
+    }
+    catch (Throwable ex)
+    {
+      Activator.log(ex, IStatus.WARNING);
+    }
+
+    return false;
+  }
+
+  private static boolean open(String command, String url)
+  {
+    if (getFromPath(command) != null)
+    {
+      String[] cmdarray = { command, url };
+
+      try
+      {
+        Process process = Runtime.getRuntime().exec(cmdarray);
+        if (process != null)
+        {
+          // Don't check whether the process is still running; some commands just delegate to others and terminate.
+          return true;
+        }
+      }
+      catch (IOException ex)
+      {
+        //$FALL-THROUGH$
+      }
+    }
+
+    return false;
+  }
+
+  private static String[] getOpenCommands()
+  {
+    String os = Platform.getOS();
+    if (Platform.OS_WIN32.equals(os))
+    {
+      return WIN_COMMANDS;
+    }
+
+    if (Platform.OS_MACOSX.equals(os))
+    {
+      return MAC_COMMANDS;
+    }
+
+    if (Platform.OS_LINUX.equals(os))
+    {
+      return LINUX_COMMANDS;
+    }
+
+    return NO_COMMANDS;
+  }
+
+  private static File getFromPath(String command)
+  {
+    String path = System.getenv().get("PATH");
+
+    StringTokenizer tokenizer = new StringTokenizer(path, File.pathSeparator);
+    while (tokenizer.hasMoreTokens())
+    {
+      String folder = tokenizer.nextToken();
+      File file = new File(folder, command);
+      if (file.isFile())
+      {
+        return file;
+      }
+    }
+
+    return null;
+  }
+}
diff --git a/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/UIUtil.java b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/UIUtil.java
new file mode 100644
index 0000000..29f854f
--- /dev/null
+++ b/org.eclipse.userstorage.ui/src/org/eclipse/userstorage/ui/internal/UIUtil.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage.ui.internal;
+
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * @author Eike Stepper
+ */
+public final class UIUtil
+{
+  private UIUtil()
+  {
+  }
+
+  public static Display getDisplay()
+  {
+    Display display = Display.getCurrent();
+    if (display == null)
+    {
+      try
+      {
+        display = PlatformUI.getWorkbench().getDisplay();
+      }
+      catch (Throwable ignore)
+      {
+        //$FALL-THROUGH$
+      }
+    }
+
+    if (display == null)
+    {
+      display = Display.getDefault();
+    }
+
+    if (display == null)
+    {
+      display = new Display();
+    }
+
+    return display;
+  }
+
+  public static Shell getShell()
+  {
+    final Shell[] shell = { null };
+
+    final Display display = getDisplay();
+    display.syncExec(new Runnable()
+    {
+      @Override
+      public void run()
+      {
+        shell[0] = display.getActiveShell();
+
+        if (shell[0] == null)
+        {
+          try
+          {
+            IWorkbench workbench = PlatformUI.getWorkbench();
+
+            IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
+            if (window == null)
+            {
+              IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
+              if (windows.length != 0)
+              {
+                window = windows[0];
+              }
+            }
+
+            if (window != null)
+            {
+              shell[0] = window.getShell();
+            }
+          }
+          catch (Throwable ignore)
+          {
+            //$FALL-THROUGH$
+          }
+        }
+
+        if (shell[0] == null)
+        {
+          Shell[] shells = display.getShells();
+          if (shells.length > 0)
+          {
+            shell[0] = shells[0];
+          }
+        }
+      }
+    });
+
+    return shell[0];
+  }
+
+  public static GridLayout createGridLayout(int numColumns)
+  {
+    GridLayout layout = new GridLayout(numColumns, false);
+    layout.marginWidth = 0;
+    layout.marginHeight = 0;
+    return layout;
+  }
+}
diff --git a/org.eclipse.userstorage/.classpath b/org.eclipse.userstorage/.classpath
new file mode 100644
index 0000000..ad32c83
--- /dev/null
+++ b/org.eclipse.userstorage/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<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="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.userstorage/.project b/org.eclipse.userstorage/.project
new file mode 100644
index 0000000..c949cd3
--- /dev/null
+++ b/org.eclipse.userstorage/.project
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.userstorage</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+	</natures>
+	<filteredResources>
+		<filter>
+			<id>1396938000000</id>
+			<name></name>
+			<type>10</type>
+			<matcher>
+				<id>org.eclipse.ui.ide.multiFilter</id>
+				<arguments>1.0-projectRelativePath-matches-true-false-target</arguments>
+			</matcher>
+		</filter>
+	</filteredResources>
+</projectDescription>
diff --git a/org.eclipse.userstorage/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.userstorage/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..bb20789
--- /dev/null
+++ b/org.eclipse.userstorage/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,410 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+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.doc.comment.support=enabled
+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=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+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=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning
+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.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=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=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+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.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=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=warning
+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=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.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled
+org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,HIGH,LOW,LOW,LOW,LOW,LOW
+org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX,PERF,MEM,POLISH,@generated NOT,@ADDED
+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=1
+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=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_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=false
+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=160
+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=2
+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=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=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=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=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=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=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=do not 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=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_lambda_arrow=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=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=do not 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=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=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not 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_lambda_arrow=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=do not 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=160
+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=2
+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
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/org.eclipse.userstorage/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.userstorage/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..7c1dd68
--- /dev/null
+++ b/org.eclipse.userstorage/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,125 @@
+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=true
+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_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=true
+cleanup.format_source_code_changes_only=false
+cleanup.insert_inferred_type_arguments=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=true
+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=false
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=true
+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_anonymous_class_creation=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup.use_type_arguments=false
+cleanup_profile=_UserStorage
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_UserStorage
+formatter_settings_version=12
+org.eclipse.jdt.ui.exception.name=ex
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=org.eclipse.userstorage;org.eclipse.emf;org.eclipse;com;org;javax;java;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="false" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment"/><template autoinsert\="false" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment"/><template autoinsert\="false" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment"/><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/*\r\n * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * which accompanies this distribution, and is available at\r\n * http\://www.eclipse.org/legal/epl-v10.html\r\n * \r\n * Contributors\:\r\n *    Eike Stepper - initial API and implementation\r\n */</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\r\n * @author Eike Stepper\r\n */</template><template autoinsert\="false" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment"/><template autoinsert\="false" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment"/><template autoinsert\="false" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment"/><template autoinsert\="false" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment"/><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\r\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\r\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\r\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\r\n</template><template autoinsert\="false" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">${exception_var}.printStackTrace();</template><template autoinsert\="false" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">${body_statement}</template><template autoinsert\="false" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+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=false
+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=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+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=true
+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=true
+sp_cleanup.remove_unused_imports=true
+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=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=true
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/org.eclipse.userstorage/.settings/org.eclipse.ltk.core.refactoring.prefs b/org.eclipse.userstorage/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..864e30f
--- /dev/null
+++ b/org.eclipse.userstorage/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Thu Feb 04 09:44:24 CET 2010
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/org.eclipse.userstorage/.settings/org.eclipse.pde.prefs b/org.eclipse.userstorage/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..2683a79
--- /dev/null
+++ b/org.eclipse.userstorage/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,32 @@
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.encodings=2
+compilers.p.build.java.compiler=2
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=2
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=2
+compilers.p.discouraged-class=2
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=1
+compilers.p.missing-version-import-package=1
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=2
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=0
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+eclipse.preferences.version=1
diff --git a/org.eclipse.userstorage/META-INF/MANIFEST.MF b/org.eclipse.userstorage/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..49ef91c
--- /dev/null
+++ b/org.eclipse.userstorage/META-INF/MANIFEST.MF
@@ -0,0 +1,23 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.userstorage;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-ActivationPolicy: lazy
+Bundle-Activator: org.eclipse.userstorage.internal.Activator
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.0.0,4.0.0)",
+ org.eclipse.core.net;bundle-version="[1.2.0,2.0.0)",
+ org.eclipse.equinox.security;bundle-version="[1.0.0,2.0.0)",
+ org.apache.httpcomponents.httpclient;bundle-version="[4.0.0,5.0.0)",
+ org.apache.httpcomponents.httpcore;bundle-version="[4.0.0,5.0.0)",
+ org.apache.commons.logging;bundle-version="[1.0.0,2.0.0)",
+ org.apache.commons.codec;bundle-version="[1.6.0,2.0.0)"
+Export-Package: org.eclipse.userstorage;version="1.0.0",
+ org.eclipse.userstorage.internal;version="1.0.0";x-friends:="org.eclipse.userstorage.tests,org.eclipse.userstorage.ui",
+ org.eclipse.userstorage.internal.util;version="1.0.0";x-friends:="org.eclipse.userstorage.tests,org.eclipse.userstorage.ui",
+ org.eclipse.userstorage.spi;version="1.0.0",
+ org.eclipse.userstorage.util;version="1.0.0"
+Eclipse-BuddyPolicy: registered
diff --git a/org.eclipse.userstorage/about.html b/org.eclipse.userstorage/about.html
new file mode 100644
index 0000000..d35d5ae
--- /dev/null
+++ b/org.eclipse.userstorage/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>June 5, 2007</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
diff --git a/org.eclipse.userstorage/about.ini b/org.eclipse.userstorage/about.ini
new file mode 100644
index 0000000..c6eaecb
--- /dev/null
+++ b/org.eclipse.userstorage/about.ini
@@ -0,0 +1,18 @@
+# Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+# 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:
+#    Eike Stepper - initial API and implementation
+
+# Property "aboutText" contains blurb for "About" dialog (translated)
+aboutText=%featureText
+
+# Property "featureImage" contains path to feature image (32x32)
+featureImage=eclipse32.png
+
+# Property "appName" contains name of the application (translated)
+appName=%featureName
+
diff --git a/org.eclipse.userstorage/about.mappings b/org.eclipse.userstorage/about.mappings
new file mode 100644
index 0000000..4b420dd
--- /dev/null
+++ b/org.eclipse.userstorage/about.mappings
@@ -0,0 +1,3 @@
+0=${build.id}
+1=${git.branch}
+2=${git.commit}
diff --git a/org.eclipse.userstorage/about.properties b/org.eclipse.userstorage/about.properties
new file mode 100644
index 0000000..c9e09e5
--- /dev/null
+++ b/org.eclipse.userstorage/about.properties
@@ -0,0 +1,17 @@
+# Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+# 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:
+#    Eike Stepper - initial API and implementation
+
+featureName = Eclipse User Storage
+featureText = Eclipse User Storage\n\
+\n\
+Version: {featureVersion} (build {0})\n\
+Commit: {2} (branch {1})\n\
+\n\
+Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others. All rights reserved.\n\
+Visit http://www.eclipse.org/userstorage for more information.
diff --git a/org.eclipse.userstorage/build.properties b/org.eclipse.userstorage/build.properties
new file mode 100644
index 0000000..b39c2de
--- /dev/null
+++ b/org.eclipse.userstorage/build.properties
@@ -0,0 +1,14 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               about.html,\
+               plugin.xml,\
+               schema/,\
+               about.ini,\
+               about.mappings,\
+               about.properties,\
+               eclipse32.png,\
+               plugin.properties
+src.includes = about.html,\
+               pom.xml
diff --git a/org.eclipse.userstorage/eclipse32.png b/org.eclipse.userstorage/eclipse32.png
new file mode 100644
index 0000000..bf85680
--- /dev/null
+++ b/org.eclipse.userstorage/eclipse32.png
Binary files differ
diff --git a/org.eclipse.userstorage/plugin.properties b/org.eclipse.userstorage/plugin.properties
new file mode 100644
index 0000000..793b408
--- /dev/null
+++ b/org.eclipse.userstorage/plugin.properties
@@ -0,0 +1,11 @@
+# Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+# 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:
+#    Eike Stepper - initial API and implementation
+
+pluginName = Eclipse User Storage
+providerName = Eclipse.org
diff --git a/org.eclipse.userstorage/plugin.xml b/org.eclipse.userstorage/plugin.xml
new file mode 100644
index 0000000..7e65599
--- /dev/null
+++ b/org.eclipse.userstorage/plugin.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<!--
+  Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+  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:
+    Eike Stepper - initial API and implementation
+-->
+
+<plugin>
+
+   <extension-point id="credentialsProviders" name="User Storage Credentials Providers" schema="schema/credentialsProviders.exsd"/>
+
+   <extension-point id="storages" name="User Storages" schema="schema/storages.exsd"/>
+
+</plugin>
diff --git a/org.eclipse.userstorage/pom.xml b/org.eclipse.userstorage/pom.xml
new file mode 100644
index 0000000..63e7dbe
--- /dev/null
+++ b/org.eclipse.userstorage/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+  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:
+    Eike Stepper - initial API and implementation
+-->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.eclipse.userstorage</groupId>
+    <artifactId>parent</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+  <groupId>org.eclipse.userstorage</groupId>
+  <artifactId>org.eclipse.userstorage</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>eclipse-plugin</packaging>
+</project>
diff --git a/org.eclipse.userstorage/schema/credentialsProviders.exsd b/org.eclipse.userstorage/schema/credentialsProviders.exsd
new file mode 100644
index 0000000..dcb24cb
--- /dev/null
+++ b/org.eclipse.userstorage/schema/credentialsProviders.exsd
@@ -0,0 +1,120 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+  Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+  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:
+    Eike Stepper - initial API and implementation
+-->
+
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.userstorage" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appinfo>
+         <meta.schema plugin="org.eclipse.userstorage" id="credentialsProviders" name="User Storage Credentials Providers"/>
+      </appinfo>
+      <documentation>
+         [Enter description of this extension point.]
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appinfo>
+            <meta.element />
+         </appinfo>
+      </annotation>
+      <complexType>
+         <sequence>
+            <element ref="credentialsProvider" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+
+               </documentation>
+               <appinfo>
+                  <meta.attribute translatable="true"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="credentialsProvider">
+      <complexType>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+
+               </documentation>
+               <appinfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.userstorage.spi.ICredentialsProvider"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+         <attribute name="priority" type="string">
+            <annotation>
+               <documentation>
+
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="since"/>
+      </appinfo>
+      <documentation>
+         [Enter the first release in which this extension point appears.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="examples"/>
+      </appinfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="apiinfo"/>
+      </appinfo>
+      <documentation>
+         [Enter API information here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="implementation"/>
+      </appinfo>
+      <documentation>
+         [Enter information about supplied implementation of this extension point.]
+      </documentation>
+   </annotation>
+
+
+</schema>
diff --git a/org.eclipse.userstorage/schema/storages.exsd b/org.eclipse.userstorage/schema/storages.exsd
new file mode 100644
index 0000000..e3662f4
--- /dev/null
+++ b/org.eclipse.userstorage/schema/storages.exsd
@@ -0,0 +1,127 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.userstorage" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.userstorage" id="storages" name="User Storages"/>
+      </appInfo>
+      <documentation>
+         [Enter description of this extension point.]
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appInfo>
+            <meta.element />
+         </appInfo>
+      </annotation>
+      <complexType>
+         <sequence>
+            <element ref="storage" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="storage">
+      <complexType>
+         <attribute name="serviceLabel" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="serviceURI" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="createAccountURI" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="editAccountURI" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="recoverPasswordURI" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         [Enter the first release in which this extension point appears.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiinfo"/>
+      </appInfo>
+      <documentation>
+         [Enter API information here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         [Enter information about supplied implementation of this extension point.]
+      </documentation>
+   </annotation>
+
+
+</schema>
diff --git a/org.eclipse.userstorage/src/org/eclipse/userstorage/IBlob.java b/org.eclipse.userstorage/src/org/eclipse/userstorage/IBlob.java
new file mode 100644
index 0000000..e26e209
--- /dev/null
+++ b/org.eclipse.userstorage/src/org/eclipse/userstorage/IBlob.java
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage;
+
+import org.eclipse.userstorage.spi.StorageCache;
+import org.eclipse.userstorage.util.ConflictException;
+import org.eclipse.userstorage.util.NoServiceException;
+import org.eclipse.userstorage.util.NotFoundException;
+import org.eclipse.userstorage.util.ProtocolException;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ * Represents a piece of data that a {@link #getStorage() storage}
+ * maintains for the logged-in user under the associated {@link #getKey() key}.
+ * <p>
+ * The actual data can be read from the {@link InputStream} returned by the {@link #getContents() getContents()} method.
+ * It can be written by passing an {@link InputStream} to the {@link #setContents(InputStream) setContents()} method.
+ * <p>
+ * On top of this scalable I/O model a few methods are provided to get or set the blob's contents in
+ * more convenient formats, such as {@link DataInput#readUTF() UTF strings}, integers, or booleans.
+ * <p>
+ * In no case the contents of this blob are kept in memory. If the {@link #getStorage() storage} of this blob was
+ * created with a {@link StorageFactory#create(String, StorageCache) storage cache}
+ * the contents are possibly served from that cache. In any case all read and write access contacts the remote service
+ * behind storage's service, even if only to validate that a possibly cached version of the contents is still up-to-date,
+ * see {@link #getETag()}.
+ * <p>
+ *
+ * @author Eike Stepper
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IBlob
+{
+  /**
+   * Returns the storage of this blob.
+   *
+   * @return the storage of this blob, never <code>null</code>.
+   */
+  public IStorage getStorage();
+
+  /**
+   * Returns the key of this blob.
+   *
+   * @return the key of this blob, never <code>null</code>.
+   */
+  public String getKey();
+
+  /**
+   * Returns an immutable {@link Map} of the properties of this blob.
+   * <p>
+   * The properties represent arbitrary meta data about this blob that the service provider decides to provide.
+   * The only property that service providers are required to provide is the {@link #getETag() ETag} property.
+   * <p>
+   * The properties map is only updated during any of the getContents() or setContents() methods.
+   * If the {@link #getStorage() storage} of this blob was
+   * created with a {@link StorageFactory#create(String, StorageCache) storage cache}
+   * the properties are possibly served from that cache.
+   * <p>
+   *
+   * @return an immutable {@link Map} of the properties of this blob, never <code>null</code>.<p>
+   * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p>
+   *
+   * @see #getETag()
+   * @see #getContents()
+   * @see #setContents(InputStream)
+   */
+  public Map<String, String> getProperties() throws IllegalStateException;
+
+  /**
+   * Returns the ETag of this blob.
+   * <p>
+   * The ETag of a blob is an opaque but unique value that the service provider assigns to a particular version
+   * (of the contents) of the blob. This value serves two purposes:
+   * <p>
+   * <ul>
+   * <li> If the {@link #getStorage() storage} of this blob was created with a
+   *      {@link StorageFactory#create(String, StorageCache) storage cache}
+   *      and the cache contains the current version of this blob
+   *      all getContents() methods use the ETag to prevent the server from sending the blob's contents again.
+   *      The cached contents are returned instead.
+   * <li> All setContents() methods use the ETag (if it is known) to prevent the server from storing conflicting
+   *      changes. A conflicting change is updating a blob with new contents that is based on an out-dated ETag.
+   * </ul>
+   * <p>
+   *
+   * @return the ETag of this blob, or <code>null</code> if the ETag of this blob is currently not known.<p>
+   * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p>
+   *
+   * @see #setETag(String)
+   */
+  public String getETag() throws IllegalStateException;
+
+  /**
+   * Sets the ETag of this blob.
+   * <p>
+   * The ETag of a blob is an opaque but unique value that the service provider assigns to a particular version
+   * (of the contents) of the blob. This value serves two purposes:
+   * <p>
+   * <ul>
+   * <li> If the {@link #getStorage() storage} of this blob was created with a
+   *      {@link StorageFactory#create(String, StorageCache) storage cache}
+   *      and the cache contains the current version of this blob
+   *      all getContents() methods use the ETag to prevent the server from sending the blob's contents again.
+   *      The cached contents are returned instead.
+   * <li> All setContents() methods use the ETag (if it is known) to prevent the server from storing conflicting
+   *      changes. A conflicting change is updating a blob with new contents that is based on an out-dated ETag.
+   * </ul>
+   * <p>
+   * If the {@link #getStorage() storage} of this blob was created with a
+   * {@link StorageFactory#create(String, StorageCache) storage cache}
+   * and the new ETag is different from the cached ETag the cached blob is deleted locally.
+   * <p>
+   *
+   * @param eTag the new ETag of this blob, or <code>null</code> to reset the ETag.<p>
+   * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p>
+   *
+   * @see #getETag()
+   */
+  public void setETag(String eTag) throws IllegalStateException;
+
+  /**
+   * Returns an {@link InputStream} that represents the current contents of this blob.
+   * <p>
+   * This method always contacts the server.
+   * <p>
+   * If the {@link #getStorage() storage} of this blob was created with a
+   * {@link StorageFactory#create(String, StorageCache) storage cache}
+   * and the cache contains the current version of this blob (i.e., the blob's ETag is up-to-date)
+   * the server will not send the blob's contents again. The cached contents are returned instead.
+   * If the cache does not contain the current version of this blob (i.e., the blob's ETag is out-of-date)
+   * the current remote contents are downloaded, cached, and returned by this method.
+   * <p>
+   * <b>Important note:</b>
+   * <p>
+   * The new contents will only be cached if (caching is enabled and) the
+   * returned input stream is fully read and closed.
+   * <p>
+   *
+   * @return an {@link InputStream} that represents the current contents of this blob, never <code>null</code>.<p>
+   * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p>
+   * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p>
+   * @throws NotFoundException if this blob does not exist on the server.<p>
+   * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p>
+   *
+   * @see #setContents(InputStream)
+   * @see #getETag()
+   */
+  public InputStream getContents() throws IOException, NoServiceException, NotFoundException, IllegalStateException;
+
+  /**
+   * Sets an {@link InputStream} that represents the new contents of this blob.
+   * <p>
+   * This method always contacts the server.
+   * <p>
+   * If this blob has an ETag it will be used to detect and avoid conflicts on the server side.
+   * The ETag of this blob can be {@link #setETag(String) set} to <code>null</code> if server-side conflict detection is not desired.
+   * Server-side conflicts are indicated by throwing a {@link ConflictException}.
+   * <p>
+   * If the {@link #getStorage() storage} of this blob was created with a
+   * {@link StorageFactory#create(String, StorageCache) storage cache}
+   * and the server successfully updated the blob (i.e., the blob's ETag was up-to-date)
+   * the cache will be updated with the new version of the contents.
+   * <p>
+   *
+   * @param in an {@link InputStream} that represents the new contents of this blob.<p>
+   * @return <code>true</code> if a new blob was created, <code>false</code> if an existing blob was updated.<p>
+   * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p>
+   * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p>
+   * @throws ConflictException if the server detected a conflict and did not update the blob.<p>
+   * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p>
+   *
+   * @see #getContents()
+   * @see #setETag(String)
+   */
+  public boolean setContents(InputStream in) throws IOException, NoServiceException, ConflictException, IllegalStateException;
+
+  /**
+   * Returns a {@link String} that represents the current contents of this blob.
+   * <p>
+   * This method is a convenient wrapper around the {@link #getContents()} method.
+   * It assumes that the binary contents of this blob represent a UTF-8 encoded text value.
+   * If this assumption is wrong (and this method can not detect this case) the results are unpredictable.
+   * Otherwise the semantics of this method are identical to the ones of {@link #getContents()}.
+   * <p>
+   *
+   * @return a {@link String} that represents the current contents of this blob, never <code>null</code>.<p>
+   * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p>
+   * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p>
+   * @throws NotFoundException if this blob does not exist on the server.<p>
+   * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p>
+   *
+   * @see #getContents()
+   */
+  public String getContentsUTF() throws IOException, NoServiceException, IllegalStateException, NotFoundException;
+
+  /**
+   * Sets a {@link String} that represents the new contents of this blob.
+   * <p>
+   * This method is a convenient wrapper around the {@link #setContents(InputStream)} method.
+   * The semantics of this method are identical to the ones of {@link #setContents(InputStream)}.
+   * <p>
+   *
+   * @param value a {@link String} that represents the new contents of this blob.<p>
+   * @return <code>true</code> if a new blob was created, <code>false</code> if an existing blob was updated.<p>
+   * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p>
+   * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p>
+   * @throws ConflictException if the server detected a conflict and did not update the blob.<p>
+   * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p>
+   *
+   * @see #setContents(InputStream)
+   */
+  public boolean setContentsUTF(String value) throws IOException, NoServiceException, ConflictException, IllegalStateException;
+
+  /**
+   * Returns a primitive int value that represents the current contents of this blob.
+   * <p>
+   * This method is a convenient wrapper around the {@link #getContents()} method.
+   * It assumes that the binary contents of this blob represent a UTF-8 encoded integer value.
+   * If this assumption is wrong (and this method can not detect this case) the results are unpredictable.
+   * Otherwise the semantics of this method are identical to the ones of {@link #getContents()}.
+   * <p>
+   *
+   * @return a primitive int value that represents the current contents of this blob.<p>
+   * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p>
+   * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p>
+   * @throws NotFoundException if this blob does not exist on the server.<p>
+   * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p>
+   *
+   * @see #getContents()
+   */
+  public int getContentsInt() throws IOException, NoServiceException, NotFoundException, IllegalStateException, NumberFormatException;
+
+  /**
+   * Sets a a primitive int value that represents the new contents of this blob.
+   * <p>
+   * This method is a convenient wrapper around the {@link #setContents(InputStream)} method.
+   * The semantics of this method are identical to the ones of {@link #setContents(InputStream)}.
+   * <p>
+   *
+   * @param value a a primitive int value that represents the new contents of this blob.<p>
+   * @return <code>true</code> if a new blob was created, <code>false</code> if an existing blob was updated.<p>
+   * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p>
+   * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p>
+   * @throws ConflictException if the server detected a conflict and did not update the blob.<p>
+   * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p>
+   *
+   * @see #setContents(InputStream)
+   */
+  public boolean setContentsInt(int value) throws IOException, NoServiceException, ConflictException, IllegalStateException;
+
+  /**
+   * Returns a primitive boolean value that represents the current contents of this blob.
+   * <p>
+   * This method is a convenient wrapper around the {@link #getContents()} method.
+   * It assumes that the binary contents of this blob represent a UTF-8 encoded boolean value.
+   * If this assumption is wrong (and this method can not detect this case) the results are unpredictable.
+   * Otherwise the semantics of this method are identical to the ones of {@link #getContents()}.
+   * <p>
+   *
+   * @return a primitive boolean value that represents the current contents of this blob.<p>
+   * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p>
+   * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p>
+   * @throws NotFoundException if this blob does not exist on the server.<p>
+   * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p>
+   *
+   * @see #getContents()
+   */
+  public boolean getContentsBoolean() throws IOException, NoServiceException, NotFoundException, IllegalStateException;
+
+  /**
+   * Sets a a primitive boolean value that represents the new contents of this blob.
+   * <p>
+   * This method is a convenient wrapper around the {@link #setContents(InputStream)} method.
+   * The semantics of this method are identical to the ones of {@link #setContents(InputStream)}.
+   * <p>
+   *
+   * @param value a a primitive boolean value that represents the new contents of this blob.<p>
+   * @return <code>true</code> if a new blob was created, <code>false</code> if an existing blob was updated.<p>
+   * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p>
+   * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p>
+   * @throws ConflictException if the server detected a conflict and did not update the blob.<p>
+   * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p>
+   *
+   * @see #setContents(InputStream)
+   */
+  public boolean setContentsBoolean(boolean value) throws IOException, NoServiceException, ConflictException, IllegalStateException;
+
+  /**
+   * Deletes this blob.
+   * <p>
+   * This method always contacts the server.
+   * <p>
+   * If this blob has an ETag it will be used to detect and avoid conflicts on the server side.
+   * The ETag of this blob can be {@link #setETag(String) set} to <code>null</code> if server-side conflict detection is not desired.
+   * Server-side conflicts are indicated by throwing a {@link ConflictException}.
+   * <p>
+   * If the {@link #getStorage() storage} of this blob was created with a
+   * {@link StorageFactory#create(String, StorageCache) storage cache}
+   * and the server successfully deleted the blob (i.e., the blob's ETag was up-to-date)
+   * the cache will be deleted, too.
+   * <p>
+   *
+   * @return <code>true</code> if this blob was successfully deleted from the server, <code>false</code> if it did not exist.<p>
+   * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p>
+   * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p>
+   * @throws ConflictException if the server detected a conflict and did not update the blob.<p>
+   * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p>
+   *
+   * @see #setETag(String)
+   */
+  public boolean delete() throws IOException, NoServiceException, ConflictException, IllegalStateException;
+
+  /**
+   * Returns <code>true</code> if this blob is disposed, <code>false</code> otherwise.
+   * <p>
+   * The only way for a blob to become disposed is when the storage of the {@link IStorage storage} of that blob
+   * is changed after that blob was created. Applications must call {@link IStorage#getBlob(String) getBlob()} to acquire
+   * a new, valid blob instance in that case.
+   * <p>
+   *
+   * @see IStorage#getBlob(String) getBlob()
+   */
+  public boolean isDisposed();
+}
diff --git a/org.eclipse.userstorage/src/org/eclipse/userstorage/IStorage.java b/org.eclipse.userstorage/src/org/eclipse/userstorage/IStorage.java
new file mode 100644
index 0000000..fba3799
--- /dev/null
+++ b/org.eclipse.userstorage/src/org/eclipse/userstorage/IStorage.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage;
+
+import org.eclipse.userstorage.spi.ICredentialsProvider;
+import org.eclipse.userstorage.spi.StorageCache;
+import org.eclipse.userstorage.util.BadKeyException;
+import org.eclipse.userstorage.util.NoServiceException;
+import org.eclipse.userstorage.util.NotFoundException;
+import org.eclipse.userstorage.util.ProtocolException;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Represents a partition of the data in a {@link #getService() storage service} that
+ * is associated with (i.e., created and maintained by) a {@link #getApplicationToken() registered application}.
+ * <p>
+ * A registered application gets access to its partition of the stored data by creating an instance of this interface as follows:
+ * <p>
+ * <pre>IStorage storage = StorageFactory.DEFAULT.create(applicationToken);<pre>
+ * <p>
+ * The <code>applicationToken</code> must be registered by the provider of the service of this storage.
+ * The service provider is responsible for registering applications and providing the needed application token.
+ * <p>
+ * Once an application has created its storage the {@link #getBlob(String) getBlob()} method can be used to get access to
+ * a specific piece of data that this application maintains for the logged-in user under a given <code>key</code>.
+ * <p>
+ *
+ * @author Eike Stepper
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IStorage
+{
+  /**
+   * Return the application token of this storage.
+   * <p>
+   * The <code>applicationToken</code> must be registered by the provider of the {@link #getService() service} of this storage.
+   * The service provider is responsible for registering applications and providing the needed application token.
+   * <p>
+   *
+   * @return the application token of this storage, never <code>null</code>.<p>
+   *
+   * @see StorageFactory#create(String)
+   */
+  public String getApplicationToken();
+
+  /**
+   * Returns the factory of this storage.
+   * <p>
+   *
+   * @return the factory of this storage, never <code>null</code>.<p>
+   */
+  public StorageFactory getFactory();
+
+  /**
+   * Returns the local cache of this storage.
+   * <p>
+   *
+   * @return the local cache of this storage, or <code>null</code> if no cache was specified when this storage was created.<p>
+   *
+   * @see StorageFactory#create(String, StorageCache)
+   */
+  public StorageCache getCache();
+
+  /**
+   * Returns the service of this storage.
+   * <p>
+   *
+   * @return the service of this storage, never <code>null</code>.<p>
+   *
+   * @see #setService(IStorageService)
+   */
+  public IStorageService getService();
+
+  /**
+   * Sets the service of this storage to the given service.
+   * <p>
+   * Calling this method is optional and only required if the default service that was assigned by the {@link StorageFactory storage factory} is not adequate.
+   * <p>
+   *
+   * @param service the service to set into this storage, must not be <code>null</code>.<p>
+   *
+   * @see #getService()
+   */
+  public void setService(IStorageService service);
+
+  /**
+   * Returns the optional credentials provider of this storage that, if available, overrides the {@link #getService() service}'s default credentials provider.
+   * <p>
+   * @return the override credentials provider of this storage, or <code>null</code> if unavailable.<p>
+   *
+   * @see #setCredentialsProvider(ICredentialsProvider)
+   */
+  public ICredentialsProvider getCredentialsProvider();
+
+  /**
+   * Sets the optional credentials provider of this storage that, if available, overrides the {@link #getService() service}'s default credentials provider.
+   * <p>
+   * Overriding the default credentials provider can make sense in scenarios where one wouldn't want a credentials dialog to pop up.
+   * {@link ICredentialsProvider#CANCEL} can be used temporarily in these cases.
+   * <p>
+   *
+   * @param credentialsProvider the override credentials provider of this storage, or <code>null</code> for no overriding.<p>
+   *
+   * @see #getCredentialsProvider()
+   */
+  public void setCredentialsProvider(ICredentialsProvider credentialsProvider);
+
+  /**
+   * Returns an {@link Iterable} of all blobs that this storage maintains for the logged-in user.
+   * <p>
+   * This method causes the remote service being contacted to return the metadata of the blobs.
+   * Blob contents are not transferred during this call.
+   * <p>
+   * This storage ensures that at no time two different IBlob instances for the same logged-in user and the same <code>key</code> exist.
+   * It also ensures that an IBlob instance becomes subject to garbage collection when the application releases its last strong reference on it.
+   * <p>
+   *
+   * @returns an {@link Iterable} of all blobs that this storage maintains for the logged-in user, never <code>null</code>.<p>
+   * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p>
+   * @throws NoServiceException if this storage has no {@link IStorageService service} assigned.<p>
+   */
+  public Iterable<IBlob> getBlobs() throws IOException;
+
+  /**
+   * Returns a list of specified blobs that this storage maintains for the logged-in user.
+   * <p>
+   * This method causes the remote service being contacted to return the metadata of the blobs.
+   * Blob contents are not transferred during this call.
+   * <p>
+   * This storage ensures that at no time two different IBlob instances for the same logged-in user and the same <code>key</code> exist.
+   * It also ensures that an IBlob instance becomes subject to garbage collection when the application releases its last strong reference on it.
+   * <p>
+   *
+   * @param pageSize the maximum number of blobs to return, must be between 1 and 100.<p>
+   * @param page the page of blobs to return, must be greater or equal to 1.<p>
+   * @returns a list of specified blobs that this storage maintains for the logged-in user, never <code>null</code>.<p>
+   * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p>
+   * @throws NoServiceException if this storage has no {@link IStorageService service} assigned.<p>
+   * @throws NotFoundException if no blobs on the specified page exist on the server.<p>
+   */
+  public List<IBlob> getBlobs(int pageSize, int page) throws IOException, NotFoundException;
+
+  /**
+   * Provides access to a specific piece of data that this storage maintains for the logged-in user under the given <code>key</code>.
+   * <p>
+   * This method does not cause the remote service being contacted. It only performs minimal
+   * {@link BadKeyException#validate(String) lexical validation} of the given <code>key</code>
+   * and returns an {@link IBlob} instance that can be used to read or write the actual blob content.
+   * <p>
+   * This storage ensures that at no time two different IBlob instances for the same logged-in user and the same <code>key</code> exist.
+   * It also ensures that an IBlob instance becomes subject to garbage collection when the application releases its last strong reference on it.
+   * <p>
+   *
+   * @param key the key that uniquely identifies this blob in the scope of the logged-in user and of this storage.
+   *        Minimal {@link BadKeyException#validate(String) lexical validation} is performed on the passed key.<p>
+   * @returns the IBlob instance that represents the piece of data that this storage
+   *          maintains for the logged-in user under the given <code>key</code>, never <code>null</code>.<p>
+   * @throws BadKeyException if {@link BadKeyException#validate(String) lexical validation} of the passed key fails.<p>
+   */
+  public IBlob getBlob(String key) throws BadKeyException;
+
+  /**
+   * Deletes <b>all</b> blobs that this storage maintains for the logged-in user.
+   * <p>
+   * The blobs of other storages/applications are not affected by this call.
+   * <p>
+   *
+   * @return <code>true</code> if at least one blob was successfully deleted from the server, <code>false</code> if no blob existed.<p>
+   * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p>
+   * @throws NoServiceException if this storage has no {@link IStorageService service} assigned.<p>
+   */
+  public boolean deleteAllBlobs() throws IOException, NoServiceException;
+
+  /**
+   * Adds the given listener to the list of listeners that are notified about {@link IStorageService service} changes.
+   *
+   * @param listener the listener to add to the list of listeners that are notified about service changes.
+   */
+  public void addListener(Listener listener);
+
+  /**
+   * Removes the given listener from the list of listeners that are notified about {@link IStorageService service} changes.
+   *
+   * @param listener the listener to remove from the list of listeners that are notified about service changes.
+   */
+  public void removeListener(Listener listener);
+
+  /**
+   * Listens to {@link IStorageService service} changes of a {@link IStorage storage}.
+   *
+   * @author Eike Stepper
+   */
+  public interface Listener
+  {
+    /**
+     * Called when the {@link IStorageService service} of a {@link IStorage storage} has changed.
+     *
+     * @param storage the storage, never <code>null</code>.
+     * @param oldService the old service of the storage, possibly <code>null</code>.
+     * @param newService the new service of the storage, possibly <code>null</code>.
+     */
+    public void serviceChanged(IStorage storage, IStorageService oldService, IStorageService newService);
+  }
+}
diff --git a/org.eclipse.userstorage/src/org/eclipse/userstorage/IStorageService.java b/org.eclipse.userstorage/src/org/eclipse/userstorage/IStorageService.java
new file mode 100644
index 0000000..cac7bf6
--- /dev/null
+++ b/org.eclipse.userstorage/src/org/eclipse/userstorage/IStorageService.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage;
+
+import org.eclipse.userstorage.internal.StorageServiceRegistry;
+import org.eclipse.userstorage.spi.ICredentialsProvider;
+
+import java.net.URI;
+import java.util.concurrent.Semaphore;
+
+/**
+ * Represents a remote <i>user storage service</i> (USS).
+ * <p>
+ * The {@link Registry storage service registry} makes known storages available and supports the
+ * {@link Registry#addService(String, URI, URI, URI, URI, String) addition} of {@link Dynamic dynamic}
+ * storages.
+ * <p>
+ *
+ * @author Eike Stepper
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IStorageService extends Comparable<IStorageService>
+{
+  /**
+   * Returns the label of the REST service behind this storage.
+   *
+   * @return the label of the REST service behind this storage, never <code>null</code>.<p>
+   */
+  public String getServiceLabel();
+
+  /**
+   * Returns the URI of the REST service behind this storage.
+   * <p>
+   * The service URI is a unique identifier of a storage and it is used as the lookup key in
+   * {@link Registry#getService(URI) Registry.getStorage()}.
+   *
+   * @return the URI of the REST service behind this storage, never <code>null</code>.<p>
+   */
+  public URI getServiceURI();
+
+  /**
+   * Returns the create account URI of this storage.
+   *
+   * @return the create account URI of this storage, can be <code>null</code>.<p>
+   */
+  public URI getCreateAccountURI();
+
+  /**
+   * Returns the edit account URI of this storage.
+   *
+   * @return the edit account URI of this storage, can be <code>null</code>.<p>
+   */
+  public URI getEditAccountURI();
+
+  /**
+   * Returns the recover password URI of this storage.
+   *
+   * @return the recover password URI of this storage, can be <code>null</code>.<p>
+   */
+  public URI getRecoverPasswordURI();
+
+  /**
+   * Returns the terms of use link of this storage.
+   *
+   * @return the terms of use link of this storage, can be <code>null</code>.<p>
+   */
+  public String getTermsOfUseLink();
+
+  /**
+   * Returns a one-permit semaphore that this service acquires while control is passed to a {@link ICredentialsProvider credentials provider},
+   * such a a login dialog.
+   *
+   * @return a one-permit semaphore that this service acquires while control is passed to a {@link ICredentialsProvider credentials provider},
+   * such a a login dialog.<p>
+   */
+  public Semaphore getAuthenticationSemaphore();
+
+  /**
+   * A {@link IStorageService storage service} that is dynamically created as opposed to being
+   * statically contributed via the <code>org.eclipse.userstorage.storages</code> extension point).
+   * <p>
+   * Dynamic storages can be created and registered via the {@link Registry#addService(String, URI, URI, URI, URI, String) addStorage()} method
+   * and only dynamic storages can be {@link #remove() removed} from the {@link Registry storage service registry}.
+   * <p>
+   *
+   * @author Eike Stepper
+   * @noextend This interface is not intended to be extended by clients.
+   * @noimplement This interface is not intended to be implemented by clients.
+   */
+  public interface Dynamic extends IStorageService
+  {
+    /**
+     * Removes this storage from the {@link Registry storage service registry}.
+     */
+    public void remove();
+  }
+
+  /**
+   * Provides a central place to access registered {@link IStorageService storage services}.
+   * <p>
+   * This registry contains storages of the following two types:
+   * <p>
+   * <ul>
+   * <li> Static storages that are contributed via the <code>org.eclipse.userstorage.storages</code> extension point.
+   * <li> {@link Dynamic Dynamic} storages that are created via the {@link #addService(String, URI, URI, URI, URI, String) addStorage()} method.
+   * </ul>
+   * <p>
+   * To access the storages in this registry an application uses the {@link #INSTANCE} constant as follows:
+   * <p>
+   * <pre>   IStorage[] storages = IStorage.Registry.INSTANCE.getStorages();</pre>
+   * <p>
+   * To access the data that is stored in a storage on the server side an application must create a {@link IStorage storage}.
+   * <p>
+   *
+   * @author Eike Stepper
+   * @noextend This interface is not intended to be extended by clients.
+   * @noimplement This interface is not intended to be implemented by clients.
+   */
+  public interface Registry
+  {
+    /**
+     * The singleton instance of this registry.
+     */
+    public static final Registry INSTANCE = StorageServiceRegistry.INSTANCE;
+
+    /**
+     * Returns an array of all currently registered storages.
+     *
+     * @return an array of all currently registered storages, never <code>null</code>.<p>
+     */
+    public IStorageService[] getServices();
+
+    /**
+     * Returns the currently registered storage for the given <code>serviceURI</code>.
+     *
+     * @return the currently registered storage for the given <code>serviceURI</code>,
+     *         or <code>null</code> if no storage is registered for the given <code>serviceURI</code>.<p>
+     */
+    public IStorageService getService(URI serviceURI);
+
+    /**
+     * Adds a new dynamic storage with the given <code>serviceLabel</code> and the given <code>serviceURI</code> to this registry.
+     * <p>
+     *
+     * @param serviceLabel the label of the REST service behind the storage to be created and registered.
+     *        The label <i>must not be</i> <code>null</code> or empty and it <i>should be</i> unique (the latter is not a strict requirement
+     *        but rather a recommendation to make it easier for a user to pick a storage for an application). See also {@link IStorageService#getServiceLabel()}.<p>
+     * @param serviceURI the base URI of the REST service behind the storage to be created and registered.
+     *        The service URI is a unique identifier of the storage and it is used as the lookup key in
+     *        {@link Registry#getService(URI) Registry.getStorage()}. It <i>must not be</i> <code>null</code>. See also {@link IStorageService#getServiceURI()}.<p>
+     * @param createAccountURI an optional (<i>can be</i> <code>null</code>) URI that a user interface can use to point the user to a web page that supports the creation
+     *        of the user account needed for the REST service behind the storage to be created and registered. See also {@link IStorageService#getCreateAccountURI()}.<p>
+     * @param editAccountURI an optional (<i>can be</i> <code>null</code>) URI that a user interface can use to point the user to a web page that supports the modification
+     *        of the user account needed for the REST service behind the storage to be created and registered. See also {@link IStorageService#getEditAccountURI()}.<p>
+     * @param recoverPasswordURI an optional (<i>can be</i> <code>null</code>) URI that a user interface can use to point the user to a web page that supports the recovery
+     *        of the password needed to log into the REST service behind the storage to be created and registered. See also {@link IStorageService#getRecoverPasswordURI()}.<p>
+     * @param termsOfUseLink an optional (<i>can be</i> <code>null</code>) string that a user interface can use to point the user to a web page that supports the terms of use
+     *        of the REST service behind the storage. See also {@link IStorageService#getTermsOfUseLink()}.<p>
+     *
+     * @return the newly created and registered storage, never <code>null</code>.<p>
+     * @throws IllegalStateException if a storage with the same <code>serviceURI</code> is already registered in this registry.<p>
+     *
+     * @see #addService(String, URI)
+     */
+    public IStorageService.Dynamic addService(String serviceLabel, URI serviceURI, URI createAccountURI, URI editAccountURI, URI recoverPasswordURI,
+        String termsOfUseLink) throws IllegalStateException;
+
+    /**
+     * Adds a new dynamic storage with the given <code>serviceLabel</code> and the given <code>serviceURI</code> to this registry.
+     * <p>
+     * Calling this method is identical to calling <code>addStorage(serviceLabel, serviceURI, null, null, null)</code>.
+     * <p>
+     *
+     * @param serviceLabel the label of the REST service behind the storage to be created and registered.
+     *        The label <i>must not be</i> <code>null</code> or empty and it <i>should be</i> unique (the latter is not a strict requirement
+     *        but rather a recommendation to make it easier for a user to pick a storage for an application). See also {@link IStorageService#getServiceLabel()}.<p>
+     * @param serviceURI the base URI of the REST service behind the storage to be created and registered.
+     *        The service URI is a unique identifier of the storage and it is used as the lookup key in
+     *        {@link Registry#getService(URI) Registry.getStorage()}. It <i>must not be</i> <code>null</code>. See also {@link IStorageService#getServiceURI()}.<p>
+     *
+     * @return the newly created and registered storage, never <code>null</code>.<p>
+     * @throws IllegalStateException if a storage with the same <code>serviceURI</code> is already registered in this registry.<p>
+     *
+     * @see #addService(String, URI, URI, URI, URI, String)
+     */
+    public IStorageService.Dynamic addService(String serviceLabel, URI serviceURI) throws IllegalStateException;
+
+    /**
+     * Refreshes the dynamic services from the underlying secure storage and returns the newly added services.
+     *
+     * @return the newly added services.<p>
+     */
+    public IStorageService.Dynamic[] refresh();
+
+    /**
+     * Adds the given listener to the list of listeners that are notified about changes in this registry.
+     *
+     * @param listener the listener to add to the list of listeners that are notified about changes in this registry.
+     */
+    public void addListener(Listener listener);
+
+    /**
+     * Removes the given listener from the list of listeners that are notified about changes in this registry.
+     *
+     * @param listener the listener to remove from the list of listeners that are notified about changes in this registry.
+     */
+    public void removeListener(Listener listener);
+
+    /**
+     * Listens to changes in the {@link Registry#INSTANCE storage service registry}.
+     *
+     * @author Eike Stepper
+     */
+    public interface Listener
+    {
+      /**
+       * Called when a service has been added to the {@link Registry#INSTANCE storage service registry}.
+       *
+       * @param service the service that has been added to the registry, never <code>null</code>.
+       */
+      public void serviceAdded(IStorageService service);
+
+      /**
+       * Called when a service has been removed from the {@link Registry#INSTANCE storage service registry}.
+       *
+       * @param service the service that has been removed from the registry, never <code>null</code>.
+       */
+      public void serviceRemoved(IStorageService service);
+    }
+  }
+}
diff --git a/org.eclipse.userstorage/src/org/eclipse/userstorage/StorageFactory.java b/org.eclipse.userstorage/src/org/eclipse/userstorage/StorageFactory.java
new file mode 100644
index 0000000..eacd900
--- /dev/null
+++ b/org.eclipse.userstorage/src/org/eclipse/userstorage/StorageFactory.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others.
+ * 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:
+ *    Eike Stepper - initial API and implementation
+ */
+package org.eclipse.userstorage;
+
+import org.eclipse.userstorage.IStorageService.Registry;
+import org.eclipse.userstorage.internal.Storage;
+import org.eclipse.userstorage.spi.ISettings;
+import org.eclipse.userstorage.spi.StorageCache;
+import org.eclipse.userstorage.util.BadApplicationTokenException;
+import org.eclipse.userstorage.util.Settings;
+import org.eclipse.userstorage.util.Settings.MemorySettings;
+
+/**
+ * Creates {@link IStorage storages} and maintains their preferred {@link IStorage#getService() services}
+ * in the supplied {@link #getSettings() settings}.
+ *
+ * @author Eike Stepper
+ */
+public final class StorageFactory
+{
+  public static final StorageFactory DEFAULT = new StorageFactory(Settings.DEFAULT);
+
+  private final ISettings settings;
+
+  /**
+   * Constructs this storage factory with the given settings.
+   *
+   * @param settings the settings to use with this storage factory, or <code>null</code> for {@link Settings#NONE no settings}.
+   */
+  public StorageFactory(ISettings settings)
+  {
+    this.settings = settings != null ? settings : Settings.NONE;
+  }
+
+  /**
+   * Constructs this storage factory with {@link MemorySettings in-memory settings}.
+   */
+  public StorageFactory()
+  {
+    this(new MemorySettings());
+  }
+
+  /**
+   * Returns the settings of this factory.
+   *
+   * @return the settings of this factory, never <code>null</code>.
+   */
+  public ISettings getSettings()
+  {
+    return settings;
+  }
+
+  /**
+   * Creates a storage for the application identified by the given application token.
+   * <p>
+   * This factory searches for a {@link IStorage#getService() storage service} in the following order:
+   * <p>
+   * <ol>
+   * <li> Look-up a mapping for the <code>applicationToken</code> in the {@link #getSettings() settings} of this factory.
+   * <li> Look-up a mapping for <code>"&lt;default>"</code> in the {@link #getSettings() settings} of this factory.
+   * <li> Look-up the first service in the {@link IStorageService.Registry storage service registry}.
+   * <li> No service is assigned if the {@link Registry storage service registry} is empty.
+   * </ol>
+   * <p>
+   * Calling this method is identical to calling <code>create(applicationToken, null)</code>.
+   * <p>
+   *
+   * @param applicationToken the application token that identifies the application of the storage to be created.
+   *        Minimal {@link BadApplicationTokenException#validate(String) lexical validation} is performed on the passed application token.<p>
+   * @return the newly created storage, never <code>null</code>.<p>
+   * @throws BadApplicationTokenException if {@link BadApplicationTokenException#validate(String) lexical validation} of the passed application token fails.<p>
+   *
+   * @see #create(String, StorageCache)
+   */
+  public IStorage create(String applicationToken) throws BadApplicationTokenException
+  {
+    return create(applicationToken, null);
+  }
+
+  /**
+   * Creates a storage for the application identified by the given application token and associates it with a given {@link StorageCache storage cache}.