diff --git a/Kieker.WebGUI/README b/Kieker.WebGUI/README
new file mode 100644
index 0000000000000000000000000000000000000000..234eaefcfaab63cacf4b4186a02fa323ce9a57b5
--- /dev/null
+++ b/Kieker.WebGUI/README
@@ -0,0 +1 @@
+In order to start the WebGUI use either "mvn jetty:run" or "mvn package" in combination with the corresponding script in the bin-directory. The GUI is available under "http://localhost:8080/Kieker.WebGUI/" after it has been started.
\ No newline at end of file
diff --git a/Kieker.WebGUI/lib/kieker-1.6-SNAPSHOT_emf.jar b/Kieker.WebGUI/lib/kieker-1.6-SNAPSHOT_emf.jar
index e1c53890f254d4bbc0f6c83f5811bbba6960533e..f3a97619cb3f4660770e5aa0466e3ef3cb8ebe40 100644
Binary files a/Kieker.WebGUI/lib/kieker-1.6-SNAPSHOT_emf.jar and b/Kieker.WebGUI/lib/kieker-1.6-SNAPSHOT_emf.jar differ
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/CurrentWorkSpaceProjectBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/CurrentWorkSpaceProjectBean.java
index 360accae41dbc5a5c23af12148ff62690953ec70..618cdab97ec78846929ba6c428f5e88a9a2a72d3 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/CurrentWorkSpaceProjectBean.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/CurrentWorkSpaceProjectBean.java
@@ -25,7 +25,9 @@ import java.lang.reflect.Modifier;
 import java.net.MalformedURLException;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import javax.faces.application.FacesMessage;
 import javax.faces.application.FacesMessage.Severity;
@@ -35,7 +37,14 @@ import javax.faces.context.FacesContext;
 
 import kieker.analysis.model.analysisMetaModel.MIAnalysisMetaModelFactory;
 import kieker.analysis.model.analysisMetaModel.MIDependency;
+import kieker.analysis.model.analysisMetaModel.MIFilter;
+import kieker.analysis.model.analysisMetaModel.MIInputPort;
+import kieker.analysis.model.analysisMetaModel.MIOutputPort;
+import kieker.analysis.model.analysisMetaModel.MIPlugin;
 import kieker.analysis.model.analysisMetaModel.MIProject;
+import kieker.analysis.model.analysisMetaModel.MIProperty;
+import kieker.analysis.model.analysisMetaModel.MIRepository;
+import kieker.analysis.model.analysisMetaModel.MIRepositoryConnector;
 import kieker.analysis.model.analysisMetaModel.impl.MAnalysisMetaModelFactory;
 import kieker.analysis.plugin.AbstractPlugin;
 import kieker.analysis.plugin.annotation.Plugin;
@@ -43,10 +52,12 @@ import kieker.analysis.plugin.filter.AbstractFilterPlugin;
 import kieker.analysis.plugin.reader.AbstractReaderPlugin;
 import kieker.analysis.repository.AbstractRepository;
 import kieker.analysis.repository.annotation.Repository;
+import kieker.common.configuration.Configuration;
 import kieker.webgui.common.FSManager;
 import kieker.webgui.common.Pair;
 import kieker.webgui.common.PluginFinder;
 import kieker.webgui.common.exception.LibraryAlreadyExistingException;
+import kieker.webgui.common.exception.NewerProjectException;
 
 import org.primefaces.event.FileUploadEvent;
 import org.primefaces.model.UploadedFile;
