You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by ss...@apache.org on 2013/02/22 16:21:37 UTC

[7/37] MARMOTTA-105: renamed packages in marmotta-core

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4d3eebdd/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/modules/ModuleServiceImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/modules/ModuleServiceImpl.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/modules/ModuleServiceImpl.java
new file mode 100644
index 0000000..4eef08e
--- /dev/null
+++ b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/modules/ModuleServiceImpl.java
@@ -0,0 +1,291 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 org.apache.marmotta.platform.core.services.modules;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.marmotta.platform.core.api.modules.ModuleService;
+import org.apache.marmotta.platform.core.model.module.ModuleConfiguration;
+import org.apache.commons.configuration.CompositeConfiguration;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.spi.InjectionPoint;
+import java.io.IOException;
+import java.net.JarURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Add file description here!
+ * <p/>
+ * User: sschaffe
+ */
+@ApplicationScoped
+public class ModuleServiceImpl implements ModuleService {
+
+    private Logger log = LoggerFactory.getLogger(ModuleServiceImpl.class);
+
+    private Set<String> modules;
+
+    private Map<String,Configuration> configurationMap;
+    private Map<String, Configuration> jarURLs;
+
+    @PostConstruct
+    public void initialize() {
+        modules = new HashSet<String>();
+        configurationMap = new HashMap<String, Configuration>();
+        jarURLs = new HashMap<String, Configuration>();
+
+        try {
+            Enumeration<URL> modulePropertiesEnum = this.getClass().getClassLoader().getResources("kiwi-module.properties");
+
+            while(modulePropertiesEnum.hasMoreElements()) {
+                URL moduleUrl = modulePropertiesEnum.nextElement();
+
+                Configuration moduleProperties = null;
+                try {
+                    Set<Configuration> configurations = new HashSet<Configuration>();
+
+                    // get basic module configuration
+                    moduleProperties = new PropertiesConfiguration(moduleUrl);
+                    configurations.add(moduleProperties);
+
+                    String moduleName = moduleProperties.getString("name");
+                    modules.add(moduleName);
+
+
+                    URLConnection urlConnection = moduleUrl.openConnection();
+                    URL jarUrl;
+                    if(urlConnection instanceof JarURLConnection) {
+                        JarURLConnection conn = (JarURLConnection)urlConnection;
+                        jarUrl = conn.getJarFileURL();
+                    } else {
+                        String fileUrl = moduleUrl.toString();
+                        jarUrl = new URL(fileUrl.substring(0,fileUrl.lastIndexOf("/")));
+                    }
+
+
+
+                    // get the build information
+                    try {
+                        PropertiesConfiguration buildInfo = new PropertiesConfiguration(new URL("jar:"+jarUrl.toString()+"!/buildinfo.properties"));
+                        buildInfo.setDelimiterParsingDisabled(true);
+                        configurations.add(buildInfo);
+                    } catch(ConfigurationException ex) {
+                    }
+
+                    // alternative: maven buildinfo plugin
+                    try {
+                        PropertiesConfiguration buildInfo = new PropertiesConfiguration(new URL("jar:"+jarUrl.toString()+"!/build.info"));
+                        buildInfo.setDelimiterParsingDisabled(true);
+                        configurations.add(buildInfo);
+                    } catch(ConfigurationException ex) {
+                    }
+
+
+
+                    // create runtime configuration
+                    MapConfiguration runtimeConfiguration = new MapConfiguration(new HashMap<String, Object>());
+                    runtimeConfiguration.setProperty("runtime.jarfile", jarUrl.toString());
+                    configurations.add(runtimeConfiguration);
+
+
+                    CompositeConfiguration moduleConfiguration = new CompositeConfiguration(configurations);
+                    configurationMap.put(moduleName, moduleConfiguration);
+                    jarURLs.put(jarUrl.toString(), moduleConfiguration);
+
+                } catch (ConfigurationException e) {
+                    log.error("error parsing kiwi-module.properties file at {}",moduleUrl,e);
+                }
+
+
+            }
+        } catch (IOException ex) {
+            log.error("I/O error while trying to retrieve kiwi-module.properties file",ex);
+        }
+    }
+
+    /**
+     * Provide the current module configuration to the service injecting it
+     *
+     */
+    @Override
+    @Produces
+    public ModuleConfiguration getModuleConfiguration(InjectionPoint injectionPoint) {
+        URL jarUrl = injectionPoint.getMember().getDeclaringClass().getProtectionDomain().getCodeSource().getLocation();
+        Configuration cfg = jarURLs.get(jarUrl.toString());
+        if(cfg != null) {
+            return new ModuleConfiguration(cfg);
+        } else {
+            return new ModuleConfiguration(new MapConfiguration(new HashMap<String, Object>()));
+        }
+    }
+
+    /**
+     * Provide the current module configuration for the given class, i.e. the configuration of the
+     * module containing the class.
+     */
+    @Override
+    public ModuleConfiguration getModuleConfiguration(Class<?> cls) {
+        URL jarUrl = cls.getProtectionDomain().getCodeSource().getLocation();
+        Configuration cfg = jarURLs.get(jarUrl.toString());
+        if(cfg != null) {
+            return new ModuleConfiguration(cfg);
+        } else {
+            return new ModuleConfiguration(new MapConfiguration(new HashMap<String, Object>()));
+        }
+    }
+
+    /**
+     * Return a list of entities used by this module. Each entry is a fully-qualified classname of
+     * an entity class that this module registers.
+     *
+     * @param moduleName
+     * @return
+     */
+    @Override
+    public Collection<String> getEntities(String moduleName) {
+        Configuration config = getModuleConfiguration(moduleName).getConfiguration();
+        if(config != null) return ImmutableList.copyOf(config.getStringArray("entities"));
+        else
+            return null;
+    }
+
+    /**
+     * List the names of all currently active modules
+     *
+     * @return
+     */
+    @Override
+    public Collection<String> listModules() {
+        return modules;
+    }
+
+    /**
+     * Return the configuration for the module identified by the name given as argument. Returns an
+     * immutable Apache Commons Configuration object, or null if the module is not found.
+     *
+     * @param moduleName
+     * @return
+     */
+    @Override
+    public ModuleConfiguration getModuleConfiguration(String moduleName) {
+
+        Configuration cfg = configurationMap.get(moduleName);
+        if(cfg != null) {
+            return new ModuleConfiguration(cfg);
+        } else {
+            return new ModuleConfiguration(new MapConfiguration(new HashMap<String, Object>()));
+        }
+    }
+
+    /**
+     * Get the URL of the JAR file of the module whose name is given as argument.
+     *
+     * @param moduleName
+     * @return
+     */
+    @Override
+    public URL getModuleJar(String moduleName) {
+        try {
+            return new URL(configurationMap.get(moduleName).getString("runtime.jarfile"));
+        } catch (MalformedURLException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Get the path relative to the LMF base URL where the web contents of this URL can be found
+     *
+     * @param moduleName
+     * @return
+     */
+    @Override
+    public String getModuleWeb(String moduleName) {
+        Configuration config = getModuleConfiguration(moduleName).getConfiguration();
+        if(config != null) return config.getString("baseurl", "/" + moduleName);
+        else
+            return null;
+    }
+
+    /**
+     * Return a list of webservices used by this module. Each entry is a fully-qualified classname
+     * of a webservice class that this module registers.
+     *
+     * @param moduleName
+     * @return
+     */
+    @Override
+    public Collection<String> getWebservices(String moduleName) {
+        Configuration config = getModuleConfiguration(moduleName).getConfiguration();
+        if(config != null) return ImmutableList.copyOf(config.getStringArray("webservices"));
+        else
+            return null;
+    }
+
+    /**
+     * Return a list of filters used by this module. Each entry is a fully-qualified classname
+     * of a filter class implementing LMFHttpFilter that this module registers.
+     *
+     * @param moduleName
+     * @return
+     */
+    @Override
+    public Collection<String> getFilters(String moduleName) {
+        Configuration config = getModuleConfiguration(moduleName).getConfiguration();
+        if(config != null) return ImmutableList.copyOf(config.getStringArray("filters"));
+        else
+            return null;
+    }
+
+    /**
+     * Return a list of admin pages (paths)
+     * @param moduleName
+     * @return
+     */
+    @Override
+    public List<String> getAdminPages(String moduleName) {
+        Configuration config = getModuleConfiguration(moduleName).getConfiguration();
+        if(config != null) return ImmutableList.copyOf(config.getStringArray("adminpages"));
+        else
+            return null;
+    }
+
+    @Override
+    public int getWeight(String moduleName) {
+        Configuration config = getModuleConfiguration(moduleName).getConfiguration();
+        if (config != null)
+            return config.getInt("weight", 50);
+        else
+            return 50;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4d3eebdd/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/prefix/PrefixCC.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/prefix/PrefixCC.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/prefix/PrefixCC.java
new file mode 100644
index 0000000..d96728d
--- /dev/null
+++ b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/prefix/PrefixCC.java
@@ -0,0 +1,107 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 org.apache.marmotta.platform.core.services.prefix;
+
+import org.apache.marmotta.platform.core.api.http.HttpClientService;
+import org.apache.marmotta.platform.core.api.prefix.PrefixProvider;
+import org.apache.marmotta.platform.core.util.http.HttpRequestUtil;
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpHead;
+import org.apache.http.util.EntityUtils;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import java.io.IOException;
+
+/**
+ * Prefix.cc Provider
+ * 
+ * @author Sergio Fernández
+ *
+ */
+@ApplicationScoped
+public class PrefixCC implements PrefixProvider {
+
+    private static final String URI = "http://prefix.cc/";
+    private static final String USER_AGENT = "LMF Prefix";
+
+    @Inject
+    private Logger log;
+
+    @Inject
+    private HttpClientService   httpClientService;
+
+    @Override
+    public String getNamespace(final String prefix) {
+        HttpGet get = new HttpGet(URI + prefix + ".file.json");
+        HttpRequestUtil.setUserAgentString(get, USER_AGENT);
+        get.setHeader("Accept", "application/json");
+        try {
+            return httpClientService.execute(get, new ResponseHandler<String>() {
+
+                @Override
+                public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
+                    try {
+                        if (200 == response.getStatusLine().getStatusCode()) {
+                            HttpEntity entity = response.getEntity();
+                            JSONObject json = new JSONObject(EntityUtils.toString(entity));
+                            return json.getString(prefix);
+                        } else {
+                            log.error("Error: prefix '" + prefix + "' not found at prefix.cc");
+                            return null;
+                        }
+                    } catch (JSONException e) {
+                        throw new IOException(e);
+                    }
+                }
+            });
+        } catch (Exception e) {
+            log.error("Error retrieving prefix '" + prefix + "' from prefix.cc: " + e.getMessage());
+            return null;
+        }
+    }
+
+    @Override
+    public String getPrefix(String namespace) {
+        HttpHead head = new HttpHead(URI + "reverse?uri=" + namespace);
+        HttpRequestUtil.setFollowRedirect(head, false);
+        HttpRequestUtil.setUserAgentString(head, USER_AGENT);
+        try {
+            return httpClientService.execute(head, new ResponseHandler<String>() {
+                @Override
+                public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
+                    if (response.containsHeader("location")) {
+                        Header location = response.getFirstHeader("location");
+                        return location.getValue().substring(URI.length());
+                    } else
+                        return null;
+                }
+            });
+        } catch (Exception e) {
+            log.error("Error trying to retrieve prefic.cc reverse lookup for namespace '" + namespace + "': " + e.getMessage());
+            return null;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4d3eebdd/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/prefix/PrefixServiceCC.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/prefix/PrefixServiceCC.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/prefix/PrefixServiceCC.java
new file mode 100644
index 0000000..6380442
--- /dev/null
+++ b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/prefix/PrefixServiceCC.java
@@ -0,0 +1,110 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 org.apache.marmotta.platform.core.services.prefix;
+
+import java.net.URISyntaxException;
+
+import org.apache.marmotta.platform.core.api.prefix.PrefixProvider;
+import org.apache.commons.lang.StringUtils;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Alternative;
+import javax.inject.Inject;
+
+/**
+ * Prefix manager supporting prefix.cc as eager external provider
+ * 
+ * @author Sergio Fernández
+ * 
+ */
+@Alternative
+@ApplicationScoped
+public class PrefixServiceCC extends PrefixServiceImpl {
+
+    @Inject
+    private PrefixProvider prefixcc;
+
+    public PrefixServiceCC() {
+        super();
+    }
+
+    @Override
+    public String getNamespace(String prefix) {
+        String namespace = super.getNamespace(prefix);
+        if (StringUtils.isNotBlank(namespace))
+            return namespace;
+        else
+            try {
+                return namespaceLookup(prefix);
+            } catch (Exception e) {
+                return null;
+            }
+    }
+
+    @Override
+    public String getPrefix(String namespace) {
+        String prefix = super.getPrefix(namespace);
+        if (StringUtils.isNotBlank(prefix))
+            return prefix;
+        else
+            try {
+                return prefixLookup(namespace);
+            } catch (Exception e) {
+                return null;
+            }
+    }
+
+    @Override
+    public boolean containsPrefix(String prefix) {
+        if (!super.containsPrefix(prefix)) {
+            try {
+                namespaceLookup(prefix);
+            } catch (Exception e) {
+                return false;
+            }
+        }
+        return super.containsPrefix(prefix);
+    }
+
+    @Override
+    public boolean containsNamespace(String namespace) {
+        if (!super.containsNamespace(namespace)) {
+            try {
+                prefixLookup(namespace);
+            } catch (Exception e) {
+                return false;
+            }
+        }
+        return super.containsNamespace(namespace);
+    }
+
+    private String prefixLookup(String namespace) throws IllegalArgumentException, URISyntaxException {
+        String prefix = prefixcc.getPrefix(namespace);
+        if (StringUtils.isNotBlank(prefix)) {
+            add(prefix, namespace);
+        }
+        return prefix;
+    }
+
+    private String namespaceLookup(String prefix) throws IllegalArgumentException, URISyntaxException {
+        String namespace = prefixcc.getNamespace(prefix);
+        if (StringUtils.isNotBlank(namespace)) {
+            add(prefix, namespace);
+        }
+        return namespace;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4d3eebdd/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/prefix/PrefixServiceImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/prefix/PrefixServiceImpl.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/prefix/PrefixServiceImpl.java
new file mode 100644
index 0000000..8dee712
--- /dev/null
+++ b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/prefix/PrefixServiceImpl.java
@@ -0,0 +1,184 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 org.apache.marmotta.platform.core.services.prefix;
+
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+import javax.inject.Inject;
+
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.core.api.prefix.PrefixService;
+import org.apache.marmotta.platform.core.events.ConfigurationChangedEvent;
+import org.apache.marmotta.platform.core.events.SesameStartupEvent;
+import org.apache.commons.lang.StringUtils;
+import org.apache.marmotta.commons.http.UriUtil;
+import org.slf4j.Logger;
+
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+
+/**
+ * Prefix Manager default implementation
+ * 
+ * @author Sergio Fernández
+ * 
+ */
+@ApplicationScoped
+public class PrefixServiceImpl implements PrefixService {
+
+    private static final String CONFIGURATION_PREFIX = "prefix";
+
+    @Inject
+    private Logger log;
+
+    @Inject
+    private ConfigurationService  configurationService;
+
+    private BiMap<String, String> cache;
+
+    public PrefixServiceImpl() {
+        super();
+        cache = HashBiMap.create();
+    }
+
+    protected void initialize(@Observes SesameStartupEvent event) {
+        for (String key : configurationService.listConfigurationKeys(CONFIGURATION_PREFIX)) {
+            String prefix = key.substring(CONFIGURATION_PREFIX.length() + 1);
+            String namespace = configurationService.getStringConfiguration(key);
+            cache.put(prefix, namespace);
+        }
+        addLocalMappings();
+    }
+
+    protected void onConfigurationChange(@Observes ConfigurationChangedEvent event) {
+        for (String changedKey : event.getKeys()) {
+            if (changedKey.startsWith(CONFIGURATION_PREFIX + ".")) {
+                String prefix = changedKey.substring(CONFIGURATION_PREFIX.length() + 1);
+                String namespace = configurationService.getStringConfiguration(changedKey);
+                cache.put(prefix, namespace);
+            }
+        }
+    }
+
+    protected void addLocalMappings() {
+        String base = configurationService.getBaseUri();
+        cache.put("local", base + ConfigurationService.RESOURCE_PATH + "/");
+        cache.put("context", base + ConfigurationService.CONTEXT_PATH + "/");
+    }
+
+    @Override
+    public String getNamespace(String prefix) {
+        return cache.get(prefix);
+    }
+
+    @Override
+    public String getPrefix(String namespace) {
+        return cache.inverse().get(namespace);
+    }
+
+    @Override
+    public synchronized void add(String prefix, String namespace) throws IllegalArgumentException, URISyntaxException {
+        if (cache.containsKey(prefix)) {
+            log.error("prefix " + prefix + " already managed");
+            throw new IllegalArgumentException("prefix " + prefix + " already managed, use forceAdd() if you'd like to force its rewrite");
+        } else {
+            String validatedNamespace = validateNamespace(namespace);
+            if (validatedNamespace != null) {
+                try {
+                    cache.put(prefix, validatedNamespace);
+                    configurationService.setConfiguration(CONFIGURATION_PREFIX + "." + prefix, validatedNamespace);
+                } catch (IllegalArgumentException e) {
+                    log.error("namespace " + validatedNamespace + " is already bound to '" + getPrefix(validatedNamespace) + "' prefix, use forceAdd() if you'd like to force its rewrite");
+                    throw new IllegalArgumentException("namespace " + validatedNamespace + " is already bound to '" + getPrefix(validatedNamespace) + "' prefix");
+                }
+            } else {
+                log.error("Namespace <" + namespace + "> is not valid");
+                throw new URISyntaxException(namespace, "Namespace <" + namespace + "> is not valid");
+            }
+        }
+    }
+
+    @Override
+    public void forceAdd(String prefix, String namespace) {
+        cache.forcePut(prefix, namespace);
+        configurationService.setConfiguration(CONFIGURATION_PREFIX + prefix, namespace);
+    }
+
+    @Override
+    public Map<String, String> getMappings() {
+        return Collections.unmodifiableMap(cache);
+    }
+
+    @Override
+    public boolean containsPrefix(String prefix) {
+        return cache.containsKey(prefix);
+    }
+
+    @Override
+    public boolean containsNamespace(String namespace) {
+        return cache.containsValue(namespace);
+    }
+
+    private String validateNamespace(String namespace) {
+        String last = namespace.substring(namespace.length() - 1);
+        if (last.compareTo("/") != 0) {
+            if (last.compareTo("#") != 0) {
+                namespace += "#";
+            }
+        }
+        if (UriUtil.validate(namespace)) {
+            return namespace;
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public String getCurie(String uri) {
+        if (UriUtil.validate(uri)) {
+            String ns = UriUtil.getNamespace(uri);
+            String ref = UriUtil.getReference(uri);
+            if (StringUtils.isNotBlank(ns) && StringUtils.isNotBlank(ref) && containsNamespace(ns))
+                return getPrefix(ns) + ":" + ref;
+            else
+                return null;
+        } else
+            return null;
+    }
+
+    @Override
+    public String serializePrefixMapping() {
+        StringBuffer sb = new StringBuffer();
+        for (Map.Entry<String, String> mapping : cache.entrySet()) {
+            sb.append("\n").append(mapping.getKey()).append(": ").append(mapping.getValue()).append(" ");
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public String serializePrefixesSparqlDeclaration() {
+        StringBuffer sb = new StringBuffer();
+        for (Map.Entry<String, String> mapping : cache.entrySet()) {
+            sb.append("PREFIX ").append(mapping.getKey()).append(": <").append(mapping.getValue()).append("> \n");
+        }
+        return sb.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4d3eebdd/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/sesame/KiWiSesameUtil.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/sesame/KiWiSesameUtil.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/sesame/KiWiSesameUtil.java
new file mode 100644
index 0000000..20850ed
--- /dev/null
+++ b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/sesame/KiWiSesameUtil.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 org.apache.marmotta.platform.core.services.sesame;
+
+import org.apache.marmotta.kiwi.model.rdf.KiWiTriple;
+import org.openrdf.model.Resource;
+import org.openrdf.model.Statement;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.RepositoryResult;
+
+import java.util.Date;
+
+/**
+ * Some utils to work with KiWi model and Sesame
+ * 
+ * @author Sebastian Schaffert
+ */
+public class KiWiSesameUtil {
+
+
+    /**
+     * Get the last modification of the set of triples passed as argument.
+     *
+     * @deprecated this class will be removed before the 2.6 release, the helper function should be moved elsewhere
+     * @return date
+     * @throws RepositoryException
+     */
+    public static Date lastModified(Resource resource, RepositoryConnection conn) throws RepositoryException {
+        Date last_modified = new Date(0);
+        RepositoryResult<Statement> triples = conn.getStatements(resource, null, null, false);
+        try {
+            while (triples.hasNext()) {
+                Statement triple = triples.next();
+                if (triple instanceof KiWiTriple) {
+                    KiWiTriple t = (KiWiTriple) triple;
+                    if (t.getCreated().getTime() > last_modified.getTime()) {
+                        last_modified = t.getCreated();
+                    }
+                }
+            }
+        } finally {
+            triples.close();
+        }
+        return last_modified;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4d3eebdd/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/sesame/ResourceSubjectMetadata.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/sesame/ResourceSubjectMetadata.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/sesame/ResourceSubjectMetadata.java
new file mode 100644
index 0000000..bd1b0a4
--- /dev/null
+++ b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/sesame/ResourceSubjectMetadata.java
@@ -0,0 +1,78 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 org.apache.marmotta.platform.core.services.sesame;
+
+import org.apache.marmotta.kiwi.model.rdf.KiWiAnonResource;
+import org.apache.marmotta.kiwi.model.rdf.KiWiUriResource;
+import org.openrdf.model.BNode;
+import org.openrdf.model.Resource;
+import org.openrdf.model.Value;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.event.base.RepositoryConnectionInterceptorAdapter;
+
+/**
+ * A filter/view on repositories that displays only the metadata for a resource
+ * 
+ * @author Sebastian Schaffert
+ *
+ */
+public class ResourceSubjectMetadata extends RepositoryConnectionInterceptorAdapter {
+
+    private Resource subject;
+
+    public ResourceSubjectMetadata(Resource subject) {
+        this.subject = subject;
+    }
+
+    @Override
+    public boolean add(RepositoryConnection conn, Resource s, org.openrdf.model.URI p, Value o, Resource... contexts) {
+        boolean denyAdd = true;
+        if (s instanceof org.openrdf.model.URI && subject instanceof org.openrdf.model.URI ) {
+            // if s is a URI and subject a KiWiUriResource, return
+            // true if they are different
+            denyAdd = !s.stringValue().equals(((KiWiUriResource) subject).toString());
+        } else if (s instanceof BNode && subject instanceof BNode) {
+            // if s is a BNode and subject a KiWiAnonResource,
+            // return true if they are different
+            denyAdd = !s.stringValue().equals(((KiWiAnonResource) subject).getID());
+        } else {
+            // in all other cases, return true to filter out the
+            // triple
+            denyAdd = true;
+        }
+        return denyAdd;
+    };
+
+    @Override
+    public boolean remove(RepositoryConnection conn, Resource s, org.openrdf.model.URI p, Value o, Resource... contexts) {
+        boolean denyRemove = true;
+        if (s instanceof org.openrdf.model.URI && subject instanceof org.openrdf.model.URI ) {
+            // if s is a URI and subject a KiWiUriResource, return
+            // true if they are different
+            denyRemove = !s.stringValue().equals(subject.stringValue());
+        } else if (s instanceof BNode && subject instanceof BNode) {
+            // if s is a BNode and subject a KiWiAnonResource,
+            // return true if they are different
+            denyRemove = !s.stringValue().equals(subject.stringValue());
+        } else {
+            // in all other cases, return true to filter out the
+            // triple
+            denyRemove = true;
+        }
+        return denyRemove;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4d3eebdd/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/statistics/StatisticsServiceImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/statistics/StatisticsServiceImpl.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/statistics/StatisticsServiceImpl.java
new file mode 100644
index 0000000..f536622
--- /dev/null
+++ b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/statistics/StatisticsServiceImpl.java
@@ -0,0 +1,186 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 org.apache.marmotta.platform.core.services.statistics;
+
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.core.api.statistics.StatisticsModule;
+import org.apache.marmotta.platform.core.api.statistics.StatisticsService;
+import org.apache.marmotta.platform.core.events.ConfigurationChangedEvent;
+import org.slf4j.Logger;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+import javax.inject.Named;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * StatisticsServiceImpl
+ *
+ * @author Sebastian Schaffert
+ *
+ */
+@ApplicationScoped
+@Named("kiwi.core.statisticsService")
+public class StatisticsServiceImpl implements StatisticsService {
+
+    private LinkedHashMap<String,StatisticsModule> modules;
+
+    private boolean enabled = false;
+
+    @Inject
+    private Logger log;
+
+    @Inject
+    private ConfigurationService configurationService;
+
+    /**
+     * Initialise all statistics modules that are found in the system
+     * @param modules
+     */
+    @Inject
+    protected void initModules(@Any Instance<StatisticsModule> modules) {
+        log.info("LMF StatisticsService starting up ...");
+
+        this.modules = new LinkedHashMap<String,StatisticsModule>();
+
+        for(StatisticsModule module : modules) {
+            registerModule(module.getName(),module);
+        }
+
+        if(configurationService.getBooleanConfiguration("statistics.enabled",false)) {
+            enableAll();
+        } else {
+            disableAll();
+        }
+    }
+
+    public void configurationChangedEvent(@Observes ConfigurationChangedEvent event) {
+        if (event.containsChangedKey("statistics.enabled")) {
+            if(configurationService.getBooleanConfiguration("statistics.enabled",false)) {
+                enableAll();
+            } else {
+                disableAll();
+            }
+        }
+    }
+
+
+
+    /* (non-Javadoc)
+     * @see kiwi.api.statistics.StatisticsService#enableAll()
+     */
+    @Override
+    public void enableAll() {
+        for(StatisticsModule mod : modules.values()) {
+            mod.enable();
+        }
+
+        enabled = true;
+    }
+
+    /* (non-Javadoc)
+     * @see kiwi.api.statistics.StatisticsService#disableAll()
+     */
+    @Override
+    public void disableAll() {
+        for(StatisticsModule mod : modules.values()) {
+            mod.disable();
+        }
+
+        enabled = false;
+    }
+
+
+
+    /* (non-Javadoc)
+     * @see kiwi.api.statistics.StatisticsService#isEnabled()
+     */
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    /* (non-Javadoc)
+     * @see kiwi.api.statistics.StatisticsService#enableModule(java.lang.String)
+     */
+    @Override
+    public void enableModule(String modName) {
+        if(modules.get(modName) != null) {
+            modules.get(modName).enable();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see kiwi.api.statistics.StatisticsService#disableModule(java.lang.String)
+     */
+    @Override
+    public void disableModule(String modName) {
+        if(modules.get(modName) != null) {
+            modules.get(modName).disable();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see kiwi.api.statistics.StatisticsService#registerModule(java.lang.String, kiwi.api.statistics.StatisticsModule)
+     */
+    @Override
+    public void registerModule(String modName, StatisticsModule mod) {
+        log.info("registering statistics module \"{}\"", modName);
+        modules.put(modName,mod);
+    }
+
+    /* (non-Javadoc)
+     * @see kiwi.api.statistics.StatisticsService#unregisterModule(kiwi.api.statistics.StatisticsModule)
+     */
+    @Override
+    public void unregisterModule(StatisticsModule mod) {
+        unregisterModule(mod.getName());
+    }
+
+    /* (non-Javadoc)
+     * @see kiwi.api.statistics.StatisticsService#unregisterModule(java.lang.String)
+     */
+    @Override
+    public void unregisterModule(String modName) {
+        log.info("unregistering statistics module \"{}\"", modName);
+        modules.remove(modName);
+    }
+
+
+    /* (non-Javadoc)
+     * @see kiwi.api.statistics.StatisticsService#getModule(java.lang.String)
+     */
+    @Override
+    public StatisticsModule getModule(String modName) {
+        return modules.get(modName);
+    }
+
+    /* (non-Javadoc)
+     * @see kiwi.api.statistics.StatisticsService#listModules()
+     */
+    @Override
+    public List<String> listModules() {
+        return new LinkedList<String>(modules.keySet());
+    }
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4d3eebdd/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/statistics/ehcache/EHCacheStatisticsModule.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/statistics/ehcache/EHCacheStatisticsModule.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/statistics/ehcache/EHCacheStatisticsModule.java
new file mode 100644
index 0000000..3b144da
--- /dev/null
+++ b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/statistics/ehcache/EHCacheStatisticsModule.java
@@ -0,0 +1,138 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 org.apache.marmotta.platform.core.services.statistics.ehcache;
+
+import org.apache.marmotta.platform.core.api.cache.CachingService;
+import org.apache.marmotta.platform.core.api.statistics.StatisticsModule;
+import net.sf.ehcache.Ehcache;
+import net.sf.ehcache.Statistics;
+import org.slf4j.Logger;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Offer statistical information about the EHCache caches used in the KiWi System
+ * <p/>
+ * User: sschaffe
+ */
+public class EHCacheStatisticsModule implements StatisticsModule {
+
+    @Inject
+    private Logger log;
+
+    @Inject
+    private CachingService cachingService;
+
+    @PostConstruct
+    public void initialize() {
+
+
+    }
+
+     /**
+     * Enable this module. Depending on the type of information, this may involve additional runtime overhead.
+     */
+    @Override
+    public void enable() {
+        for(String cacheName : cachingService.getCacheNames()) {
+             Ehcache cache = cachingService.getCacheByName(cacheName);
+             if(cache != null) {
+                 cache.setStatisticsEnabled(true);
+                 cache.setStatisticsAccuracy(Statistics.STATISTICS_ACCURACY_GUARANTEED);
+             }
+         }
+    }
+
+    /**
+     * Disable this module.
+     */
+    @Override
+    public void disable() {
+        for(String cacheName : cachingService.getCacheNames()) {
+             Ehcache cache = cachingService.getCacheByName(cacheName);
+             if(cache != null) {
+                 cache.setStatisticsEnabled(false);
+                 cache.setStatisticsAccuracy(Statistics.STATISTICS_ACCURACY_NONE);
+             }
+         }
+    }
+
+    /**
+     * Return true if the module is enabled.
+     *
+     * @return
+     */
+    @Override
+    public boolean isEnabled() {
+        return true;
+    }
+
+    /**
+     * Return all names of properties supported by this module.
+     *
+     * @return
+     */
+    @Override
+    public List<String> getPropertyNames() {
+
+        List<String> propertyNames = new LinkedList<String>();
+        for(String cacheName : cachingService.getCacheNames()) {
+            propertyNames.add(cacheName + " hits");
+            propertyNames.add(cacheName + " misses");
+            propertyNames.add(cacheName + " size");
+        }
+        return propertyNames;
+    }
+
+    /**
+     * Return the statistics as a map from key to value
+     *
+     * @return
+     */
+    @Override
+    public Map<String, String> getStatistics() {
+
+        LinkedHashMap<String,String> result = new LinkedHashMap<String, String>();
+        for(String cacheName : cachingService.getCacheNames()) {
+            Ehcache cache = cachingService.getCacheByName(cacheName);
+            if(cache != null) {
+                Statistics stat = cache.getStatistics();
+
+                result.put(cacheName + " hits",""+stat.getCacheHits());
+                result.put(cacheName + " misses",""+stat.getCacheMisses());
+                result.put(cacheName + " size",""+stat.getObjectCount());
+            } else {
+                log.warn("cache with name {} does not exist",cacheName);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Return the display name of the statistics module.
+     *
+     * @return
+     */
+    @Override
+    public String getName() {
+        return "Cache Statistics";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4d3eebdd/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/statistics/system/SystemStatisticsModule.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/statistics/system/SystemStatisticsModule.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/statistics/system/SystemStatisticsModule.java
new file mode 100644
index 0000000..9f976c7
--- /dev/null
+++ b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/statistics/system/SystemStatisticsModule.java
@@ -0,0 +1,112 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 org.apache.marmotta.platform.core.services.statistics.system;
+
+import org.apache.marmotta.platform.core.api.statistics.StatisticsModule;
+
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * SystemStatisticsModule
+ *
+ * @author Sebastian Schaffert
+ *
+ */
+public class SystemStatisticsModule implements StatisticsModule {
+
+
+    /**
+     * Return the display name of the statistics module.
+     *
+     * @return
+     */
+    @Override
+    public String getName() {
+        return "System Statistics";
+    }
+
+    /* (non-Javadoc)
+      * @see kiwi.api.statistics.StatisticsModule#enable()
+      */
+	@Override
+	public void enable() {
+		// do nothing, system statistics always enabled
+	}
+
+	/* (non-Javadoc)
+	 * @see kiwi.api.statistics.StatisticsModule#disable()
+	 */
+	@Override
+	public void disable() {
+		// do nothing, system statistics always enabled
+	}
+
+	
+	
+	/* (non-Javadoc)
+	 * @see kiwi.api.statistics.StatisticsModule#isEnabled()
+	 */
+	@Override
+	public boolean isEnabled() {
+		return true;
+	}
+
+	
+	
+	/* (non-Javadoc)
+	 * @see kiwi.api.statistics.StatisticsModule#getPropertyNames()
+	 */
+	@Override
+	public List<String> getPropertyNames() {
+		List<String> result = new LinkedList<String>();
+		
+		result.add("java version");
+		result.add("java vendor");
+		result.add("operating system");
+		
+		result.add("free memory");
+		result.add("total memory");
+		result.add("max memory");
+		
+		return result;
+	}
+
+	/* (non-Javadoc)
+	 * @see kiwi.api.statistics.StatisticsModule#getStatistics()
+	 */
+	@Override
+	public Map<String, String> getStatistics() {
+
+		
+		
+		LinkedHashMap<String,String> result = new LinkedHashMap<String, String>();
+
+		result.put("java version", System.getProperty("java.version"));
+		result.put("java vendor", System.getProperty("java.vendor"));
+		result.put("operating system", System.getProperty("os.name")+" ("+System.getProperty("os.version")+")");
+		
+		Runtime rt = Runtime.getRuntime();
+		result.put("free memory",""+rt.freeMemory()/(1024*1024)+"MB");
+		result.put("total memory",""+rt.totalMemory()/(1024*1024)+"MB");
+		result.put("max memory",""+rt.maxMemory()/(1024*1024)+"MB");
+		
+		return result;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4d3eebdd/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/task/TaskImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/task/TaskImpl.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/task/TaskImpl.java
new file mode 100644
index 0000000..c27682f
--- /dev/null
+++ b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/task/TaskImpl.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 org.apache.marmotta.platform.core.services.task;
+
+import org.apache.marmotta.platform.core.api.task.Task;
+import org.apache.marmotta.platform.core.api.task.TaskManagerService;
+
+
+class TaskImpl extends Task {
+
+    private static final String WAITING_DETAIL = "Waiting in status";
+
+    private final TaskManagerService manager;
+
+    TaskImpl(TaskManagerService manager, String uuid, String name, String group) {
+        super(uuid);
+        this.manager = manager;
+        this.name = name;
+        this.group = group;
+    }
+
+    @Override
+    public long endTask() {
+        long dur = System.currentTimeMillis() - started;
+        manager.endTask(this);
+        return dur;
+    }
+
+    public void subTastStarting(Task subTask) {
+        detailMessages.put(WAITING_DETAIL, getMessage());
+        updateMessage("waiting for Task " + subTask.getName() + " to complete");
+    }
+
+    public void subTaskEnded() {
+        updateMessage(detailMessages.remove(WAITING_DETAIL));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4d3eebdd/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/task/TaskManagerServiceImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/task/TaskManagerServiceImpl.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/task/TaskManagerServiceImpl.java
new file mode 100644
index 0000000..10a5ecd
--- /dev/null
+++ b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/task/TaskManagerServiceImpl.java
@@ -0,0 +1,268 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 org.apache.marmotta.platform.core.services.task;
+
+import org.apache.marmotta.platform.core.api.task.Task;
+import org.apache.marmotta.platform.core.api.task.TaskInfo;
+import org.apache.marmotta.platform.core.api.task.TaskManagerService;
+
+import org.apache.marmotta.commons.util.HashUtils;
+import org.slf4j.Logger;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+import java.util.WeakHashMap;
+
+@ApplicationScoped
+public class TaskManagerServiceImpl implements TaskManagerService {
+
+    private static final String                        DEFAULT_GROUP = "default";
+
+    private final WeakHashMap<Thread, Stack<TaskImpl>> tasks;
+
+    private final ThreadWatchdog watchdog;
+
+    @Inject
+    private Logger                                     log;
+
+    @Inject
+    public TaskManagerServiceImpl() {
+        tasks = new WeakHashMap<Thread, Stack<TaskImpl>>();
+        watchdog = new ThreadWatchdog(15000);
+    }
+
+    @PostConstruct
+    public void startup() {
+        watchdog.start();
+    }
+
+    /* (non-Javadoc)
+     * @see xx.test.taks.TaskManagerService#endTask(xx.test.taks.TaskInfo)
+     */
+    @Override
+    public void endTask(TaskInfo task) {
+        final Stack<TaskImpl> stack = getStack();
+        if (stack.contains(task)) {
+            while (!stack.isEmpty()) {
+                Task t = stack.pop();
+                if (t.equals(task)) {
+                    log.debug("Ending task {}.{}", t.getGroup(), t.getName());
+                    break;
+                } else {
+                    log.debug("Ending task {}.{} because it's a sub-task", t.getGroup(), t.getName());
+                    t.endTask();
+                }
+            }
+            if (!stack.isEmpty()) {
+                stack.peek().subTaskEnded();
+            }
+        } else {
+            log.debug("Not ending task {} because thread {} is not the owner", task.getName(), Thread.currentThread().getName());
+        }
+        if (stack.isEmpty()) {
+            tasks.remove(Thread.currentThread());
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see xx.test.taks.TaskManagerService#getTasks()
+     */
+    @Override
+    public List<TaskInfo> getTasks() {
+        LinkedList<TaskInfo> ts = new LinkedList<TaskInfo>();
+        for (Stack<TaskImpl> stack : tasks.values()) {
+            ts.addAll(stack);
+        }
+        return Collections.unmodifiableList(ts);
+    }
+
+    /* (non-Javadoc)
+     * @see xx.test.taks.TaskManagerService#getTask()
+     */
+    @Override
+    public Task getTask() {
+        return createTask(Thread.currentThread().getName());
+    }
+
+    /* (non-Javadoc)
+     * @see xx.test.taks.TaskManagerService#createTask(java.lang.String)
+     */
+    @Override
+    public Task createTask(String name, String group) {
+        final Stack<TaskImpl> stack = getStack();
+        final Task task;
+        if (stack.isEmpty())
+            return createSubTask(name, group);
+        else {
+            task = stack.peek();
+            task.updateName(name);
+            if (group != null) {
+                task.updateGroup(group);
+            }
+        }
+        return task;
+    }
+
+    @Override
+    public Task createTask(String string) {
+        return createTask(string, null);
+    }
+
+    /* (non-Javadoc)
+     * @see xx.test.taks.TaskManagerService#createSubTask(java.lang.String)
+     */
+    @Override
+    public Task createSubTask(String name) {
+        return createSubTask(name, null);
+    }
+
+    @Override
+    public Task createSubTask(String name, String group) {
+        final Stack<TaskImpl> stack = getStack();
+        final TaskImpl task;
+        synchronized (stack) {
+            task = new TaskImpl(this, createUUID(), name, group != null ? group : DEFAULT_GROUP);
+            if (!stack.isEmpty()) {
+                stack.peek().subTastStarting(task);
+            }
+            stack.push(task);
+        }
+        return task;
+    }
+
+    private String createUUID() {
+        final Thread t = Thread.currentThread();
+        String string = String.format("%d: %s %tR", t.getId(), t.getName(), new Date());
+        return HashUtils.md5sum(string);
+    }
+
+    private Stack<TaskImpl> getStack() {
+        final Thread key = Thread.currentThread();
+        Stack<TaskImpl> stack = tasks.get(key);
+        if (stack == null) {
+            stack = new Stack<TaskImpl>();
+            tasks.put(key, stack);
+        }
+        return stack;
+    }
+
+    /* (non-Javadoc)
+     * @see xx.test.taks.TaskManagerService#getTasksByGroup()
+     */
+    @Override
+    public Map<String, List<TaskInfo>> getTasksByGroup() {
+        Map<String, List<TaskInfo>> result = new LinkedHashMap<String, List<TaskInfo>>();
+
+        for (TaskInfo task : getTasks()) {
+            final String group = task.getGroup();
+            List<TaskInfo> list = result.get(group);
+            if (list == null) {
+                list = new LinkedList<TaskInfo>();
+                result.put(group, list);
+            }
+            list.add(task);
+        }
+
+        return result;
+    }
+
+    /* (non-Javadoc)
+     * @see xx.test.taks.TaskManagerService#getTasksByThread()
+     */
+    @Override
+    public Map<WeakReference<Thread>, Stack<TaskInfo>> getTasksByThread() {
+        Map<WeakReference<Thread>, Stack<TaskInfo>> result = new LinkedHashMap<WeakReference<Thread>, Stack<TaskInfo>>();
+
+        for (Map.Entry<Thread, Stack<TaskImpl>> e : tasks.entrySet()) {
+            Stack<TaskInfo> list = new Stack<TaskInfo>();
+            list.addAll(e.getValue());
+            result.put(new WeakReference<Thread>(e.getKey()), list);
+        }
+
+        return result;
+    }
+
+    private class ThreadWatchdog extends Thread {
+
+        private final long millis;
+        private boolean running;
+
+        public ThreadWatchdog(long millis) {
+            super("TaskThreadWatchdog");
+            this.millis = millis;
+        }
+
+        @Override
+        public void run() {
+            running = true;
+            log.trace("Watchdog: starting up");
+            final Task task = getTask();
+            int count = 0;
+            while (running) {
+                task.updateMessage("cleaning up");
+                task.updateProgress(++count);
+                try {
+                    HashSet<Thread> dead = new HashSet<Thread>();
+                    for (Thread t : tasks.keySet()) {
+                        if (!t.isAlive()) {
+                            dead.add(t);
+                        }
+                    }
+                    for (Thread t : dead) {
+                        log.debug("Watchdog: cleaning up dead thread " + t.getName());
+                        tasks.remove(t);
+                        t = null;
+                    }
+                    dead.clear();
+                    dead = null;
+                    task.updateMessage("sleeping");
+                    synchronized (ThreadWatchdog.this) {
+                        this.wait(millis);
+                    }
+                } catch (InterruptedException e) {
+                    // ignore
+                }
+            }
+            task.endTask();
+            log.trace("Watchdog: shutdown");
+        }
+
+        public void shutdown() {
+            running = false;
+            synchronized (this) {
+                this.notify();
+            }
+        }
+
+    }
+
+    @PreDestroy
+    public void shutdown() {
+        watchdog.shutdown();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4d3eebdd/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/templating/TemplatingHelper.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/templating/TemplatingHelper.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/templating/TemplatingHelper.java
new file mode 100644
index 0000000..253833d
--- /dev/null
+++ b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/templating/TemplatingHelper.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 org.apache.marmotta.platform.core.services.templating;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+import org.apache.marmotta.platform.core.api.templating.TemplatingService;
+
+import java.io.BufferedWriter;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Some methods useful for template working
+ * 
+ * @author Sergio Fernández
+ *
+ */
+public class TemplatingHelper {
+    
+    public static Configuration getConfiguration() {
+        Configuration cfg = new Configuration();
+        cfg.setClassForTemplateLoading(TemplatingHelper.class, TemplatingService.PATH);
+        return cfg;
+    }
+    
+    public static Template getTemplate(String name) throws IOException {
+        return getConfiguration().getTemplate(name);
+    }
+    
+    public static Template getTemplate(Configuration conf, String name) throws IOException {
+        return conf.getTemplate(name);
+    }
+    
+    public static String processTemplate(String name) throws IOException, TemplateException {
+        return processTemplate(name, new HashMap<String, Object>());
+    }
+
+    public static String processTemplate(String name, Map<String, Object> data) throws IOException, TemplateException {
+        Template tpl = getTemplate(name);
+        OutputStream os = new ByteArrayOutputStream();
+        Writer writer = new BufferedWriter(new OutputStreamWriter(os));
+        tpl.process(data, writer);
+        writer.flush();
+        return os.toString();
+    }
+
+    public static void processTemplate(String name, Writer writer) throws IOException, TemplateException {
+        processTemplate(name, new HashMap<String, Object>(), writer);
+    }
+
+    public static void processTemplate(String name, Map<String, Object> data, Writer writer) throws IOException, TemplateException {
+        Template tpl = getTemplate(name);
+        tpl.process(data, writer);
+        writer.flush();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/4d3eebdd/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/templating/TemplatingServiceImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/templating/TemplatingServiceImpl.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/templating/TemplatingServiceImpl.java
new file mode 100644
index 0000000..04ed71c
--- /dev/null
+++ b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/templating/TemplatingServiceImpl.java
@@ -0,0 +1,307 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * 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 org.apache.marmotta.platform.core.services.templating;
+
+import freemarker.template.Template;
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.core.api.modules.ModuleService;
+import org.apache.marmotta.platform.core.api.templating.TemplatingService;
+import org.apache.marmotta.platform.core.events.ConfigurationChangedEvent;
+import org.apache.marmotta.platform.core.exception.TemplatingException;
+import org.apache.marmotta.platform.core.model.template.MenuItem;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+import javax.inject.Inject;
+import javax.servlet.ServletContext;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * User: Thomas Kurz
+ * Date: 22.07.11
+ * Time: 13:06
+ */
+@ApplicationScoped
+public class TemplatingServiceImpl implements TemplatingService {
+
+    private ServletContext context;
+
+    private static enum Properties { HEAD, CONTENT }
+
+    @Inject
+    private ModuleService moduleService;
+
+    @Inject
+    private ConfigurationService configurationService;
+
+    //some statics
+    private static final String TEMPLATE_STRING = "admin.ftl";
+    private static final String DEFAULT_REST_PATH = "/doc/rest/";
+    private static final String DEFAULT_REST_FILE = "overview-summary.html";
+    private static final String DEFAULT_STYLE = "screen";
+    private static final String DEFAULT_TITLE_FOR_WEBSERVICES = "webservices";
+    private static final String DEFAULT_PROJECT = "lmf";
+
+    //pattern to filter comments content
+    private static final Pattern PATTERN = Pattern.compile("\\<!--###BEGIN_([^#]+)###--\\>(.+)\\<!--###END_\\1###--\\>",Pattern.DOTALL);
+    private Template tpl;
+    private Menu menu;
+
+    /**
+     * inits a freemarker template service with a servlet context
+     * @param context a servlet context
+     */
+    @Override
+    public void init(ServletContext context) throws TemplatingException {
+        this.context = context;
+        initDataModel();
+        try {
+            tpl = TemplatingHelper.getTemplate(TEMPLATE_STRING);
+        } catch (IOException e) {
+            //e.printStackTrace();
+            throw new TemplatingException(e.getMessage());
+        }
+    }
+
+    /**
+     * Check whether the templating service considers the resource passed in the path as a menu entry it is
+     * responsible for.
+     *
+     * @param path a url path
+     * @return if the give path points to an admin page
+     */
+    @Override
+    public boolean isMenuEntry(String path) {
+        if(menu.path_titles.keySet().contains(configurationService.getPath()+path)) return true;
+        if(path.contains(DEFAULT_REST_PATH)) return true;
+        else return false;
+    }
+
+    /**
+     * this method wraps a file with a specified admin template. If the file is not a admin page,
+     * the bytes are returned unprocessed
+     * @param bytes content represented in a byte array
+     * @return the processed (templated) byte array
+     */
+    @Override
+    public byte[] process(byte[] bytes, String path) throws TemplatingException {
+
+        if(!configurationService.getBooleanConfiguration("templating.cache.enabled",true) && context!=null) {
+            init(context);
+        }
+        //apply template
+        if(!isMenuEntry(path)) return bytes;
+        //activate
+        String module = menu.getCurrentModule(configurationService.getPath() + path);
+        //fill data model
+        @SuppressWarnings("unchecked")
+        Map<String, Object> datamodel = (Map<String, Object>)basic_map.clone();
+        //begin hack!!!
+        datamodel.put("USER_MODULE_IS_ACTIVE", moduleService.listModules().contains("Users"));
+        //end hack!!!
+        datamodel.put("MODULE_MENU",menu.menuItems);
+        datamodel.put("DEFAULT_STYLE", configurationService.getStringConfiguration("kiwi.pages.style", DEFAULT_STYLE));
+        datamodel.put("CURRENT_TITLE", getNameFromPath(path));
+        datamodel.put("CURRENT_MODULE",module);
+        try {
+            String s = new String(bytes);
+            Matcher m = PATTERN.matcher(s);
+            while (m.find()) {
+                datamodel.put(m.group(1),m.group(2));
+            }
+        } catch (Exception e) {
+            throw new TemplatingException(e.getMessage());
+        }
+
+        //make magic happen
+        try {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            tpl.process(datamodel, new OutputStreamWriter(bos));
+            bytes = bos.toByteArray();
+            bos.flush();
+            bos.close();
+        } catch (Exception e) {
+            throw new TemplatingException(e.getMessage());
+        }
+        return bytes;
+    }
+
+    //datamodel may not be empty
+    private HashMap<String,String> basic_map;
+    /**
+     * creates a data model, which contains all properties (with empty values)
+     */
+    private void initDataModel() {
+        basic_map = new HashMap<String,String>();
+        for(Properties p : Properties.values()) {
+            basic_map.put(p.name(),"<!-- "+p.name()+" not defined -->");
+        }
+        basic_map.put("SERVER_URL", configurationService.getServerUri());
+        basic_map.put("BASIC_URL", configurationService.getBaseUri());
+        String project = configurationService.getStringConfiguration("kiwi.pages.project", DEFAULT_PROJECT);
+        basic_map.put("PROJECT", project);
+        basic_map.put("LOGO", configurationService.getStringConfiguration("kiwi.pages.project."+project+".logo", project+".png"));
+        basic_map.put("FOOTER", configurationService.getStringConfiguration("kiwi.pages.project."+project+".footer", "(footer not properly configured for project "+project+")"));
+
+        menu = new Menu();
+    }
+
+    /**
+     * Update the data model in case an important value has changed
+     * @param event
+     */
+    public void configurationChangedEvent(@Observes ConfigurationChangedEvent event) {
+        if (event.getKeys().contains("kiwi.context")
+                || event.getKeys().contains("kiwi.host")
+                || event.getKeys().contains("templating.sort_by_weight")
+                || event.getKeys().contains("kiwi.pages.project")) {
+            initDataModel();
+        }
+    }
+
+    /**
+     * This object represents a menu for the admin interface. It is build using the ModuleService.
+     */
+    class Menu {
+
+        public List<MenuItem> menuItems;
+        public Map<String,String> path_titles;
+
+        public Menu() {
+            //instantiate
+            menuItems = new ArrayList<MenuItem>();
+            path_titles = new HashMap<String, String>();
+            //sort menu
+            ArrayList<String> menuSorted = new ArrayList<String>(moduleService.listModules());
+            if(configurationService.getBooleanConfiguration("templating.sort_by_weight",true)) {
+                Collections.sort(menuSorted, new Comparator<String>() {
+                    @Override
+                    public int compare(String o1, String o2) {
+                        final int w1 = moduleService.getWeight(o1), w2 = moduleService.getWeight(o2);
+                        if (w1 == w2) return o1.compareTo(o2);
+                        return w1 - w2;
+                    }
+                });
+            } else {
+                Collections.sort(menuSorted);
+            }
+
+            //build structure
+            for(String module : menuSorted) {
+                String path = configurationService.getPath() + moduleService.getModuleWeb(module);
+                if(moduleHasAdminPages(module)) {
+                    MenuItem menu_item = new MenuItem();
+                    menu_item.getProperties().put("title",module);
+                    menu_item.getProperties().put("baseurl",moduleService.getModuleConfiguration(module).getConfiguration().getString("baseurl","/"+module));
+                    for(String page : moduleService.getAdminPages(module)) {
+                        if(page.equals("")) {
+                            continue;
+                        }
+                        MenuItem submenu = new MenuItem();
+                        submenu.getProperties().put("title",getNameFromPath(page));
+                        submenu.getProperties().put("path",path+page);
+                        //test if it is active
+                        menu_item.getSubmenu().add(submenu);
+                        path_titles.put(path+page,page);
+                    }
+                    if(moduleService.getWebservices(module)!=null &&
+                            !moduleService.getWebservices(module).isEmpty() &&
+                            !moduleService.getWebservices(module).iterator().next().equals("")) {
+                        MenuItem submenu = new MenuItem();
+                        submenu.getProperties().put("title",DEFAULT_TITLE_FOR_WEBSERVICES);
+                        submenu.getProperties().put("path",path+DEFAULT_REST_PATH+DEFAULT_REST_FILE);
+                        //test if it is active
+                        menu_item.getSubmenu().add(submenu);
+                        path_titles.put(path+DEFAULT_REST_PATH+DEFAULT_REST_FILE,DEFAULT_TITLE_FOR_WEBSERVICES);
+                    }
+                    menuItems.add(menu_item);
+                }
+            }
+        }
+
+        /**
+         * get current module and set submenu to active
+         * @param path the current system path
+         * @return current module name
+         */
+        public String getCurrentModule(String path) {
+            String module = "";
+            boolean active = false;
+            //test with module and submenu must be active
+            for(MenuItem menuItem : menuItems) {
+                if(path.startsWith((String)menuItem.getProperties().get("baseurl"))) {
+                    module = (String)menuItem.getProperties().get("title");
+                }
+                for(MenuItem submenu : menuItem.getSubmenu()) {
+                    if(submenu.getProperties().get("path").equals(path)) {
+                        submenu.getProperties().put("active",true);
+                        module = (String)menuItem.getProperties().get("title");
+                        active = true;
+                    } else {
+                        submenu.getProperties().put("active",false);
+                    }
+                }
+            }
+            //workaround for webservices (autogenerated pages that are nit fix stored in the menu structure)
+            if(!active) {
+                for(MenuItem menuItem : menuItems) {
+                    if(module.equals(menuItem.getProperties().get("title"))) {
+                        for(MenuItem submenu : menuItem.getSubmenu()) {
+                            if(submenu.getProperties().get("title").equals(DEFAULT_TITLE_FOR_WEBSERVICES)) {
+                                submenu.getProperties().put("active",true);
+                            }
+                        }
+                    }
+                }
+            }
+            return module;
+        }
+
+        /**
+         * Tests if a module should appear in the menu
+         * @param module a module name
+         * @return true is module should appear, false if not
+         */
+        private boolean moduleHasAdminPages(String module) {
+            if(moduleService.getAdminPages(module)!=null &&
+                    !moduleService.getAdminPages(module).isEmpty() &&
+                    !moduleService.getAdminPages(module).get(0).equals(""))
+                return true;
+            else if(moduleService.getWebservices(module)!=null &&
+                    !moduleService.getWebservices(module).isEmpty() &&
+                    !moduleService.getWebservices(module).iterator().next().equals("")) return true;
+            return false;
+        }
+
+    }
+
+    /**
+     * returns a proper name for a path by using the filename.
+     * @param path
+     * @return
+     */
+    private String getNameFromPath(String path) {
+        if(path.contains(DEFAULT_REST_PATH)) return DEFAULT_TITLE_FOR_WEBSERVICES;
+        return path.substring(path.lastIndexOf("/")).replaceAll("/"," ").replaceAll("_"," ").replaceAll(".html","").replaceAll(".jsp","");
+    }
+
+}