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:36 UTC
[31/37] MARMOTTA-105: refactoring of packages in remaining platform
modules
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/api/UserConfigurationService.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/api/UserConfigurationService.java b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/api/UserConfigurationService.java
new file mode 100644
index 0000000..54e8da4
--- /dev/null
+++ b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/api/UserConfigurationService.java
@@ -0,0 +1,99 @@
+/**
+ * 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.user.api;
+
+import org.apache.marmotta.platform.user.model.UserAccount;
+
+import java.util.List;
+
+/**
+ * Add file description here!
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+public interface UserConfigurationService {
+
+
+ /**
+ * Check whether the given configuration is set for the given user.
+ *
+ * @param user
+ * @param key
+ * @return
+ */
+ public boolean isUserConfigurationSet(UserAccount user, String key);
+
+ /**
+ * Get the configuration for the given user and key. If there is no such configuration, a new one is
+ * created with empty value (returns null).
+ *
+ * @param user the user for whom to get the configuration
+ * @param key unique configuration key for lookup
+ * @return a configuration object with either the configured value or null as value
+ */
+ public String getUserConfiguration(UserAccount user, String key);
+
+ /**
+ * Get the configuration for the given user and key. If there is no such configuration, a new one is
+ * created using the provided defaultValue as string value.
+ *
+ * @param user the user for whom to get the configuration
+ * @param key unique configuration key for lookup
+ * @param defaultValue default value if configuration not found
+ * @return a configuration object with either the configured value or defaultValue
+ */
+ public String getUserConfiguration(UserAccount user, String key, String defaultValue);
+
+
+ /**
+ * Set the configuration "key" to the string value "value".
+ * @param key
+ * @param value
+ */
+ public void setUserConfiguration(UserAccount user, String key, String value);
+
+ /**
+ * Set the configuration "key" to the string value "value".
+ * @param key
+ * @param values
+ */
+ public void setUserListConfiguration(UserAccount user, String key, List<String> values);
+
+
+ /**
+ * Return the list configuration value of the given key for the given user. If there is
+ * no value for the key, returns the empty list.
+ *
+ * @param user
+ */
+ public List<Object> getUserListConfiguration(UserAccount user, String key);
+
+ /**
+ * Return the list configuration value of the given key for the given user. Returns the
+ * given defaultValue if no configuration is found for the given key.
+ *
+ * @param user
+ */
+ public List<Object> getUserListConfiguration(UserAccount user, String key, List<Object> defaultValue);
+
+ /**
+ * Remove the user configuration identified by "key" from the database.
+ * @param key
+ */
+ public void removeUserConfiguration(UserAccount user, String key);
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/filters/LMFAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/filters/LMFAuthenticationFilter.java b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/filters/LMFAuthenticationFilter.java
new file mode 100644
index 0000000..78b0043
--- /dev/null
+++ b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/filters/LMFAuthenticationFilter.java
@@ -0,0 +1,201 @@
+/**
+ * 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.user.filters;
+
+import org.apache.marmotta.platform.user.api.AuthenticationService;
+import org.apache.marmotta.commons.sesame.model.Namespaces;
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.core.api.modules.LMFHttpFilter;
+import org.apache.marmotta.platform.core.api.user.UserService;
+import org.apache.marmotta.platform.core.exception.UserExistsException;
+import org.apache.marmotta.platform.core.exception.security.AccessDeniedException;
+import org.jboss.resteasy.spi.UnhandledException;
+import org.openrdf.model.URI;
+import org.slf4j.Logger;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+import static org.apache.commons.codec.binary.Base64.decodeBase64;
+
+/**
+ * This filter implements HTTB Basic Authentication support for the LMF. It serves two purposes:
+ * <ul>
+ * <li>carrying out HTTP Basic Authentication when an "Authorization" header is present</li>
+ * <li>sending an HTTP authorization request in case one of the services in the chain threw an AccessDeniedException</li>
+ * </ul>
+ *
+ * In case security is enabled, it listens for the presence of an "Authorization" header, parses it according to HTTP Basic Authentication
+ * (Base64 decoding and splitting username/password at ":") and tries to authenticate with the given
+ * credentials using the LMF AuthenticationService.
+ * <ul>
+ * <li>In case authentication succeeds, it sets the attributes
+ * user.name and user.roles in the request so that further filters/services can make use of the
+ * authentication information, and it sets the current user for all activities carried out in the thread.</li>
+ * <li>In case authentication fails, no user information is added to the request.</li>
+ * </ul>
+ * The filter also listens for {@link org.apache.marmotta.platform.core.exception.security.AccessDeniedException} thrown by
+ * subsequent filters or servlets in the chain, in which case it returns an HTTP authorization request to the
+ * client. In particular, this functionality is used by the LMFAccessControlFilter to restrict access to
+ * services based on security profiles.
+ * <p/>
+ * @see UserService
+ *
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+@ApplicationScoped
+public class LMFAuthenticationFilter implements LMFHttpFilter {
+
+ @Inject
+ private Logger log;
+
+ @Inject
+ private ConfigurationService configurationService;
+
+ @Inject
+ private UserService userService;
+
+ @Inject
+ private AuthenticationService authenticationService;
+
+ /**
+ * Initialise authentication filter
+ */
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ log.info("LMF Authentication Filter starting up; user authentication is {}",configurationService.getBooleanConfiguration("security.enabled",true)?"enabled":"disabled");
+ }
+
+
+ /**
+ * Return the pattern (regular expression) that a request URI (relative to the LMF base URI) has to match
+ * before triggering this filter.
+ *
+ * @return
+ */
+ @Override
+ public String getPattern() {
+ return "^/.*";
+ }
+
+ /**
+ * Return the priority of the filter. Filters that need to be executed before anything else should return
+ * PRIO_FIRST, filters that need to be executed last in the chain should return PRIO_LAST, all other filters
+ * something inbetween (e.g. PRIO_MIDDLE).
+ *
+ * @return
+ */
+ @Override
+ public int getPriority() {
+ return PRIO_AUTH;
+ }
+
+ /**
+ * Check for the presence of a "Authorization" header in the request header and authorize the user if yes.
+ * Sets the attributes "user.name" and "user.roles" in the request for further processing.
+ */
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+ if(configurationService.getBooleanConfiguration("security.enabled",true)) {
+
+ HttpServletRequest httpRequest = (HttpServletRequest)request;
+
+ // check whether authentication information has been sent with the request
+
+ try {
+ String authorization = httpRequest.getHeader("Authorization");
+ if (authorization != null) {
+ boolean authSuccess = false;
+ String login = Namespaces.ANONYMOUS_LOGIN;
+ if (authorization.startsWith("Basic ")) {
+ String credentialsBase64 = authorization.split(" ")[1];
+ String credentialsPlain = new String(decodeBase64(credentialsBase64));
+ String[] credentials = credentialsPlain.split(":");
+ if (credentials.length == 2) {
+ login = credentials[0];
+ String passwd = credentials[1];
+
+ if (authenticationService.authenticateUser(login, passwd)) {
+ authSuccess = true;
+ httpRequest.setAttribute("user.name", login);
+ httpRequest.setAttribute("user.roles", authenticationService.listUserRoles(login));
+ URI user = userService.getUser(login);
+ if (user == null) {
+ try {
+ user = userService.createUser(login);
+ } catch (UserExistsException e) {
+ }
+ }
+ userService.setCurrentUser(user);
+ }
+ }
+ }
+ if (!authSuccess && !login.equals(Namespaces.ANONYMOUS_LOGIN)) {
+ // Apparently wrong username/passwd: ask for the correct one
+ throw new AccessDeniedException();
+ }
+ }
+
+ chain.doFilter(request,response);
+ } catch(AccessDeniedException ex) {
+ build401Response(response);
+ } catch (UnhandledException ue) {
+ // This is to handle AccessDeniedExeptions in REST-Webservices
+ if (ue.getCause().getClass().equals(AccessDeniedException.class)) {
+ build401Response(response);
+ } else
+ throw ue;
+ } finally {
+ userService.clearCurrentUser();
+ }
+ } else {
+ chain.doFilter(request,response);
+ }
+ }
+
+ private void build401Response(ServletResponse response) {
+ // access denied; request authentication
+ HttpServletResponse httpResponse = (HttpServletResponse)response;
+ httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+
+ String authMethod = "Basic";
+ if ("BASIC".equalsIgnoreCase(configurationService.getStringConfiguration("security.method", authMethod))) {
+ authMethod = "Basic";
+ // } else if("DIGEST".equalsIgnoreCase(configurationService.getStringConfiguration("security.method"))) {
+ // authMethod = "Digest";
+ }
+ String authRealm = configurationService.getStringConfiguration("security.realm","Linked Media Framework");
+
+ httpResponse.setHeader("WWW-Authenticate",authMethod + " realm=\""+authRealm+"\"");
+ }
+
+ /**
+ * Destroy authentication filter
+ */
+ @Override
+ public void destroy() {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/model/UserAccount.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/model/UserAccount.java b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/model/UserAccount.java
new file mode 100644
index 0000000..d042e40
--- /dev/null
+++ b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/model/UserAccount.java
@@ -0,0 +1,183 @@
+/**
+ * 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.user.model;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.marmotta.commons.util.HashUtils;
+
+/**
+ * User: Stephanie Stroka
+ * Date: 18.05.2011
+ * Time: 11:29:17
+ */
+
+public class UserAccount implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Enum of avalable password-hash algorithms.
+ *
+ * @author Jakob Frank <ja...@salzburgresearch.at>
+ *
+ */
+ public static enum PasswordHash {
+ PLAIN {
+ @Override
+ protected String hash(String in) {
+ return in;
+ }
+ },
+ MD5 {
+ @Override
+ protected String hash(String in) {
+ return HashUtils.md5sum(in);
+ }
+ },
+ SHA1 {
+ @Override
+ protected String hash(String in) {
+ return HashUtils.sha1(in);
+ }
+ };
+
+ public String encrypt(String passwd) {
+ return passwd == null ? null : ":" + this.toString().toLowerCase() + "::" + this.hash(passwd);
+ }
+
+ protected abstract String hash(String in);
+
+ private static final Pattern P = Pattern.compile(":(\\w+)::(.*)");
+
+ public static boolean checkPasswd(String encrypted, String passwd) {
+ if (encrypted != null && passwd != null) {
+ try {
+ Matcher m = P.matcher(encrypted);
+ if (m.matches()) {
+ final PasswordHash h = PasswordHash.valueOf(m.group(1).toUpperCase());
+ return encrypted.matches(h.encrypt(passwd));
+ }
+ } catch (Exception e) {
+ }
+ }
+ return false;
+ }
+
+ public static PasswordHash getPasswordHash(String passwdHash) {
+ if (passwdHash != null) {
+ try {
+ Matcher m = P.matcher(passwdHash);
+ if (m.matches()) {
+ final PasswordHash h = PasswordHash.valueOf(m.group(1).toUpperCase());
+ return h;
+ }
+ } catch (Exception e) {
+ }
+ }
+ return SHA1;
+ }
+ }
+
+
+ /* the user's credentials */
+ private String login;
+ private String passwdHash;
+
+ /* the user's webId that points to their RDF user profile */
+ private String webId;
+
+ private Set<String> roles;
+
+ public UserAccount() {
+ roles = new HashSet<String>();
+ }
+
+ public UserAccount(String login, String webId) {
+ this();
+ this.login = login;
+ this.webId = webId;
+ }
+
+ public String getLogin() {
+ return login;
+ }
+
+ public void setLogin(String login) {
+ this.login = login;
+ }
+
+ public String getPasswdHash() {
+ return passwdHash;
+ }
+
+ public void setPasswdHash(String passwdHash) {
+ this.passwdHash = passwdHash;
+ }
+
+ public boolean checkPasswd(String password) {
+ return PasswordHash.checkPasswd(getPasswdHash(), password);
+ }
+
+
+ public void setPasswd(PasswordHash alg, String passwd) {
+ this.passwdHash = alg.encrypt(passwd);
+ }
+
+ public String getWebId() {
+ return webId;
+ }
+
+ public void setWebId(String webId) {
+ this.webId = webId;
+ }
+
+
+ public Set<String> getRoles() {
+ return roles;
+ }
+
+ public void setRoles(Set<String> roles) {
+ this.roles = roles;
+ }
+
+ public void addRole(String role) {
+ this.roles.add(role);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ UserAccount that = (UserAccount) o;
+
+ if (login != null ? !login.equals(that.login) : that.login != null) return false;
+ if (webId != null ? !webId.equals(that.webId) : that.webId != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = login != null ? login.hashCode() : 0;
+ result = 31 * result + (webId != null ? webId.hashCode() : 0);
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/AccountServiceImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/AccountServiceImpl.java b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/AccountServiceImpl.java
new file mode 100644
index 0000000..752a33e
--- /dev/null
+++ b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/AccountServiceImpl.java
@@ -0,0 +1,292 @@
+/**
+ * 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.user.services;
+
+import org.apache.marmotta.platform.user.api.AccountService;
+import org.apache.marmotta.platform.user.model.UserAccount;
+import org.apache.marmotta.platform.user.model.UserAccount.PasswordHash;
+import com.google.common.base.Preconditions;
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.core.api.user.UserService;
+import org.apache.marmotta.platform.core.events.ConfigurationChangedEvent;
+import org.apache.marmotta.platform.core.events.SystemStartupEvent;
+import org.apache.marmotta.platform.core.exception.UserExistsException;
+import org.apache.marmotta.platform.core.model.user.KiWiUser;
+import org.apache.marmotta.platform.core.qualifiers.cache.LMFCache;
+import net.sf.ehcache.Ehcache;
+import net.sf.ehcache.Element;
+import org.apache.commons.lang.StringUtils;
+import org.apache.marmotta.commons.sesame.model.Namespaces;
+import org.apache.marmotta.kiwi.model.rdf.KiWiUriResource;
+import org.openrdf.model.Resource;
+import org.openrdf.model.URI;
+import org.slf4j.Logger;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@ApplicationScoped
+public class AccountServiceImpl implements AccountService {
+
+ @Inject
+ private Logger log;
+
+ @Inject
+ private ConfigurationService configurationService;
+
+ @Inject
+ private UserService userService;
+
+ @Inject
+ @LMFCache("user-cache")
+ private Ehcache userCache;
+
+ private PasswordHash hashAlgo;
+
+
+ public AccountServiceImpl() {
+ hashAlgo = PasswordHash.SHA1;
+ }
+
+ @PostConstruct
+ public void initialize() {
+ final String conf = configurationService.getStringConfiguration("security.password.hash", "SHA1").toUpperCase();
+ try {
+ hashAlgo = PasswordHash.valueOf(conf);
+ } catch (Exception e) {
+ hashAlgo = PasswordHash.SHA1;
+ log.warn("Invalid/unknown password hash algorithm: {}, falling back to {}", conf, hashAlgo);
+ }
+ }
+
+ public void systemStartup(@Observes SystemStartupEvent event) {
+ log.info("creating default system accounts ...");
+ createDefaultAccounts();
+ }
+
+ public void onConfigurationChange(@Observes ConfigurationChangedEvent event) {
+ if (event.containsChangedKey("security.password.hash")) {
+ initialize();
+ }
+ }
+
+ @Override
+ public void createDefaultAccounts() {
+ // Currently there is only one default account: admin
+ UserAccount account = getAccount(Namespaces.ADMIN_LOGIN);
+ if (account == null) {
+ Set<String> roles = new HashSet<String>(configurationService.getListConfiguration("user." + Namespaces.ADMIN_LOGIN + ".roles"));
+ account = createAccount(Namespaces.ADMIN_LOGIN);
+ account.setRoles(roles);
+ account.setPasswd(hashAlgo, configurationService.getStringConfiguration("user." + Namespaces.ADMIN_LOGIN + ".password"));
+ save(account);
+ }
+ }
+
+ @Override
+ public List<UserAccount> listAccounts() {
+ Set<String> logins = new HashSet<String>();
+ for(String key : configurationService.listConfigurationKeys("user")) {
+ String[] components = key.split("\\.");
+ if(components.length > 2 && "webid".equals(components[2])) {
+ logins.add(components[1]);
+ }
+ }
+
+ final List<UserAccount> list = new ArrayList<UserAccount>();
+ for(String login : logins) {
+ list.add(getAccount(login));
+ }
+
+
+ for (UserAccount userAccount : list) {
+ userCache.put(new Element(userAccount.getLogin(), userAccount));
+ userCache.put(new Element(userAccount.getWebId(), userAccount));
+ }
+ return list;
+ }
+
+ @Override
+ public List<UserAccount> listAccounts(String role) {
+ List<UserAccount> result = new ArrayList<UserAccount>();
+
+ for(UserAccount account : listAccounts()) {
+ if(account.getRoles().contains(role)) {
+ result.add(account);
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public UserAccount createAccount(String login) {
+ return createAccount(login, null, null);
+ }
+
+ @Override
+ public UserAccount createAccount(String login, String firstName, String lastName) {
+ Preconditions.checkArgument(StringUtils.isNotBlank(login), "blank/empty login not allowed");
+
+ URI webid = userService.getUser(login);
+ if (webid == null) {
+ try {
+ webid = userService.createUser(login, firstName, lastName);
+ } catch (UserExistsException e) {
+ log.warn("User {} exists. This should not happen as it was checked 3 lines before!", login);
+ webid = userService.getUser(login);
+ }
+ }
+
+ if(webid instanceof KiWiUriResource) {
+ UserAccount account = new UserAccount(login, webid.stringValue());
+
+ save(account);
+
+ return account;
+ } else {
+ log.error("could not create user account, the backend is not KiWi");
+
+ return null;
+ }
+ }
+
+ private void save(UserAccount account) {
+ configurationService.setConfiguration("user."+account.getLogin()+".pwhash", account.getPasswdHash());
+ configurationService.setConfiguration("user."+account.getLogin()+".webid", account.getWebId());
+ configurationService.setListConfiguration("user." + account.getLogin() + ".roles", new ArrayList<String>(account.getRoles()));
+ }
+
+ @Override
+ public void deleteAccount(UserAccount account) {
+ for(String key : configurationService.listConfigurationKeys("user."+account.getLogin())) {
+ configurationService.removeConfiguration(key);
+ }
+ userCache.remove(account.getLogin());
+ userCache.remove(account.getWebId());
+ }
+
+ @Override
+ public UserAccount getAccount(String login) {
+ if (StringUtils.isBlank(login)) return null;
+ UserAccount account = null;
+ if (userCache != null && userCache.get(login) != null) {
+ account = (UserAccount) userCache.get(login).getObjectValue();
+ } else {
+ if (configurationService.isConfigurationSet("user."+login+".webid")) {
+ account = new UserAccount();
+
+ account.setLogin(login);
+ account.setPasswdHash(configurationService.getStringConfiguration("user."+login+".pwhash"));
+ account.setRoles(new HashSet<String>(configurationService.getListConfiguration("user."+login+".roles")));
+ account.setWebId(configurationService.getStringConfiguration("user."+login+".webid"));
+
+ userCache.put(new Element(account.getLogin(), account));
+ userCache.put(new Element(account.getWebId(), account));
+ } else {
+ log.info("UserAccount {} not found", login);
+ }
+ }
+ return account;
+ }
+
+ @Override
+ public UserAccount getAccount(URI resource) {
+ Preconditions.checkArgument(resource != null);
+
+ UserAccount account = null;
+ if (userCache != null && userCache.get(resource) != null) {
+ account = (UserAccount) userCache.get(resource).getObjectValue();
+ } else {
+ for(UserAccount a : listAccounts()) {
+ if(a.getWebId().equals(resource.stringValue())) {
+ account = a;
+ break;
+ }
+ }
+ if (account != null) {
+ userCache.put(new Element(account.getLogin(), account));
+ userCache.put(new Element(account.getWebId(), account));
+ } else {
+ log.warn("UserAccount {} not found", resource);
+ }
+ }
+ return account;
+ }
+
+ @Override
+ public UserAccount getAccount(KiWiUser user) {
+ Resource delegate = user.getDelegate();
+ if (delegate instanceof URI)
+ return getAccount((URI) delegate);
+ return null;
+ }
+
+ @Override
+ public UserAccount setPassword(UserAccount account, String passwd) {
+ account.setPasswd(hashAlgo, passwd);
+ save(account);
+ return account;
+ }
+
+ @Override
+ public boolean checkPassword(UserAccount account, String passwd) {
+ return account != null && account.checkPasswd(passwd);
+ }
+
+ @Override
+ public boolean checkPassword(String login, String passwd) {
+ return getAccount(login) != null && getAccount(login).checkPasswd(passwd);
+ }
+
+ @Override
+ public void setRoles(UserAccount account, Set<String> roles) {
+ account.setRoles(new HashSet<String>(roles));
+ save(account);
+ }
+
+ @Override
+ public Set<String> getRoles(UserAccount account) {
+ return account.getRoles();
+ }
+
+ @Override
+ public void addRole(UserAccount account, String role) {
+ account.addRole(role);
+ save(account);
+ }
+
+ @Override
+ public void removeRole(UserAccount account, String role) {
+ Set<String> roles = account.getRoles();
+ roles.remove(role);
+ account.setRoles(roles);
+ save(account);
+ }
+
+ @Override
+ public boolean hasRole(UserAccount account, String role) {
+ return account.getRoles().contains(role);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/AuthenticationServiceImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/AuthenticationServiceImpl.java b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/AuthenticationServiceImpl.java
new file mode 100644
index 0000000..e456977
--- /dev/null
+++ b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/AuthenticationServiceImpl.java
@@ -0,0 +1,165 @@
+/**
+ * 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.user.services;
+
+import org.apache.marmotta.platform.user.api.AccountService;
+import org.apache.marmotta.platform.user.api.AuthenticationProvider;
+import org.apache.marmotta.platform.user.api.AuthenticationService;
+import org.apache.marmotta.platform.user.model.UserAccount;
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.core.events.ConfigurationChangedEvent;
+import org.apache.marmotta.platform.core.util.CdiUtils;
+import org.slf4j.Logger;
+
+import javax.annotation.PostConstruct;
+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.HashSet;
+import java.util.Set;
+
+/**
+ * A simple implementation of an authentication that stores plain-text passwords in the system configuration.
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+@ApplicationScoped
+public class AuthenticationServiceImpl implements AuthenticationService {
+
+ public static final String DEFAULT_AUTH_PROVIDER_NAMED = "lmf";
+
+ @Inject
+ private Logger log;
+
+ @Inject
+ private AccountService accountService;
+
+ @Inject
+ private ConfigurationService configurationService;
+
+ @Inject @Any
+ private Instance<AuthenticationProvider> providers;
+
+ private AuthenticationProvider authenticationProvider;
+
+ @PostConstruct
+ protected void initialize() {
+ log.debug("initializing AuthenticationService");
+
+ final String prov = configurationService.getStringConfiguration("user.auth.provider", DEFAULT_AUTH_PROVIDER_NAMED);
+
+ Instance<AuthenticationProvider> selected = CdiUtils.selectNamed(providers, prov);
+ if (selected.isAmbiguous()) {
+ authenticationProvider = selected.iterator().next();
+ log.error("multiple candidates for AuthenticationProvider '{}' found. Chose randomly!", prov);
+ } else if (selected.isUnsatisfied()) {
+ log.error("no candidate for AuthenticationProvider '{}' found, falling back to default", prov);
+ authenticationProvider = CdiUtils.selectNamed(providers, DEFAULT_AUTH_PROVIDER_NAMED).iterator().next();
+ } else {
+ authenticationProvider = selected.get();
+ }
+ }
+
+ protected void onConfigurationChange(@Observes ConfigurationChangedEvent event) {
+ if (event.containsChangedKey("user.auth.provider")) {
+ initialize();
+ }
+ }
+
+ @Override
+ public Set<String> listAuthProviderNames() {
+ HashSet<String> pNames = new HashSet<String>();
+ for (AuthenticationProvider p : providers) {
+ Named ann = p.getClass().getAnnotation(Named.class);
+ if (ann != null) {
+ pNames.add(ann.value());
+ }
+ }
+ return pNames;
+ }
+
+
+ /**
+ * Authenticate the user with the given login and password. Returns true on success, false if the user does not
+ * exist or the passwords do not match.
+ *
+ * @param login login of the user to authenticate
+ * @param password password of the user to authenticate
+ * @return true on success, false if the user does not exist or the passwords do not match.
+ */
+ @Override
+ public boolean authenticateUser(String login, String password) {
+ log.debug("AUTH {} with {}", login, authenticationProvider != null ? authenticationProvider.getClass().getSimpleName() : null);
+ return authenticationProvider.checkPassword(accountService.getAccount(login), password);
+ }
+
+
+ /**
+ * Change the password of the user with the given login to the given new password. The implementation may decide
+ * where to persist the password in a secure manner and whether to apply additional security like password hashing.
+ *
+ * @param login
+ * @param password
+ * @return
+ */
+ @Override
+ public void setUserPassword(String login, String password) {
+ final UserAccount a = accountService.getAccount(login);
+ authenticationProvider.updatePassword(a, password);
+ }
+
+ /**
+ * Return the roles that are assigned to the user (a list of strings that can be chosen by the administrator as
+ * needed).
+ *
+ * @param login login name of the user for whom to return the roles
+ * @return a list of strings with the role names currently assigned to the user
+ */
+ @Override
+ public Set<String> listUserRoles(String login) {
+ return accountService.getRoles(accountService.getAccount(login));
+ }
+
+
+ /**
+ * Add the role with the given name to the user with the given login.
+ *
+ * @param login the login name of the user with whom to associate roles
+ * @param role the role name to associate with the user
+ */
+ @Override
+ public void addUserRole(String login, String role) {
+ final UserAccount a = accountService.getAccount(login);
+ accountService.addRole(a, role);
+ }
+
+ /**
+ * Remove the role with the given name from the user with the given login.
+ *
+ * @param login the login name of the user from whom to remove the role
+ * @param role the role name to remove from the list of roles of the user
+ */
+ @Override
+ public void removeUserRole(String login, String role) {
+ final UserAccount a = accountService.getAccount(login);
+ accountService.removeRole(a, role);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/UserConfigurationServiceImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/UserConfigurationServiceImpl.java b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/UserConfigurationServiceImpl.java
new file mode 100644
index 0000000..c3f23de
--- /dev/null
+++ b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/UserConfigurationServiceImpl.java
@@ -0,0 +1,178 @@
+/**
+ * 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.user.services;
+
+import org.apache.marmotta.platform.user.api.UserConfigurationService;
+import org.apache.marmotta.platform.user.model.UserAccount;
+import com.google.common.base.Preconditions;
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+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 javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import java.io.File;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Add file description here!
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+@ApplicationScoped
+public class UserConfigurationServiceImpl implements UserConfigurationService {
+
+ @Inject
+ private Logger log;
+
+ @Inject
+ private ConfigurationService configurationService;
+
+ private HashMap<String, Configuration> userConfigurations;
+
+
+ @PostConstruct
+ public void initialise() {
+ userConfigurations = new HashMap<String, Configuration>();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see kiwi.api.config.ConfigurationService#isUserConfigurationSet(kiwi.model.user.UserAccount,
+ * java.lang.String)
+ */
+ @Override
+ public boolean isUserConfigurationSet(UserAccount user, String key) {
+ Preconditions.checkNotNull(user);
+ Preconditions.checkNotNull(key);
+
+ return getUserConfiguration(user).containsKey(key);
+ }
+
+ @Override
+ public String getUserConfiguration(UserAccount user, String key, String defaultValue) {
+ Preconditions.checkNotNull(user);
+ Preconditions.checkNotNull(key);
+
+ return getUserConfiguration(user).getString(key, defaultValue);
+ }
+
+ @Override
+ public String getUserConfiguration(UserAccount user, String key) {
+ Preconditions.checkNotNull(user);
+ Preconditions.checkNotNull(key);
+
+ return getUserConfiguration(user).getString(key);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * kiwi.api.config.ConfigurationService#getUserListConfiguration(kiwi.model.user.UserAccount,
+ * java.lang.String)
+ */
+ @Override
+ public List<Object> getUserListConfiguration(UserAccount user, String key) {
+ Preconditions.checkNotNull(user);
+ Preconditions.checkNotNull(key);
+
+ return getUserListConfiguration(user, key, Collections.emptyList());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * kiwi.api.config.ConfigurationService#getUserListConfiguration(kiwi.model.user.UserAccount,
+ * java.lang.String, java.util.List)
+ */
+ @Override
+ public List<Object> getUserListConfiguration(UserAccount user, String key, List<Object> defaultValue) {
+ Preconditions.checkNotNull(user);
+ Preconditions.checkNotNull(key);
+
+ return getUserConfiguration(user).getList(key, defaultValue);
+ }
+
+ @Override
+ public void removeUserConfiguration(UserAccount user, String key) {
+ Preconditions.checkNotNull(user);
+ Preconditions.checkNotNull(key);
+
+ getUserConfiguration(user).clearProperty(key);
+ }
+
+ @Override
+ public void setUserListConfiguration(UserAccount user, String key, List<String> values) {
+ Preconditions.checkNotNull(user);
+ Preconditions.checkNotNull(key);
+
+ getUserConfiguration(user).setProperty(key, values);
+ }
+
+ @Override
+ public void setUserConfiguration(UserAccount user, String key, String value) {
+ Preconditions.checkNotNull(user);
+ Preconditions.checkNotNull(key);
+
+ getUserConfiguration(user).setProperty(key, value);
+ }
+
+
+ public Configuration getUserConfiguration(UserAccount user) {
+ Configuration userConfig = userConfigurations.get(user.getLogin());
+ if (userConfig == null) {
+
+ String userConfigFile = configurationService.getConfiguration("kiwi.work.dir") + File.separator + "config" + File.separator + user.getLogin() + ".conf";
+
+ try {
+ File f = new File(userConfigFile);
+ if (f.exists()) {
+ f.createNewFile();
+ }
+ userConfig = new PropertiesConfiguration(f);
+ } catch (Exception ex) {
+ log.error("could not create user configuration in file #0: #1", userConfigFile, ex.getMessage());
+ userConfig = new MapConfiguration(new HashMap<String, Object>());
+ }
+ userConfigurations.put(user.getLogin(), userConfig);
+ }
+ return userConfig;
+ }
+
+
+ public void save(UserAccount user) {
+ Configuration userConfig = getUserConfiguration(user);
+
+ if (userConfig instanceof PropertiesConfiguration) {
+ try {
+ ((PropertiesConfiguration) userConfig).save();
+ } catch (ConfigurationException e) {
+ log.error("could not save user configuration for user #0: #1", user.getLogin(), e.getMessage());
+ }
+ }
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/auth/LMFAuthProviderImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/auth/LMFAuthProviderImpl.java b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/auth/LMFAuthProviderImpl.java
new file mode 100644
index 0000000..8389e55
--- /dev/null
+++ b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/auth/LMFAuthProviderImpl.java
@@ -0,0 +1,47 @@
+/**
+ * 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.user.services.auth;
+
+import org.apache.marmotta.platform.user.api.AccountService;
+import org.apache.marmotta.platform.user.api.AuthenticationProvider;
+import org.apache.marmotta.platform.user.model.UserAccount;
+import org.apache.marmotta.platform.user.services.AuthenticationServiceImpl;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Default;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+@ApplicationScoped
+@Named(AuthenticationServiceImpl.DEFAULT_AUTH_PROVIDER_NAMED)
+@Default
+public class LMFAuthProviderImpl implements AuthenticationProvider {
+
+ @Inject
+ private AccountService accountService;
+
+ @Override
+ public boolean checkPassword(UserAccount login, String passwd) {
+ return accountService.checkPassword(login, passwd);
+ }
+
+ @Override
+ public boolean updatePassword(UserAccount login, String newPasswd) {
+ accountService.setPassword(login, newPasswd);
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/auth/LdapAuthProvider.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/auth/LdapAuthProvider.java b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/auth/LdapAuthProvider.java
new file mode 100644
index 0000000..720e691
--- /dev/null
+++ b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/services/auth/LdapAuthProvider.java
@@ -0,0 +1,132 @@
+/**
+ * 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.user.services.auth;
+
+import org.apache.marmotta.platform.user.api.AuthenticationProvider;
+import org.apache.marmotta.platform.user.model.UserAccount;
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.slf4j.Logger;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.naming.Context;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import javax.naming.directory.ModificationItem;
+import java.util.Hashtable;
+import java.util.regex.Pattern;
+
+/**
+ * Authenticate LMF-Users against LDAP.
+ *
+ * TODO: maybe switch to jldap (compile 'com.novell.ldap:jldap:4.3') which might also allow password
+ * change.
+ * TODO: password-update is currently not implemented.
+ *
+ * <h3>Configuration Settings</h3>
+ * <dl>
+ * <dt>user.auth.ldap.server
+ * <dd>hostname/IP of the ldap-server (default: <b>localhost</b>)
+ * <dt>user.auth.ldap.port
+ * <dd>ldap server port (default: <b>389</b>)
+ * <dt>user.auth.ldap.dn
+ * <dd>Pattern to build the DN for auth. <code>{login}</code> will be replaced by the account
+ * name/login (default: <b>{login}</b>)
+ * </dl>
+ *
+ * @author Jakob Frank <ja...@salzburgresearch.at>
+ * @author Daniel Trabe <da...@salzburgresearch.at>
+ *
+ */
+@ApplicationScoped
+@Named(LdapAuthProvider.QUALIFIER)
+public class LdapAuthProvider implements AuthenticationProvider {
+
+ static final String QUALIFIER = "ldap";
+ static final String CONF_SERVER = "user.auth." + QUALIFIER + ".server";
+ static final String CONF_PORT = "user.auth." + QUALIFIER + ".port";
+ static final String CONF_DN = "user.auth." + QUALIFIER + ".dn";
+
+
+ @Inject
+ private ConfigurationService configurationService;
+
+ @Inject
+ private Logger log;
+
+ @Override
+ public boolean checkPassword(UserAccount login, String passwd) {
+ return login != null && login(login.getLogin(), passwd);
+ }
+
+ @Override
+ public boolean updatePassword(UserAccount login, String newPasswd) {
+ if (login == null) return false;
+ String username = login.getLogin();
+ log.trace("changePassword called for account: {}", username);
+
+ ModificationItem[] mod = new ModificationItem[1];
+ Attribute attr = new BasicAttribute("userpassword", newPasswd);
+ mod[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr);
+
+ final String dn = configurationService.getStringConfiguration(CONF_DN, "{login}")
+ .replaceAll(Pattern.quote("{login}"), username);
+ try {
+ // ctx.modifyAttributes(dn, mod);
+ // log.info("LDAP-Passwd update for {} successful ({})", username, dn);
+ // return true;
+ } catch (Exception e) {
+ log.info("LDAP-Passwd update for {} failed ({})", username, dn);
+ }
+ log.warn("LDAP-Passwd update not implemented");
+ return false;
+ }
+
+ private boolean login(String login, String secret) {
+ try {
+ // Set up the environment for creating the initial context
+ Hashtable<String, String> env = new Hashtable<String, String>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+ env.put(Context.PROVIDER_URL, String.format("ldap://%s:%d",
+ configurationService.getStringConfiguration(CONF_SERVER, configurationService.getServerName()),
+ configurationService.getIntConfiguration(CONF_PORT, 389)));
+
+ env.put(Context.SECURITY_AUTHENTICATION, "simple");
+ env.put(Context.SECURITY_PRINCIPAL, configurationService.getStringConfiguration(CONF_DN, "{login}")
+ .replaceAll(Pattern.quote("{login}"), login));
+ env.put(Context.SECURITY_CREDENTIALS, secret);
+
+ // Create the initial context
+ DirContext ctx = new InitialDirContext(env);
+ // If retrieving the context worked, login was successful.
+ boolean result = ctx != null;
+
+ if (ctx != null) {
+ ctx.close();
+ }
+
+ log.trace("LDAP-Login successful for {}", login);
+ return result;
+ } catch (Exception e) {
+ log.info("LDAP-Login for {} failed: {}", login, e.getMessage());
+ return false;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/webservices/UserManagementWebService.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/webservices/UserManagementWebService.java b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/webservices/UserManagementWebService.java
new file mode 100644
index 0000000..07f140f
--- /dev/null
+++ b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/webservices/UserManagementWebService.java
@@ -0,0 +1,316 @@
+/**
+ * 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.user.webservices;
+
+import org.apache.marmotta.platform.user.api.AccountService;
+import org.apache.marmotta.platform.user.model.UserAccount;
+import org.apache.marmotta.commons.sesame.model.Namespaces;
+import org.apache.marmotta.commons.sesame.repository.ResourceUtils;
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.core.api.triplestore.SesameService;
+import org.apache.commons.lang.StringUtils;
+import org.openrdf.model.Literal;
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.model.Value;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.RepositoryResult;
+import org.slf4j.Logger;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@Path("/users")
+public class UserManagementWebService {
+ private static final Pattern PROFILE_URI_PATTERN = Pattern.compile("^<([^>]+)>$");
+
+ @Inject
+ private Logger log;
+
+ @Inject
+ private AccountService accountService;
+
+ @Inject
+ private ConfigurationService configurationService;
+
+ @Inject
+ private SesameService sesameService;
+
+ private List<String> acceptedFoafProperties;
+
+ private static final List<String> RESERVED_LOGINS = Arrays.asList("me", "login", "anonymous");
+
+ @PostConstruct
+ public void initialize() {
+ acceptedFoafProperties = configurationService.getListConfiguration("user.account.foaf.properties",
+ Arrays.asList("firstName", "nick", "lastName", "familyName", "givenName", "name", "title", "age", "mbox", "homepage"));
+ }
+
+ /**
+ * List users (that have the given role).
+ *
+ * @param role the required role (optional)
+ * @return an array of {@link org.apache.marmotta.platform.user.webservices.UserWebService.AccountPoJo}s containing users (that have the required role, if
+ * role was given) (in JSON).
+ */
+ @GET
+ @Produces(Namespaces.MIME_TYPE_JSON)
+ public Response listUsers(@QueryParam("role") String role) {
+ final List<UserAccount> accounts;
+ if (role == null) {
+ accounts = accountService.listAccounts();
+ } else {
+ accounts = accountService.listAccounts(role);
+ }
+
+ final List<UserWebService.AccountPoJo> resp = new ArrayList<UserWebService.AccountPoJo>();
+ for (UserAccount userAccount : accounts) {
+ UserWebService.AccountPoJo apj = new UserWebService.AccountPoJo(userAccount.getLogin(), userAccount.getWebId());
+ apj.setRoles(userAccount.getRoles());
+ resp.add(apj);
+ }
+
+ return Response.ok(resp, Namespaces.MIME_TYPE_JSON).build();
+ }
+
+ /**
+ * Create a new user account (incl. user resource)
+ *
+ * @param login the account name / login name of the new user.
+ * @return the {@link org.apache.marmotta.platform.user.webservices.UserWebService.AccountPoJo} of the newly created user.
+ * @HTTP 409 if an account with the given login already exists
+ * @HTTP 400 if the login is a reserved keyword: [me, login, anonymous]
+ * @HTTP 500 on other errors.
+ */
+ @POST
+ @Path("/{login}")
+ public Response createUser(@PathParam("login") String login) {
+ if (accountService.getAccount(login) != null)
+ return Response.status(Status.CONFLICT).entity(String.format("'%s' already exists!", login)).build();
+
+ if (StringUtils.isBlank(login)) return Response.status(Status.BAD_REQUEST).entity("Provide a username").build();
+
+ // Must not create an account with a reserved username!
+ if (RESERVED_LOGINS.contains(login))
+ return Response.status(Status.BAD_REQUEST).entity(String.format("The following usernames are not allowed: %s", RESERVED_LOGINS)).build();
+
+ UserAccount a = accountService.createAccount(login);
+ if (a != null)
+ return getUser(login);
+
+ log.error("Creating an account for {} failed", login);
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Sorry, don't know why").build();
+ }
+
+ /**
+ * Return the Account data of the requested login
+ *
+ * @param login the account requested
+ * @return an {@link org.apache.marmotta.platform.user.webservices.UserWebService.AccountPoJo} of the requested account
+ * @HTTP 404 if no such user exists.
+ */
+ @GET
+ @Path("/{login}")
+ @Produces(Namespaces.MIME_TYPE_JSON)
+ public Response getUser(@PathParam("login") String login) {
+ UserAccount account = accountService.getAccount(login);
+ if (account == null) return Response.status(Status.NOT_FOUND).entity(String.format("No login for '%s' found!", login)).build();
+
+ try {
+ RepositoryConnection conn = sesameService.getConnection();
+ try {
+ UserWebService.AccountPoJo apj = new UserWebService.AccountPoJo(account.getLogin(), account.getWebId());
+ apj.setRoles(account.getRoles());
+
+ RepositoryResult<Statement> triples = conn.getStatements(conn.getValueFactory().createURI(account.getWebId()),null,null,true);
+
+ while(triples.hasNext()) {
+ Statement t = triples.next();
+
+ String prop = t.getPredicate().stringValue();
+ if (prop.startsWith(Namespaces.NS_FOAF)) {
+ Value object = t.getObject();
+ if (object instanceof URI) {
+ apj.setFoaf(prop, String.format("<%s>", object));
+ } else if (object instanceof Literal) {
+ apj.setFoaf(prop, object.toString());
+ }
+ }
+ }
+
+ return Response.ok(apj, Namespaces.MIME_TYPE_JSON).build();
+ } finally {
+ conn.commit();
+ conn.close();
+ }
+ } catch(RepositoryException ex) {
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity(ex.getMessage()).build();
+ }
+ }
+
+ /**
+ * Delete the account with the given login.
+ *
+ * @param login the account to delete
+ * @param delFoaf if <code>true</code>, also delete the user profile (foaf)
+ * @return 200 ok on success
+ * @HTTP 404 if no such user exists
+ */
+ @DELETE
+ @Path("/{login}")
+ public Response deleteUser(@PathParam("login") String login, @QueryParam("deleteFoaf") @DefaultValue("false") boolean delFoaf) {
+ UserAccount account = accountService.getAccount(login);
+ if (account == null) return Response.status(Status.NOT_FOUND).entity(String.format("No login for '%s' found!", login)).build();
+
+ try {
+ RepositoryConnection conn = sesameService.getConnection();
+ try {
+ if (delFoaf && account.getWebId() != null) {
+ // TODO: Remove only users foaf profile?
+ conn.remove(conn.getValueFactory().createURI(account.getWebId()),null,null);
+ }
+
+ accountService.deleteAccount(account);
+ return Response.status(Status.OK).entity(String.format("login removed")).build();
+ } finally {
+ conn.commit();
+ conn.close();
+ }
+ } catch(RepositoryException ex) {
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity(ex.getMessage()).build();
+ }
+ }
+
+ /**
+ * Set the roles for the given account
+ *
+ * @param login the account
+ * @param roles <code>role</code> params of the roles to set
+ * @param roles2 <code>role[]</code> params of the roles to set
+ * @return the {@link org.apache.marmotta.platform.user.webservices.UserWebService.AccountPoJo} of the account after update
+ * @HTTP 404 if no such account exists.
+ */
+ @POST
+ @Path("/{login}/roles")
+ public Response setUserRoles(@PathParam("login") String login, @QueryParam("role") String[] roles, @QueryParam("role[]") String[] roles2) {
+ UserAccount account = accountService.getAccount(login);
+ if (account == null) return Response.status(Status.NOT_FOUND).entity(String.format("No login for '%s' found!", login)).build();
+
+ HashSet<String> roleSet = new HashSet<String>();
+ for (String role : roles) {
+ roleSet.add(role);
+ }
+ for (String role : roles2) {
+ roleSet.add(role);
+ }
+ accountService.setRoles(account, roleSet);
+
+ return getUser(login);
+ }
+
+ /**
+ * Set the password for the given account
+ *
+ * @param login the account to set the password for
+ * @param passwd the new password
+ * @return 200 OK on success
+ * @HTTP 404 if no such account exists
+ */
+ @POST
+ @Path("/{login}/password")
+ public Response setUserPassword(@PathParam("login") String login, @FormParam("password") String passwd) {
+ UserAccount account = accountService.getAccount(login);
+ if (account == null) return Response.status(Status.NOT_FOUND).entity(String.format("No login for '%s' found!", login)).build();
+
+ accountService.setPassword(account, passwd);
+
+ return Response.ok("Password updated").build();
+ }
+
+ /**
+ * Update/Save the user profile (foaf) for the given account
+ *
+ * @param login the user to modify
+ * @param formParams the user profile (foaf, without prefix) in
+ * {@value at.newmedialab.sesame.commons.model.Namespaces#MIME_TYPE_FORM_URLENC}
+ * @return {@link org.apache.marmotta.platform.user.webservices.UserWebService.AccountPoJo} after the update in JSON
+ * @see UserWebService#post(MultivaluedMap)
+ * @HTTP 404 if no such user exists.
+ */
+ @POST
+ @Path("/{login}/profile")
+ public Response setUserProfile(@PathParam("login") String login, MultivaluedMap<String, String> formParams) {
+ UserAccount account = accountService.getAccount(login);
+ if (account == null) return Response.status(Status.NOT_FOUND).entity(String.format("No login for '%s' found!", login)).build();
+
+ try {
+ RepositoryConnection conn = sesameService.getConnection();
+
+ try {
+ String currentUser = account.getWebId();
+ for (String prop : formParams.keySet()) {
+ if (!acceptedFoafProperties.contains(prop)) {
+ continue;
+ }
+
+ String property = Namespaces.NS_FOAF + prop;
+ URI p = conn.getValueFactory().createURI(property);
+ URI u = conn.getValueFactory().createURI(currentUser);
+ ResourceUtils.removeProperty(conn,u, property);
+ String val = formParams.getFirst(prop);
+ if (val != null && val.length() > 0) {
+ Matcher m = PROFILE_URI_PATTERN.matcher(val);
+ if (m.matches()) {
+ URI o = conn.getValueFactory().createURI(m.group(1));
+ conn.add(u,p,o,u);
+ } else {
+ Literal o = conn.getValueFactory().createLiteral(val.trim());
+ conn.add(u,p,o,u);
+ }
+ }
+ }
+ } finally {
+ conn.commit();
+ conn.close();
+ }
+ } catch (RepositoryException e) {
+ // This must not happen!
+ return Response.serverError().entity(e).build();
+ }
+
+ return getUser(login);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/webservices/UserWebService.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/webservices/UserWebService.java b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/webservices/UserWebService.java
new file mode 100644
index 0000000..96c5b1b
--- /dev/null
+++ b/platform/marmotta-user/src/main/java/org/apache/marmotta/platform/user/webservices/UserWebService.java
@@ -0,0 +1,346 @@
+/**
+ * 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.user.webservices;
+
+import org.apache.marmotta.platform.user.api.AccountService;
+import org.apache.marmotta.platform.user.model.UserAccount;
+import org.apache.marmotta.commons.sesame.model.Namespaces;
+import org.apache.marmotta.commons.sesame.repository.ResourceUtils;
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.core.api.triplestore.SesameService;
+import org.apache.marmotta.platform.core.api.user.UserService;
+import org.apache.marmotta.platform.core.exception.security.AccessDeniedException;
+import org.openrdf.model.Literal;
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.model.Value;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.ws.rs.*;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import java.io.UnsupportedEncodingException;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * User-Account related webservices, accessable by every user (each for his/her own data)
+ *
+ * @author Jakob Frank <ja...@salzburgresearch.at>
+ *
+ */
+@Path("/user")
+public class UserWebService {
+
+ private static final Pattern PROFILE_URI_PATTERN = Pattern.compile("^<([^>]+)>$");
+
+ @Inject
+ private ConfigurationService configurationService;
+
+ @Inject
+ private UserService userService;
+
+ @Inject
+ private AccountService accountService;
+
+ @Inject
+ private SesameService sesameService;
+
+ private List<String> acceptedFoafProperties;
+
+ @PostConstruct
+ public void initialize() {
+ acceptedFoafProperties = configurationService.getListConfiguration("user.account.foaf.properties",
+ Arrays.asList("firstName", "nick", "lastName", "familyName", "givenName", "name", "title", "age", "mbox", "homepage"));
+ }
+
+ /**
+ * Provide Account information about the currently logged in user (account)
+ *
+ * @return {@link AccountPoJo} of the current user in JSON
+ * @see AccountPoJo
+ */
+ @GET
+ @Path("/me")
+ @Produces(Namespaces.MIME_TYPE_JSON)
+ public Response get() {
+ return get(userService.getCurrentUser());
+ }
+
+ private Response get(URI user) {
+ if (userService.isAnonymous(user)) {
+ AccountPoJo apj = new AccountPoJo(Namespaces.ANONYMOUS_LOGIN, user.stringValue());
+ return Response.ok(apj, Namespaces.MIME_TYPE_JSON).location(java.net.URI.create(user.stringValue())).build();
+ }
+ try {
+ RepositoryConnection conn = sesameService.getConnection();
+ try {
+ final UserAccount a = accountService.getAccount(user);
+ if (a != null) {
+ AccountPoJo apj = new AccountPoJo(a.getLogin(), a.getWebId());
+ apj.setRoles(a.getRoles());
+
+ for (Statement t : ResourceUtils.listOutgoing(conn,conn.getValueFactory().createURI(a.getWebId()))) {
+ String prop = t.getPredicate().stringValue();
+ if (prop.startsWith(Namespaces.NS_FOAF)) {
+ Value object = t.getObject();
+ if (object instanceof org.openrdf.model.URI) {
+ apj.setFoaf(prop, String.format("<%s>", object));
+ } else if (object instanceof Literal) {
+ apj.setFoaf(prop, object.toString());
+ }
+ }
+ }
+
+ return Response.ok(apj, Namespaces.MIME_TYPE_JSON).location(java.net.URI.create(user.stringValue())).build();
+ }
+ return Response.status(Status.NOT_FOUND).entity("Could not find account data of " + user).build();
+ } finally {
+ conn.commit();
+ conn.close();
+ }
+ } catch (RepositoryException e) {
+ // This must not happen!
+ return Response.serverError().entity(e).build();
+ }
+
+ }
+
+ /**
+ * Update/Set the profile information (foaf) for the current user.
+ * Post-Body should contain the property=value mapping (propterty without foaf-prefix) for the
+ * profile.
+ *
+ * @param formParams the user profile (foaf, without prefix) in
+ * {@value at.newmedialab.sesame.commons.model.Namespaces#MIME_TYPE_FORM_URLENC}
+ * @return {@link AccountPoJo} after the update in JSON
+ *
+ * @HTTP 403 When the current user is <code>anonymous</code>.
+ * @HTTP 500 If a {@link RepositoryException} occurs (which should not happen as no
+ * namespaces are used here)
+ */
+ @POST
+ @Path("/me")
+ @Consumes(Namespaces.MIME_TYPE_FORM_URLENC)
+ public Response post(MultivaluedMap<String, String> formParams) {
+ final URI currentUser = userService.getCurrentUser();
+ if (userService.isAnonymous(currentUser)) return Response.status(Status.FORBIDDEN).entity("anonymous is read-only").build();
+
+ try {
+ RepositoryConnection conn = sesameService.getConnection();
+
+ try {
+ for (String prop : formParams.keySet()) {
+ if (!acceptedFoafProperties.contains(prop)) {
+ continue;
+ }
+ URI p = conn.getValueFactory().createURI(Namespaces.NS_FOAF + prop);
+
+ conn.remove(currentUser,p,null);
+
+ String val = formParams.getFirst(prop);
+ if (val != null && val.length() > 0) {
+ Matcher m = PROFILE_URI_PATTERN.matcher(val);
+ if (m.matches()) {
+ URI o = conn.getValueFactory().createURI(m.group(1));
+ conn.add(currentUser, p, o, currentUser);
+ } else {
+ Literal o = conn.getValueFactory().createLiteral(val.trim());
+ conn.add(currentUser, p, o, currentUser);
+ }
+ }
+
+ }
+ return get(currentUser);
+ } finally {
+ conn.commit();
+ conn.close();
+ }
+ } catch (RepositoryException e) {
+ // This must not happen!
+ return Response.serverError().entity(e).build();
+ }
+ }
+
+ /**
+ * Dummy to avoid exceptions if post body is empty.
+ *
+ * @see #post(MultivaluedMap)
+ * @return {@link AccountPoJo} of the current user in JSON
+ */
+ @POST
+ @Path("/me")
+ public Response post() {
+ return get();
+ }
+
+ /**
+ * Update/change the password for the current user.
+ *
+ * @param oldPwd the old (current) password.
+ * @param newPwd the new password
+ * @return 200 OK on success
+ * @HTTP 404 if the current account could not be loaded
+ * @HTTP 403 if the old pasword did not match
+ */
+ @POST
+ @Path("/me/passwd")
+ public Response passwd(@FormParam("oldPasswd") String oldPwd, @FormParam("newPasswd") String newPwd) {
+ final org.openrdf.model.URI currentUser = userService.getCurrentUser();
+ final UserAccount a = accountService.getAccount(currentUser);
+
+ if (a == null) return Response.status(Status.NOT_FOUND).entity(String.format("No account found for <%s>", currentUser)).build();
+
+ if (accountService.checkPassword(a, oldPwd)) {
+ accountService.setPassword(a, newPwd);
+ return Response.ok("Password changed").build();
+ } else
+ return Response.status(Status.FORBIDDEN).entity("password check failed").build();
+ }
+
+ /**
+ * Resolve/Redirect access to /user/* uris.
+ *
+ * @param login the login of the user to redirect to
+ * @param types header param of accepted mime-types
+ * @return a redirect to the user-resource in the resource service.
+ * @HTTP 404 if no such user exists.
+ * @HTTP 303 on success
+ * @HTTP 400 if no valid resource uri could be built with the login
+ * @HTTP 500 on other exceptions
+ */
+ @GET
+ @Path("/{login:[^#?]+}")
+ public Response getUser(@PathParam("login") String login, @HeaderParam("Accept") String types) {
+ try {
+ RepositoryConnection conn = sesameService.getConnection();
+ try {
+ final URI user = userService.getUser(login);
+ if (user == null) return Response.status(Status.NOT_FOUND).entity(String.format("User %s not found", login)).build();
+
+ java.net.URI u = new java.net.URI(configurationService.getServerUri() + "resource?uri=" + URLEncoder.encode(user.stringValue(), "utf-8"));
+
+ return Response.seeOther(u).header("Accept", types).build();
+ } finally {
+ conn.commit();
+ conn.commit();
+ }
+ } catch (URISyntaxException e) {
+ return Response.status(Status.BAD_REQUEST).entity(String.format("Invalid URI: %s", e.getMessage())).build();
+ } catch (UnsupportedEncodingException e) {
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ } catch (RepositoryException e) {
+ return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ }
+ }
+
+ /**
+ * Throws a {@link AccessDeniedException} if currently no user is logged in (aka: current user
+ * is anonymous).
+ *
+ * @param ref the referer to redirect to
+ * @param logout set to true to log out (does currently nothing)
+ * @return a redirect to the referer url
+ * @throws AccessDeniedException if currently no user is logged in.
+ * @HTTP 303 if the user is already logged in (or <code>logout == true</code>)
+ */
+ @GET
+ @Path("/login")
+ public Response login(@HeaderParam("Referer") String ref, @QueryParam("logout") @DefaultValue("false") boolean logout,
+ @QueryParam("user") String login) {
+ // Check whether we want to logout
+ if (logout) {
+ userService.setCurrentUser(userService.getAnonymousUser());
+ throw new AccessDeniedException();
+ }
+
+ // Anonymous cannot login
+ if (userService.isAnonymous(userService.getCurrentUser())) throw new AccessDeniedException();
+
+ // Check whether this is the right (desired) user
+ if (login != null && !userService.getCurrentUser().equals(userService.getUser(login))) throw new AccessDeniedException();
+
+ if (ref == null || "".equals(ref)) {
+ ref = configurationService.getServerUri() + configurationService.getStringConfiguration("kiwi.pages.startup");
+ }
+ return Response.seeOther(java.net.URI.create(ref)).build();
+ }
+
+ /**
+ * Wrapped AccountInformation for serialisation.
+ *
+ * @author Jakob Frank <ja...@salzburgresearch.at>
+ *
+ */
+ static class AccountPoJo {
+ private String login, uri, roles[];
+ private Map<String, String> foaf;
+
+ public AccountPoJo(String login, String uri) {
+ this.login = login;
+ if (uri != null) {
+ this.uri = uri;
+ } else {
+ this.uri = null;
+ }
+ this.roles = new String[0];
+ this.foaf = new HashMap<String, String>();
+ }
+
+ public void setRoles(Set<String> roles) {
+ if (roles != null) {
+ this.roles = roles.toArray(new String[roles.size()]);
+ } else {
+ this.roles = new String[0];
+ }
+ }
+
+ public void setFoaf(String prop, String value) {
+ foaf.put(prop, value);
+ }
+
+ public void setFoaf(Map<String, String> foaf) {
+ this.foaf = foaf;
+ }
+
+ public String getLogin() {
+ return login;
+ }
+
+ public String getUri() {
+ return uri;
+ }
+
+ public String[] getRoles() {
+ return roles;
+ }
+
+ public Map<String, String> getFoaf() {
+ return foaf;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-user/src/main/resources/kiwi-module.properties
----------------------------------------------------------------------
diff --git a/platform/marmotta-user/src/main/resources/kiwi-module.properties b/platform/marmotta-user/src/main/resources/kiwi-module.properties
index c8841d3..ab0a784 100644
--- a/platform/marmotta-user/src/main/resources/kiwi-module.properties
+++ b/platform/marmotta-user/src/main/resources/kiwi-module.properties
@@ -22,12 +22,10 @@ subtitle = Profile and Account Management
icon_small = /admin/img/user_small.png
-webservices=at.newmedialab.lmf.user.webservices.UserWebService,\
- at.newmedialab.lmf.user.webservices.UserManagementWebService
+webservices=org.apache.marmotta.platform.user.webservices.UserWebService,\
+ org.apache.marmotta.platform.user.webservices.UserManagementWebService
-entities=at.newmedialab.lmf.user.model.UserAccount
-
adminpages=/me.html,\
/admin/users.html
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-versioning/src/main/java/at/newmedialab/lmf/versioning/api/MementoService.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/at/newmedialab/lmf/versioning/api/MementoService.java b/platform/marmotta-versioning/src/main/java/at/newmedialab/lmf/versioning/api/MementoService.java
deleted file mode 100644
index 1724518..0000000
--- a/platform/marmotta-versioning/src/main/java/at/newmedialab/lmf/versioning/api/MementoService.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * 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 at.newmedialab.lmf.versioning.api;
-
-import at.newmedialab.lmf.versioning.exception.MementoException;
-import at.newmedialab.lmf.versioning.model.MementoVersionSet;
-import org.apache.marmotta.kiwi.versioning.model.Version;
-import org.openrdf.model.Resource;
-import java.util.Date;
-
-/**
- * ...
- * <p/>
- * Author: Thomas Kurz (tkurz@apache.org)
- */
-public interface MementoService {
-
- //public Version getNextVersion(Resource resource, Version version) throws MementoException;
-
- //public Version getPreviousVersion(Resource resource, Version version) throws MementoException;
-
- /**
- * returns the version for a resource that was current on the given date
- * @param resource a uri resource
- * @param date a date
- * @return the version with respect to the date
- * @throws MementoException
- */
- public Version getVersion(Resource resource, Date date) throws MementoException;
-
- //public Version getLastVersion(Resource resource) throws MementoException;
- //public Version getFirstVersion(Resource resource) throws MementoException;
-
- /**
- * returns a memento version set that includes first, last, current, prev and next version with respect
- * to a given date and resource
- * @param resource a requested resource
- * @param date a requested date
- * @return a memento version set
- * @throws MementoException
- * @see MementoVersionSet
- */
- public MementoVersionSet getVersionSet(Resource resource, Date date) throws MementoException;
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-versioning/src/main/java/at/newmedialab/lmf/versioning/api/VersionSerializerService.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/at/newmedialab/lmf/versioning/api/VersionSerializerService.java b/platform/marmotta-versioning/src/main/java/at/newmedialab/lmf/versioning/api/VersionSerializerService.java
deleted file mode 100644
index a16446a..0000000
--- a/platform/marmotta-versioning/src/main/java/at/newmedialab/lmf/versioning/api/VersionSerializerService.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * 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 at.newmedialab.lmf.versioning.api;
-
-import at.newmedialab.lmf.versioning.io.VersionSerializer;
-import org.apache.marmotta.commons.http.ContentType;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * Manages serialisation writers for Version objects
- * <p/>
- * Author: Thomas Kurz (tkurz@apache.org)
- */
-public interface VersionSerializerService {
-
- /**
- * returns a serializer for Version objects on a given ContentType
- * @param type a list of mimetype (from Accept header)
- * @return a serializer
- */
- public VersionSerializer getSerializer(List<ContentType> type) throws IOException;
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-versioning/src/main/java/at/newmedialab/lmf/versioning/exception/MementoException.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/at/newmedialab/lmf/versioning/exception/MementoException.java b/platform/marmotta-versioning/src/main/java/at/newmedialab/lmf/versioning/exception/MementoException.java
deleted file mode 100644
index b0307e5..0000000
--- a/platform/marmotta-versioning/src/main/java/at/newmedialab/lmf/versioning/exception/MementoException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * 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 at.newmedialab.lmf.versioning.exception;
-
-/**
- * Exception is thrown if something went wrong in memento versioning
- * <p/>
- * Author: Thomas Kurz (tkurz@apache.org)
- */
-public class MementoException extends Exception {
-
- public MementoException() {}
-
- public MementoException(String m) {
- super(m);
- }
-
- public MementoException(Throwable t) {
- super(t);
- }
-
-}