@@ -204,6 +215,9 @@ public final class CurrentWorkSpaceProjectBean {
 	 */
 	private void addLibrariesToModel() {
 		final List<MIDependency> libs = FSManager.getInstance().getModelLibraries(this.projectName);
+		// Add them, but remove all existing dependencies so far to avoid double entries. This also makes sure that the model - after it has been opened - points
+		// just to valid dependencies (and to all of them).
+		this.project.getDependencies().clear();
 		this.project.getDependencies().addAll(libs);
 	}
 
@@ -248,6 +262,7 @@ public final class CurrentWorkSpaceProjectBean {
 	public String clearProject() {
 		this.project = null;
 		this.projectName = null;
+		this.classLoader = null;
 		this.timeStamp = 0;
 
 		return CurrentWorkSpaceProjectBean.PAGE_PROJECT_OVERVIEW;
@@ -295,8 +310,9 @@ public final class CurrentWorkSpaceProjectBean {
 			CurrentWorkSpaceProjectBean.showMessage(FacesMessage.SEVERITY_INFO, "Libary uploaded.");
 			// As it seem to have worked, we can add the library to our model.
 			this.project.getDependencies().add(lib);
-			// Update our class loader
+			// Update our class loader and the available plugins & repositories
 			this.reloadClassLoader();
+			this.addToToolPalette(lib);
 		} catch (final LibraryAlreadyExistingException ex) {
 			CurrentWorkSpaceProjectBean.showMessage(FacesMessage.SEVERITY_WARN, "A library with the same name exists already.");
 		} catch (final IOException ex) {
@@ -341,6 +357,185 @@ public final class CurrentWorkSpaceProjectBean {
 		return this.availableRepositories;
 	}
 
+	/**
+	 * This method tries to save the current project and informs the user about success or fail.
+	 * 
+	 * @param overwriteNewerProject
+	 *            This flag determines whether a newer project should be overwritten.
+	 */
+	public void saveProject(final boolean overwriteNewerProject) {
+		try {
+			FSManager.getInstance().saveProject(this.projectName, this.project, this.timeStamp, overwriteNewerProject);
+			CurrentWorkSpaceProjectBean.showMessage(FacesMessage.SEVERITY_INFO, "Project saved.");
+			// Update the time stamp!
+			this.resetTimeStamp();
+		} catch (final IOException ex) {
+			CurrentWorkSpaceProjectBean.showMessage(FacesMessage.SEVERITY_ERROR, "An error occured while saving the projct.");
+		} catch (final NewerProjectException ex) {
+			CurrentWorkSpaceProjectBean.showMessage(FacesMessage.SEVERITY_WARN, "The project has been modified externally in the meanwhile.");
+		}
+	}
+
+	/**
+	 * This method fills the ports of the given plugin. In other words: It tries to instantiate the given class and to extract the ports. If the instantiation fails
+	 * (for various reasons), the method informs the user and executes normally - without an exception.
+	 * 
+	 * @param clazz
+	 *            The class to be used as a base.
+	 * @param plugin
+	 *            The plugin to be filled.
+	 */
+	private void fillPorts(final Class<AbstractPlugin> clazz, final MIPlugin plugin) {
+		try {
+			// Try to instantiate the given class, using the special constructor of Kieker.
+			final AbstractPlugin pluginInstance = clazz.getConstructor(Configuration.class).newInstance(new Configuration());
+
+			// Get the port and use them to initialize the model plugin.
+			final String[] inputPortNames = pluginInstance.getAllInputPortNames();
+			final String[] outputPortNames = pluginInstance.getAllOutputPortNames();
+			final String[] repositoryPortNames = pluginInstance.getAllRepositoryPortNames();
+
+			// Add input ports
+			if (plugin instanceof MIFilter) {
+				for (final String inputPortName : inputPortNames) {
+					final MIInputPort mInputPort = this.factory.createInputPort();
+					mInputPort.setName(inputPortName);
+					mInputPort.setParent((MIFilter) plugin);
+				}
+			}
+
+			// Add output ports.
+			for (final String outputPortName : outputPortNames) {
+				final MIOutputPort mOutputPort = this.factory.createOutputPort();
+				mOutputPort.setName(outputPortName);
+				mOutputPort.setParent(plugin);
+			}
+
+			// Add repository ports.
+			for (final String repositoryPortName : repositoryPortNames) {
+				final MIRepositoryConnector mConnector = this.factory.createRepositoryConnector();
+				mConnector.setName(repositoryPortName);
+				plugin.getRepositories().add(mConnector);
+			}
+
+		} catch (final Exception ex) {
+			// Inform the user about the fail!
+			CurrentWorkSpaceProjectBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the ports of the plugin.");
+		}
+	}
+
+	/**
+	 * This method fills the properties of the given repository. In other words: It tries to instantiate the given class and to extract the configuration keys. If
+	 * the instantiation fails (for various reasons), the method informs the user and executes normally - without an exception.
+	 * 
+	 * @param clazz
+	 *            The class to be used as a base.
+	 * @param repository
+	 *            The repository to be filled.
+	 */
+	private void fillProperties(final Class<AbstractRepository> clazz, final MIRepository repository) {
+		try {
+			// Try to instantiate the given class, using the special constructor of Kieker.
+			final AbstractRepository repositoryInstance = clazz.getConstructor(Configuration.class).newInstance(new Configuration());
+			// Get the current configuration and use it to initialize the model repository, as THIS configuration instance will contain all keys.
+			final Configuration configuration = repositoryInstance.getCurrentConfiguration();
+
+			repository.getProperties().addAll(this.extractProperties(configuration));
+		} catch (final Exception ex) {
+			// Inform the user about the fail!
+			CurrentWorkSpaceProjectBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the properties of the repository.");
+		}
+	}
+
+	/**
+	 * This method fills the properties of the given plugin. In other words: It tries to instantiate the given class and to extract the configuration keys. If
+	 * the instantiation fails (for various reasons), the method informs the user and executes normally - without an exception.
+	 * 
+	 * @param clazz
+	 *            The class to be used as a base.
+	 * @param plugin
+	 *            The plugin to be filled.
+	 */
+	private void fillProperties(final Class<AbstractPlugin> clazz, final MIPlugin plugin) {
+		try {
+			// Try to instantiate the given class, using the special constructor of Kieker.
+			final AbstractPlugin pluginInstance = clazz.getConstructor(Configuration.class).newInstance(new Configuration());
+			// Get the current configuration and use it to initialize the model plugin, as THIS configuration instance will contain all keys.
+			final Configuration configuration = pluginInstance.getCurrentConfiguration();
+
+			plugin.getProperties().addAll(this.extractProperties(configuration));
+		} catch (final Exception ex) {
+			// Inform the user about the fail!
+			CurrentWorkSpaceProjectBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the properties of the plugin.");
+		}
+	}
+
+	/**
+	 * This method extracts the properties from the given configuration. In other words: For every key within the configuration, the method creates a model
+	 * counterpart.
+	 * 
+	 * @param configuration
+	 *            The configuration to be used for extraction.
+	 * @return The list containing one {@link MIProperty} for every key within the configuration.
+	 */
+	private List<MIProperty> extractProperties(final Configuration configuration) {
+		final List<MIProperty> result = new ArrayList<MIProperty>();
+
+		// Run through all entries.
+		final Iterator<Map.Entry<Object, Object>> iterator = configuration.entrySet().iterator();
+		while (iterator.hasNext()) {
+			final Map.Entry<Object, Object> entry = iterator.next();
+			// Create a property object for the current entry.
+			final MIProperty property = this.factory.createProperty();
+			property.setName(entry.getKey().toString());
+			property.setValue(entry.getValue().toString());
+
+			result.add(property);
+		}
+
+		return result;
+	}
+
+	/**
+	 * This method adds a new repository to the current model, using the given instance of {@code Class} for it.
+	 * 
+	 * @param clazz
+	 *            The class of the repository to be added.
+	 */
+	public void addRepository(final Class<AbstractRepository> clazz) {
+		// Create a new instance for the model
+		final MIRepository repository = this.factory.createRepository();
+		repository.setClassname(clazz.getName());
+		repository.setName(clazz.getSimpleName());
+
+		this.fillProperties(clazz, repository);
+		// Add it to the project
+		this.project.getRepositories().add(repository);
+	}
+
+	/**
+	 * This method adds a new plugin to the current model, using the given instance of {@code Class} for it.
+	 * 
+	 * @param clazz
+	 *            The class of the plugin to be added. This can be both, a filter or a reader.
+	 */
+	public void addPlugin(final Class<AbstractPlugin> clazz) {
+		// Create a new instance for the model
+		final MIPlugin plugin;
+		if (AbstractReaderPlugin.class.isAssignableFrom(clazz)) {
+			plugin = this.factory.createReader();
+		} else {
+			plugin = this.factory.createFilter();
+		}
+		plugin.setClassname(clazz.getName());
+		plugin.setName(clazz.getSimpleName());
+
+		this.fillProperties(clazz, plugin);
+		this.fillPorts(clazz, plugin);
+		// Add it to the project
+		this.project.getPlugins().add(plugin);
+	}
+
 	/**
 	 * This method shows the current user a message by using the growl-component of PrimeFaces.
 	 * 
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/FSManager.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/FSManager.java
index 47c3f517a5b93026c7eaa89be586b196fe067a2e..02d116a7531c215bdb6cec9b8e74b2b58ed8d8ac 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/common/FSManager.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/FSManager.java
@@ -46,6 +46,7 @@ import kieker.analysis.model.analysisMetaModel.impl.MAnalysisMetaModelFactory;
 import kieker.common.logging.Log;
 import kieker.common.logging.LogFactory;
 import kieker.webgui.common.exception.LibraryAlreadyExistingException;
+import kieker.webgui.common.exception.NewerProjectException;
 import kieker.webgui.common.exception.ProjectAlreadyExistingException;
 
 import org.primefaces.model.UploadedFile;
@@ -199,6 +200,42 @@ public final class FSManager {
 		}
 	}
 
+	/**
+	 * This method tries to save the given project.
+	 * 
+	 * @param projectName
+	 *            The name of the project to be saved.
+	 * @param project
+	 *            The project to be saved.
+	 * @param timeStamp
+	 *            The time stamp, the given project has been opened (necessary to check for a newer version).
+	 * @param overwriteNewerProject
+	 *            This flag determines whether a newer project should be overwritten.
+	 * @throws IOException
+	 *             If something went wrong during saving the project.
+	 * @throws NewerProjectException
+	 *             This exception is raised if the time stamp of the project on the file system is newer than the given one <b>and</b> if the flag
+	 *             {@code overwriteNewerProject} is false. If it is true, a newer version will be overwritten.
+	 */
+	public void saveProject(final String projectName, final MIProject project, final long timeStamp, final boolean overwriteNewerProject) throws IOException,
+			NewerProjectException {
+		// Get the lock
+		final Object lock = this.getLock(projectName);
+		synchronized (lock) {
+			// Check for a newer version first
+			final long currTimeStamp = this.getCurrTimeStamp(projectName);
+			if (!overwriteNewerProject && (currTimeStamp > timeStamp)) {
+				throw new NewerProjectException("The project with the name '" + projectName + "' has a newer version on the FS.");
+			}
+
+			// Everything seems to be okay (or we should overwrite the current file). Try to save it. Assemble the path to the KAX-file for this purpose.
+			final File kaxFile = new File(FSManager.ROOT_DIRECTORY + File.separator + projectName + File.separator + projectName + "." + FSManager.KAX_EXTENSION);
+
+			// Try to save it.
+			AnalysisController.saveToFile(kaxFile, project);
+		}
+	}
+
 	/**
 	 * Returns a list containing all available projects on the FS as a string.
 	 * 
@@ -317,7 +354,7 @@ public final class FSManager {
 
 	/**
 	 * This method delivers all available libraries for the given project as a pair of strings. The first element is the name of the library, the second one the size
-	 * of the lib in MiBytes and as a human readable string.
+	 * of the lib in MiBytes and as a human readable string. If the given name is null, an empty list will be returned.
 	 * 
 	 * @param projectName
 	 *            The name of the project.
@@ -325,21 +362,23 @@ public final class FSManager {
 	 */
 	public List<Pair<String, String>> getLibraries(final String projectName) {
 		final List<Pair<String, String>> result = new ArrayList<Pair<String, String>>();
-		// Get the lock for the project
-		final Object lock = this.getLock(projectName);
-
-		synchronized (lock) {
-			// Run through the libs and put them into our list.
-			final File libDir = new File(FSManager.ROOT_DIRECTORY + File.separator + projectName + File.separator + FSManager.LIB_DIRECTORY);
-			final File files[] = libDir.listFiles();
-			if (files != null) {
-				for (final File file : files) {
-					if (file.getName().endsWith("." + FSManager.LIB_EXTENSION)) {
-						final float len = file.length() / 1024.0f / 1024.0f;
-						final NumberFormat numberFormat = new DecimalFormat("0.00");
-						numberFormat.setRoundingMode(RoundingMode.DOWN);
-						final String lenStr = numberFormat.format(len);
-						result.add(new Pair<String, String>(file.getName(), lenStr));
+		if (projectName != null) {
+			// Get the lock for the project
+			final Object lock = this.getLock(projectName);
+
+			synchronized (lock) {
+				// Run through the libs and put them into our list.
+				final File libDir = new File(FSManager.ROOT_DIRECTORY + File.separator + projectName + File.separator + FSManager.LIB_DIRECTORY);
+				final File files[] = libDir.listFiles();
+				if (files != null) {
+					for (final File file : files) {
+						if (file.getName().endsWith("." + FSManager.LIB_EXTENSION)) {
+							final float len = file.length() / 1024.0f / 1024.0f;
+							final NumberFormat numberFormat = new DecimalFormat("0.00");
+							numberFormat.setRoundingMode(RoundingMode.DOWN);
+							final String lenStr = numberFormat.format(len);
+							result.add(new Pair<String, String>(file.getName(), lenStr));
+						}
 					}
 				}
 			}
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/exception/NewerProjectException.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/exception/NewerProjectException.java
new file mode 100644
index 0000000000000000000000000000000000000000..552be8bd87279bb20ef4c016c7d2d01eeea001a2
--- /dev/null
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/exception/NewerProjectException.java
@@ -0,0 +1,50 @@
+/***************************************************************************
+ * Copyright 2012 by
+ *  + Christian-Albrechts-University of Kiel
+ *    + Department of Computer Science
+ *      + Software Engineering Group 
+ *  and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+
+package kieker.webgui.common.exception;
+
+/**
+ * This exception shows that an attempt of saving a project has failed, because a newer version is available. In other words: The project has been modified in the
+ * meanwhile.
+ * 
+ * @author Nils Christian Ehmke
+ * @version 1.0
+ */
+public class NewerProjectException extends Exception {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * Creates a new instance of this class.
+	 */
+	public NewerProjectException() {
+		// No code necessary
+	}
+
+	/**
+	 * Creates a new instance of this class using the given parameters.
+	 * 
+	 * @param msg
+	 *            The message used for the exception.
+	 */
+	public NewerProjectException(final String msg) {
+		super(msg);
+	}
+}
diff --git a/Kieker.WebGUI/src/main/webapp/ProjectWorkSpace.xhtml b/Kieker.WebGUI/src/main/webapp/ProjectWorkSpace.xhtml
index 8840130f1b086f6db96e4fdaa5aa7a0a80e825b1..a04156a80fea52f8ef1a52649b54422279c4e8d7 100644
--- a/Kieker.WebGUI/src/main/webapp/ProjectWorkSpace.xhtml
+++ b/Kieker.WebGUI/src/main/webapp/ProjectWorkSpace.xhtml
@@ -22,7 +22,10 @@
                 <h:form>
                     <p:menubar>
                         <p:submenu label="File">
-                            <p:menuitem value="Save Project" ajax="true" disabled="#{empty currentWorkSpaceProjectBean.project}"/>
+                            <p:menuitem value="Save Project" update=":messages" ajax="true" action="#{currentWorkSpaceProjectBean.saveProject(false)}" disabled="#{empty currentWorkSpaceProjectBean.project}"/>
+                            <p:menuitem value="Save Project As" update=":messages" ajax="true" disabled="#{empty currentWorkSpaceProjectBean.project}"/>
+                            <p:menuitem styleClass="Force-Save-Project-Button" value="Force Save Project" update=":messages" ajax="true" action="#{currentWorkSpaceProjectBean.saveProject(true)}" disabled="#{empty currentWorkSpaceProjectBean.project}"/>
+                            <p:separator/>
                             <p:menuitem value="Reset Project" ajax="true" disabled="#{empty currentWorkSpaceProjectBean.project}"/>
                             <p:separator/>
                             <p:menuitem value="Manage Libraries" onclick="manageLibrariesDialog.show()" ajax="true" disabled="#{empty currentWorkSpaceProjectBean.project}"/>
@@ -75,7 +78,8 @@
                         </p:tab>
                         <p:tab title="Repositories">
                             <ui:repeat value="#{currentWorkSpaceProjectBean.availableRepositories}" var="repository">
-                                <p:commandLink value="#{repository.simpleName}" update=":centerForm"/><br/>
+                                <p:commandLink id="repositoryLink" value="#{repository.simpleName}" action="#{currentWorkSpaceProjectBean.addRepository(repository)}" update=":centerForm"/><br/>
+                                <p:tooltip style="font-size: 15px" for="repositoryLink" value="#{currentWorkSpaceProjectBean.getDescription(repository)}"/>
                             </ui:repeat>
                         </p:tab>
                     </p:accordionPanel>
diff --git a/Kieker.WebGUI/src/main/webapp/css/ProjectWorkSpace.css b/Kieker.WebGUI/src/main/webapp/css/ProjectWorkSpace.css
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..dcb7112953fcc5128dc7f2b1a90b03d5e96168c9 100644
--- a/Kieker.WebGUI/src/main/webapp/css/ProjectWorkSpace.css
+++ b/Kieker.WebGUI/src/main/webapp/css/ProjectWorkSpace.css
@@ -0,0 +1,5 @@
+@charset "UTF-8";
+
+.Force-Save-Project-Button {
+    white-space: nowrap
+}
\ No newline at end of file
diff --git a/Kieker.WebGUI/src/main/webapp/dialogs/manageLibrariesDialog.xhtml b/Kieker.WebGUI/src/main/webapp/dialogs/manageLibrariesDialog.xhtml
index 9e4df24417d2b9c70f62fbfec9def811bc98f2ad..a0cd9fcc82fe839676ec47e44a976c2a4c34f37a 100644
--- a/Kieker.WebGUI/src/main/webapp/dialogs/manageLibrariesDialog.xhtml
+++ b/Kieker.WebGUI/src/main/webapp/dialogs/manageLibrariesDialog.xhtml
@@ -33,7 +33,7 @@
             <br />
             <br />
             <h:form enctype="multipart/form-data">
-                <p:fileUpload auto="true" allowTypes="/(\.|\/)(jar)$/"  sizeLimit="104857600" mode="advanced" fileUploadListener="#{currentWorkSpaceProjectBean.handleFileUpload}" update=":dependenciesForm :messages"/>
+                <p:fileUpload auto="true" allowTypes="/(\.|\/)(jar)$/"  sizeLimit="104857600" mode="advanced" fileUploadListener="#{currentWorkSpaceProjectBean.handleFileUpload}" update=":dependenciesForm :messages :toolpalette"/>
             </h:form>
         </div>
         <hr/>