http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/StrippedDownAuthProvider.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/StrippedDownAuthProvider.java b/server-webapp/src/main/java/org/taverna/server/master/identity/StrippedDownAuthProvider.java deleted file mode 100644 index 06202dc..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/identity/StrippedDownAuthProvider.java +++ /dev/null @@ -1,278 +0,0 @@ -package org.taverna.server.master.identity; - -import java.util.HashMap; -import java.util.Map; - -import javax.annotation.PreDestroy; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.annotation.Required; -import org.springframework.security.authentication.AccountExpiredException; -import org.springframework.security.authentication.AuthenticationProvider; -import org.springframework.security.authentication.AuthenticationServiceException; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.authentication.CredentialsExpiredException; -import org.springframework.security.authentication.DisabledException; -import org.springframework.security.authentication.LockedException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.taverna.server.master.utils.CallTimeLogger.PerfLogged; - -/** - * A stripped down version of a - * {@link org.springframework.security.authentication.dao.DaoAuthenticationProvider - * DaoAuthenticationProvider}/ - * {@link org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider - * AbstractUserDetailsAuthenticationProvider} that avoids much of the overhead - * associated with that class. - */ -public class StrippedDownAuthProvider implements AuthenticationProvider { - /** - * The plaintext password used to perform - * {@link PasswordEncoder#isPasswordValid(String, String, Object)} on when - * the user is not found to avoid SEC-2056. - */ - private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword"; - - /** - * The password used to perform - * {@link PasswordEncoder#isPasswordValid(String, String, Object)} on when - * the user is not found to avoid SEC-2056. This is necessary, because some - * {@link PasswordEncoder} implementations will short circuit if the - * password is not in a valid format. - */ - private String userNotFoundEncodedPassword; - private UserDetailsService userDetailsService; - private PasswordEncoder passwordEncoder; - private Map<String, AuthCacheEntry> authCache = new HashMap<>(); - protected final Log logger = LogFactory.getLog(getClass()); - - private static class AuthCacheEntry { - private String creds; - private long timestamp; - private static final long VALIDITY = 1000 * 60 * 20; - AuthCacheEntry(String credentials) { - creds = credentials; - timestamp = System.currentTimeMillis(); - } - boolean valid(String password) { - return creds.equals(password) && timestamp+VALIDITY > System.currentTimeMillis(); - } - } - - @PerfLogged - @Override - public Authentication authenticate(Authentication authentication) - throws AuthenticationException { - - if (!(authentication instanceof UsernamePasswordAuthenticationToken)) - throw new IllegalArgumentException( - "can only authenticate against username+password"); - UsernamePasswordAuthenticationToken auth = (UsernamePasswordAuthenticationToken) authentication; - - // Determine username - String username = (auth.getPrincipal() == null) ? "NONE_PROVIDED" - : auth.getName(); - - UserDetails user; - - try { - user = retrieveUser(username, auth); - if (user == null) - throw new IllegalStateException( - "retrieveUser returned null - a violation of the interface contract"); - } catch (UsernameNotFoundException notFound) { - if (logger.isDebugEnabled()) - logger.debug("User '" + username + "' not found", notFound); - throw new BadCredentialsException("Bad credentials"); - } - - // Pre-auth - if (!user.isAccountNonLocked()) - throw new LockedException("User account is locked"); - if (!user.isEnabled()) - throw new DisabledException("User account is disabled"); - if (!user.isAccountNonExpired()) - throw new AccountExpiredException("User account has expired"); - Object credentials = auth.getCredentials(); - if (credentials == null) { - logger.debug("Authentication failed: no credentials provided"); - - throw new BadCredentialsException("Bad credentials"); - } - - String providedPassword = credentials.toString(); - boolean matched = false; - synchronized (authCache) { - AuthCacheEntry pw = authCache.get(username); - if (pw != null && providedPassword != null) { - if (pw.valid(providedPassword)) - matched = true; - else - authCache.remove(username); - } - } - // Auth - if (!matched) { - if (!passwordEncoder.matches(providedPassword, user.getPassword())) { - logger.debug("Authentication failed: password does not match stored value"); - - throw new BadCredentialsException("Bad credentials"); - } - if (providedPassword != null) - synchronized (authCache) { - authCache.put(username, new AuthCacheEntry(providedPassword)); - } - } - - // Post-auth - if (!user.isCredentialsNonExpired()) - throw new CredentialsExpiredException( - "User credentials have expired"); - - return createSuccessAuthentication(user, auth, user); - } - - @PreDestroy - void clearCache() { - authCache.clear(); - } - - /** - * Creates a successful {@link Authentication} object. - * <p> - * Protected so subclasses can override. - * </p> - * <p> - * Subclasses will usually store the original credentials the user supplied - * (not salted or encoded passwords) in the returned - * <code>Authentication</code> object. - * </p> - * - * @param principal - * that should be the principal in the returned object (defined - * by the {@link #isForcePrincipalAsString()} method) - * @param authentication - * that was presented to the provider for validation - * @param user - * that was loaded by the implementation - * - * @return the successful authentication token - */ - private Authentication createSuccessAuthentication(Object principal, - Authentication authentication, UserDetails user) { - /* - * Ensure we return the original credentials the user supplied, so - * subsequent attempts are successful even with encoded passwords. Also - * ensure we return the original getDetails(), so that future - * authentication events after cache expiry contain the details - */ - UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken( - principal, authentication.getCredentials(), - user.getAuthorities()); - result.setDetails(authentication.getDetails()); - - return result; - } - - @Override - public boolean supports(Class<?> authentication) { - return UsernamePasswordAuthenticationToken.class - .isAssignableFrom(authentication); - } - - /** - * Allows subclasses to actually retrieve the <code>UserDetails</code> from - * an implementation-specific location, with the option of throwing an - * <code>AuthenticationException</code> immediately if the presented - * credentials are incorrect (this is especially useful if it is necessary - * to bind to a resource as the user in order to obtain or generate a - * <code>UserDetails</code>). - * <p> - * Subclasses are not required to perform any caching, as the - * <code>AbstractUserDetailsAuthenticationProvider</code> will by default - * cache the <code>UserDetails</code>. The caching of - * <code>UserDetails</code> does present additional complexity as this means - * subsequent requests that rely on the cache will need to still have their - * credentials validated, even if the correctness of credentials was assured - * by subclasses adopting a binding-based strategy in this method. - * Accordingly it is important that subclasses either disable caching (if - * they want to ensure that this method is the only method that is capable - * of authenticating a request, as no <code>UserDetails</code> will ever be - * cached) or ensure subclasses implement - * {@link #additionalAuthenticationChecks(UserDetails, UsernamePasswordAuthenticationToken)} - * to compare the credentials of a cached <code>UserDetails</code> with - * subsequent authentication requests. - * </p> - * <p> - * Most of the time subclasses will not perform credentials inspection in - * this method, instead performing it in - * {@link #additionalAuthenticationChecks(UserDetails, UsernamePasswordAuthenticationToken)} - * so that code related to credentials validation need not be duplicated - * across two methods. - * </p> - * - * @param username - * The username to retrieve - * @param authentication - * The authentication request, which subclasses <em>may</em> need - * to perform a binding-based retrieval of the - * <code>UserDetails</code> - * - * @return the user information (never <code>null</code> - instead an - * exception should the thrown) - * - * @throws AuthenticationException - * if the credentials could not be validated (generally a - * <code>BadCredentialsException</code>, an - * <code>AuthenticationServiceException</code> or - * <code>UsernameNotFoundException</code>) - */ - private UserDetails retrieveUser(String username, - UsernamePasswordAuthenticationToken authentication) - throws AuthenticationException { - try { - return userDetailsService.loadUserByUsername(username); - } catch (UsernameNotFoundException notFound) { - if (authentication.getCredentials() != null) { - String presentedPassword = authentication.getCredentials() - .toString(); - passwordEncoder.matches(presentedPassword, - userNotFoundEncodedPassword); - } - throw notFound; - } catch (AuthenticationException e) { - throw e; - } catch (Exception repositoryProblem) { - throw new AuthenticationServiceException( - repositoryProblem.getMessage(), repositoryProblem); - } - } - - /** - * Sets the PasswordEncoder instance to be used to encode and validate - * passwords. - */ - @Required - public void setPasswordEncoder(PasswordEncoder passwordEncoder) { - if (passwordEncoder == null) - throw new IllegalArgumentException("passwordEncoder cannot be null"); - - this.passwordEncoder = passwordEncoder; - this.userNotFoundEncodedPassword = passwordEncoder - .encode(USER_NOT_FOUND_PASSWORD); - } - - @Required - public void setUserDetailsService(UserDetailsService userDetailsService) { - if (userDetailsService == null) - throw new IllegalStateException("A UserDetailsService must be set"); - this.userDetailsService = userDetailsService; - } -}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/User.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/User.java b/server-webapp/src/main/java/org/taverna/server/master/identity/User.java deleted file mode 100644 index bdb6e40..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/identity/User.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2011-2012 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.identity; - -import static org.taverna.server.master.common.Roles.ADMIN; -import static org.taverna.server.master.common.Roles.USER; -import static org.taverna.server.master.defaults.Default.AUTHORITY_PREFIX; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import javax.jdo.annotations.PersistenceCapable; -import javax.jdo.annotations.Persistent; -import javax.jdo.annotations.Query; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; - -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; - -/** - * The representation of a user in the database. - * <p> - * A user consists logically of a (non-ordered) tuple of items: - * <ul> - * <li>The {@linkplain #getUsername() user name}, - * <li>The {@linkplain #getPassword() user's password} (salted, encoded), - * <li>Whether the user is {@linkplain #isEnabled() enabled} (i.e., able to log - * in), - * <li>Whether the user has {@linkplain #isAdmin() administrative privileges}, and - * <li>What {@linkplain #getLocalUsername() system (Unix) account} the user's - * workflows will run as; separation between different users that are mapped to - * the same system account is nothing like as strongly enforced. - * </ul> - * - * @author Donal Fellows - */ -@PersistenceCapable(schema = "USERS", table = "LIST") -@Query(name = "users", language = "SQL", value = "SELECT id FROM USERS.LIST ORDER BY id", resultClass = String.class) -@XmlRootElement -@XmlType(name = "User", propOrder = {}) -@SuppressWarnings("serial") -public class User implements UserDetails { - @XmlElement - @Persistent - private boolean disabled; - @XmlElement(name = "username", required = true) - @Persistent(primaryKey = "true") - private String id; - @XmlElement(name = "password", required = true) - @Persistent(column = "password") - private String encodedPassword; - @XmlElement - @Persistent - private boolean admin; - @XmlElement - @Persistent - private String localUsername; - - @Override - public Collection<GrantedAuthority> getAuthorities() { - List<GrantedAuthority> auths = new ArrayList<>(); - auths.add(new LiteralGrantedAuthority(USER)); - if (admin) - auths.add(new LiteralGrantedAuthority(ADMIN)); - if (localUsername != null) - auths.add(new LiteralGrantedAuthority(AUTHORITY_PREFIX - + localUsername)); - return auths; - } - - @Override - public String getPassword() { - return encodedPassword; - } - - @Override - public String getUsername() { - return id; - } - - @Override - public boolean isAccountNonExpired() { - return true; - } - - @Override - public boolean isAccountNonLocked() { - return true; - } - - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - @Override - public boolean isEnabled() { - return !disabled; - } - - void setDisabled(boolean disabled) { - this.disabled = disabled; - } - - void setUsername(String username) { - this.id = username; - } - - void setEncodedPassword(String password) { - this.encodedPassword = password; - } - - void setAdmin(boolean admin) { - this.admin = admin; - } - - public boolean isAdmin() { - return admin; - } - - void setLocalUsername(String localUsername) { - this.localUsername = localUsername; - } - - public String getLocalUsername() { - return localUsername; - } -} - -@SuppressWarnings("serial") -class LiteralGrantedAuthority implements GrantedAuthority { - private String auth; - - LiteralGrantedAuthority(String auth) { - this.auth = auth; - } - - @Override - public String getAuthority() { - return auth; - } - - @Override - public String toString() { - return "AUTHORITY(" + auth + ")"; - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/UserStore.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/UserStore.java b/server-webapp/src/main/java/org/taverna/server/master/identity/UserStore.java deleted file mode 100644 index 054d932..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/identity/UserStore.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (C) 2011-2012 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.identity; - -import static org.apache.commons.logging.LogFactory.getLog; -import static org.taverna.server.master.TavernaServer.JMX_ROOT; -import static org.taverna.server.master.common.Roles.ADMIN; -import static org.taverna.server.master.common.Roles.USER; -import static org.taverna.server.master.defaults.Default.AUTHORITY_PREFIX; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; -import javax.jdo.annotations.PersistenceAware; - -import org.apache.commons.logging.Log; -import org.springframework.beans.factory.annotation.Required; -import org.springframework.dao.DataAccessException; -import org.springframework.jmx.export.annotation.ManagedAttribute; -import org.springframework.jmx.export.annotation.ManagedOperation; -import org.springframework.jmx.export.annotation.ManagedOperationParameter; -import org.springframework.jmx.export.annotation.ManagedOperationParameters; -import org.springframework.jmx.export.annotation.ManagedResource; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.core.userdetails.memory.UserAttribute; -import org.springframework.security.core.userdetails.memory.UserAttributeEditor; -import org.taverna.server.master.utils.CallTimeLogger.PerfLogged; -import org.taverna.server.master.utils.JDOSupport; - -/** - * The bean class that is responsible for managing the users in the database. - * - * @author Donal Fellows - */ -@PersistenceAware -@ManagedResource(objectName = JMX_ROOT + "Users", description = "The user database.") -public class UserStore extends JDOSupport<User> implements UserDetailsService, - UserStoreAPI { - /** The logger for the user store. */ - private transient Log log = getLog("Taverna.Server.UserDB"); - - public UserStore() { - super(User.class); - } - - @PreDestroy - void closeLog() { - log = null; - } - - private Map<String, BootstrapUserInfo> base = new HashMap<>(); - private String defLocalUser; - private PasswordEncoder encoder; - private volatile int epoch; - - /** - * Install the encoder that will be used to turn a plaintext password into - * something that it is safe to store in the database. - * - * @param encoder - * The password encoder bean to install. - */ - public void setEncoder(PasswordEncoder encoder) { - this.encoder = encoder; - } - - public void setBaselineUserProperties(Properties props) { - UserAttributeEditor parser = new UserAttributeEditor(); - - for (Object name : props.keySet()) { - String username = (String) name; - String value = props.getProperty(username); - - // Convert value to a password, enabled setting, and list of granted - // authorities - parser.setAsText(value); - - UserAttribute attr = (UserAttribute) parser.getValue(); - if (attr != null && attr.isEnabled()) - base.put(username, new BootstrapUserInfo(username, attr)); - } - } - - private void installPassword(User u, String password) { - u.setEncodedPassword(encoder.encode(password)); - } - - public void setDefaultLocalUser(String defLocalUser) { - this.defLocalUser = defLocalUser; - } - - @SuppressWarnings("unchecked") - private List<String> getUsers() { - return (List<String>) namedQuery("users").execute(); - } - - @WithinSingleTransaction - @PostConstruct - void initDB() { - if (base == null || base.isEmpty()) - log.warn("no baseline user collection"); - else if (!getUsers().isEmpty()) - log.info("using existing users from database"); - else - for (String username : base.keySet()) { - BootstrapUserInfo ud = base.get(username); - if (ud == null) - continue; - User u = ud.get(encoder); - if (u == null) - continue; - log.info("bootstrapping user " + username + " in the database"); - persist(u); - } - base = null; - epoch++; - } - - @Override - @PerfLogged - @WithinSingleTransaction - @ManagedAttribute(description = "The list of server accounts known about.", currencyTimeLimit = 30) - public List<String> getUserNames() { - return getUsers(); - } - - @Override - @PerfLogged - @WithinSingleTransaction - public User getUser(String userName) { - return detach(getById(userName)); - } - - /** - * Get information about a server account. - * - * @param userName - * The username to look up. - * @return A description map intended for use by a server admin over JMX. - */ - @PerfLogged - @WithinSingleTransaction - @ManagedOperation(description = "Get information about a server account.") - @ManagedOperationParameters(@ManagedOperationParameter(name = "userName", description = "The username to look up.")) - public Map<String, String> getUserInfo(String userName) { - User u = getById(userName); - Map<String, String> info = new HashMap<>(); - info.put("name", u.getUsername()); - info.put("admin", u.isAdmin() ? "yes" : "no"); - info.put("enabled", u.isEnabled() ? "yes" : "no"); - info.put("localID", u.getLocalUsername()); - return info; - } - - /** - * Get a list of all the users in the database. - * - * @return A list of user details, <i>copied</i> out of the database. - */ - @PerfLogged - @WithinSingleTransaction - public List<UserDetails> listUsers() { - ArrayList<UserDetails> result = new ArrayList<>(); - for (String id : getUsers()) - result.add(detach(getById(id))); - return result; - } - - @Override - @PerfLogged - @WithinSingleTransaction - @ManagedOperation(description = "Create a new user account; the account will be disabled and " - + "non-administrative by default. Does not create any underlying system account.") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "username", description = "The username to create."), - @ManagedOperationParameter(name = "password", description = "The password to use."), - @ManagedOperationParameter(name = "coupleLocalUsername", description = "Whether to set the local user name to the 'main' one.") }) - public void addUser(String username, String password, - boolean coupleLocalUsername) { - if (username.matches(".*[^a-zA-Z0-9].*")) - throw new IllegalArgumentException( - "bad user name; must be pure alphanumeric"); - if (getById(username) != null) - throw new IllegalArgumentException("user name already exists"); - User u = new User(); - u.setDisabled(true); - u.setAdmin(false); - u.setUsername(username); - installPassword(u, password); - if (coupleLocalUsername) - u.setLocalUsername(username); - else - u.setLocalUsername(defLocalUser); - log.info("creating user for " + username); - persist(u); - epoch++; - } - - @Override - @PerfLogged - @WithinSingleTransaction - @ManagedOperation(description = "Set or clear whether this account is enabled. " - + "Disabled accounts cannot be used to log in.") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "username", description = "The username to adjust."), - @ManagedOperationParameter(name = "enabled", description = "Whether to enable the account.") }) - public void setUserEnabled(String username, boolean enabled) { - User u = getById(username); - if (u != null) { - u.setDisabled(!enabled); - log.info((enabled ? "enabling" : "disabling") + " user " + username); - epoch++; - } - } - - @Override - @PerfLogged - @WithinSingleTransaction - @ManagedOperation(description = "Set or clear the mark on an account that indicates " - + "that it has administrative privileges.") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "username", description = "The username to adjust."), - @ManagedOperationParameter(name = "admin", description = "Whether the account has admin privileges.") }) - public void setUserAdmin(String username, boolean admin) { - User u = getById(username); - if (u != null) { - u.setAdmin(admin); - log.info((admin ? "enabling" : "disabling") + " user " + username - + " admin status"); - epoch++; - } - } - - @Override - @PerfLogged - @WithinSingleTransaction - @ManagedOperation(description = "Change the password for an account.") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "username", description = "The username to adjust."), - @ManagedOperationParameter(name = "password", description = "The new password to use.") }) - public void setUserPassword(String username, String password) { - User u = getById(username); - if (u != null) { - installPassword(u, password); - log.info("changing password for user " + username); - epoch++; - } - } - - @Override - @PerfLogged - @WithinSingleTransaction - @ManagedOperation(description = "Change what local system account to use for a server account.") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "username", description = "The username to adjust."), - @ManagedOperationParameter(name = "password", description = "The new local user account use.") }) - public void setUserLocalUser(String username, String localUsername) { - User u = getById(username); - if (u != null) { - u.setLocalUsername(localUsername); - log.info("mapping user " + username + " to local account " - + localUsername); - epoch++; - } - } - - @Override - @PerfLogged - @WithinSingleTransaction - @ManagedOperation(description = "Delete a server account. The underlying " - + "system account is not modified.") - @ManagedOperationParameters(@ManagedOperationParameter(name = "username", description = "The username to delete.")) - public void deleteUser(String username) { - delete(getById(username)); - log.info("deleting user " + username); - epoch++; - } - - @Override - @PerfLogged - @WithinSingleTransaction - public UserDetails loadUserByUsername(String username) - throws UsernameNotFoundException, DataAccessException { - User u; - if (base != null) { - log.warn("bootstrap user store still installed!"); - BootstrapUserInfo ud = base.get(username); - if (ud != null) { - log.warn("retrieved production credentials for " + username - + " from bootstrap store"); - u = ud.get(encoder); - if (u != null) - return u; - } - } - try { - u = detach(getById(username)); - } catch (NullPointerException npe) { - throw new UsernameNotFoundException("who are you?"); - } catch (Exception ex) { - throw new UsernameNotFoundException("who are you?", ex); - } - if (u != null) - return u; - throw new UsernameNotFoundException("who are you?"); - } - - int getEpoch() { - return epoch; - } - - public static class CachedUserStore implements UserDetailsService { - private int epoch; - private Map<String, UserDetails> cache = new HashMap<>(); - private UserStore realStore; - - @Required - public void setRealStore(UserStore store) { - this.realStore = store; - } - - @Override - @PerfLogged - public UserDetails loadUserByUsername(String username) { - int epoch = realStore.getEpoch(); - UserDetails details; - synchronized (cache) { - if (epoch != this.epoch) { - cache.clear(); - this.epoch = epoch; - details = null; - } else - details = cache.get(username); - } - if (details == null) { - details = realStore.loadUserByUsername(username); - synchronized (cache) { - cache.put(username, details); - } - } - return details; - } - } - - private static class BootstrapUserInfo { - private String user; - private String pass; - private Collection<GrantedAuthority> auth; - - BootstrapUserInfo(String username, UserAttribute attr) { - user = username; - pass = attr.getPassword(); - auth = attr.getAuthorities(); - } - - User get(PasswordEncoder encoder) { - User u = new User(); - boolean realUser = false; - for (GrantedAuthority ga : auth) { - String a = ga.getAuthority(); - if (a.startsWith(AUTHORITY_PREFIX)) - u.setLocalUsername(a.substring(AUTHORITY_PREFIX.length())); - else if (a.equals(USER)) - realUser = true; - else if (a.equals(ADMIN)) - u.setAdmin(true); - } - if (!realUser) - return null; - u.setUsername(user); - u.setEncodedPassword(encoder.encode(pass)); - u.setDisabled(false); - return u; - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/UserStoreAPI.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/UserStoreAPI.java b/server-webapp/src/main/java/org/taverna/server/master/identity/UserStoreAPI.java deleted file mode 100644 index a048da9..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/identity/UserStoreAPI.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.taverna.server.master.identity; - -import java.util.List; - -/** - * The API that is exposed by the DAO that exposes user management. - * - * @author Donal Fellows - * @see User - */ -public interface UserStoreAPI { - /** - * List the currently-known account names. - * - * @return A list of users in the database. Note that this is a snapshot. - */ - List<String> getUserNames(); - - /** - * Get a particular user's description. - * - * @param userName - * The username to look up. - * @return A <i>copy</i> of the user description. - */ - User getUser(String userName); - - /** - * Create a new user account; the account will be disabled and - * non-administrative by default. Does not create any underlying system - * account. - * - * @param username - * The username to create. - * @param password - * The password to use. - * @param coupleLocalUsername - * Whether to set the local user name to the 'main' one. - */ - void addUser(String username, String password, boolean coupleLocalUsername); - - /** - * Set or clear whether this account is enabled. Disabled accounts cannot be - * used to log in. - * - * @param username - * The username to adjust. - * @param enabled - * Whether to enable the account. - */ - void setUserEnabled(String username, boolean enabled); - - /** - * Set or clear the mark on an account that indicates that it has - * administrative privileges. - * - * @param username - * The username to adjust. - * @param admin - * Whether the account has admin privileges. - */ - void setUserAdmin(String username, boolean admin); - - /** - * Change the password for an account. - * - * @param username - * The username to adjust. - * @param password - * The new password to use. - */ - void setUserPassword(String username, String password); - - /** - * Change what local system account to use for a server account. - * - * @param username - * The username to adjust. - * @param localUsername - * The new local user account use. - */ - void setUserLocalUser(String username, String localUsername); - - /** - * Delete a server account. The underlying system account is not modified. - * - * @param username - * The username to delete. - */ - void deleteUser(String username); -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/WorkflowInternalAuthProvider.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/WorkflowInternalAuthProvider.java b/server-webapp/src/main/java/org/taverna/server/master/identity/WorkflowInternalAuthProvider.java deleted file mode 100644 index 9219a60..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/identity/WorkflowInternalAuthProvider.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (C) 2013 The University of Manchester - * - * See the file "LICENSE.txt" for license terms. - */ -package org.taverna.server.master.identity; - -import static java.util.Collections.synchronizedMap; -import static org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes; -import static org.taverna.server.master.common.Roles.SELF; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; - -import javax.annotation.Nonnull; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.annotation.Required; -import org.springframework.security.authentication.AuthenticationServiceException; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.web.authentication.WebAuthenticationDetails; -import org.springframework.web.context.request.ServletRequestAttributes; -import org.taverna.server.master.exceptions.UnknownRunException; -import org.taverna.server.master.interfaces.LocalIdentityMapper; -import org.taverna.server.master.interfaces.RunStore; -import org.taverna.server.master.utils.CallTimeLogger.PerfLogged; -import org.taverna.server.master.utils.UsernamePrincipal; -import org.taverna.server.master.worker.RunDatabaseDAO; - -/** - * A special authentication provider that allows a workflow to authenticate to - * itself. This is used to allow the workflow to publish to its own interaction - * feed. - * - * @author Donal Fellows - */ -public class WorkflowInternalAuthProvider extends - AbstractUserDetailsAuthenticationProvider { - private Log log = LogFactory.getLog("Taverna.Server.UserDB"); - private static final boolean logDecisions = true; - public static final String PREFIX = "wfrun_"; - private RunDatabaseDAO dao; - private Map<String, String> cache; - - @Required - public void setDao(RunDatabaseDAO dao) { - this.dao = dao; - } - - @Required - @SuppressWarnings("serial") - public void setCacheBound(final int bound) { - cache = synchronizedMap(new LinkedHashMap<String, String>() { - @Override - protected boolean removeEldestEntry(Map.Entry<String, String> eldest) { - return size() > bound; - } - }); - } - - public void setAuthorizedAddresses(String[] addresses) { - authorizedAddresses = new HashSet<>(localAddresses); - for (String s : addresses) - authorizedAddresses.add(s); - } - - @PostConstruct - public void logConfig() { - log.info("authorized addresses for automatic access: " - + authorizedAddresses); - } - - @PreDestroy - void closeLog() { - log = null; - } - - private final Set<String> localAddresses = new HashSet<>(); - private Set<String> authorizedAddresses; - { - localAddresses.add("127.0.0.1"); // IPv4 - localAddresses.add("::1"); // IPv6 - try { - InetAddress addr = InetAddress.getLocalHost(); - if (!addr.isLoopbackAddress()) - localAddresses.add(addr.getHostAddress()); - } catch (UnknownHostException e) { - // Ignore the exception - } - authorizedAddresses = new HashSet<>(localAddresses); - } - - /** - * Check that the authentication request is actually valid for the given - * user record. - * - * @param userRecord - * as retrieved from the - * {@link #retrieveUser(String, UsernamePasswordAuthenticationToken)} - * or <code>UserCache</code> - * @param principal - * the principal that is trying to authenticate (and that we're - * trying to bind) - * @param credentials - * the credentials (e.g., password) presented by the principal - * - * @throws AuthenticationException - * AuthenticationException if the credentials could not be - * validated (generally a <code>BadCredentialsException</code>, - * an <code>AuthenticationServiceException</code>) - * @throws Exception - * If something goes wrong. Will be logged and converted to a - * generic AuthenticationException. - */ - protected void additionalAuthenticationChecks(UserDetails userRecord, - @Nonnull Object principal, @Nonnull Object credentials) - throws Exception { - @Nonnull - HttpServletRequest req = ((ServletRequestAttributes) currentRequestAttributes()) - .getRequest(); - - // Are we coming from a "local" address? - if (!req.getLocalAddr().equals(req.getRemoteAddr()) - && !authorizedAddresses.contains(req.getRemoteAddr())) { - if (logDecisions) - log.info("attempt to use workflow magic token from untrusted address:" - + " token=" - + userRecord.getUsername() - + ", address=" - + req.getRemoteAddr()); - throw new BadCredentialsException("bad login token"); - } - - // Does the password match? - if (!credentials.equals(userRecord.getPassword())) { - if (logDecisions) - log.info("workflow magic token is untrusted due to password mismatch:" - + " wanted=" - + userRecord.getPassword() - + ", got=" - + credentials); - throw new BadCredentialsException("bad login token"); - } - - if (logDecisions) - log.info("granted role " + SELF + " to user " - + userRecord.getUsername()); - } - - /** - * Retrieve the <code>UserDetails</code> from the relevant store, with the - * option of throwing an <code>AuthenticationException</code> immediately if - * the presented credentials are incorrect (this is especially useful if it - * is necessary to bind to a resource as the user in order to obtain or - * generate a <code>UserDetails</code>). - * - * @param username - * The username to retrieve - * @param details - * The details from the authentication request. - * @see #retrieveUser(String,UsernamePasswordAuthenticationToken) - * @return the user information (never <code>null</code> - instead an - * exception should the thrown) - * @throws AuthenticationException - * if the credentials could not be validated (generally a - * <code>BadCredentialsException</code>, an - * <code>AuthenticationServiceException</code> or - * <code>UsernameNotFoundException</code>) - * @throws Exception - * If something goes wrong. It will be logged and converted into - * a general AuthenticationException. - */ - @Nonnull - protected UserDetails retrieveUser(String username, Object details) - throws Exception { - if (details == null || !(details instanceof WebAuthenticationDetails)) - throw new UsernameNotFoundException("context unsupported"); - if (!username.startsWith(PREFIX)) - throw new UsernameNotFoundException( - "unsupported username for this provider"); - if (logDecisions) - log.info("request for auth for user " + username); - String wfid = username.substring(PREFIX.length()); - String securityToken; - try { - securityToken = cache.get(wfid); - if (securityToken == null) { - securityToken = dao.getSecurityToken(wfid); - if (securityToken == null) - throw new UsernameNotFoundException("no such user"); - cache.put(wfid, securityToken); - } - } catch (NullPointerException npe) { - throw new UsernameNotFoundException("no such user"); - } - return new User(username, securityToken, true, true, true, true, - Arrays.asList(new LiteralGrantedAuthority(SELF), - new WorkflowSelfAuthority(wfid))); - } - - @Override - @PerfLogged - protected final void additionalAuthenticationChecks(UserDetails userRecord, - UsernamePasswordAuthenticationToken token) { - try { - additionalAuthenticationChecks(userRecord, token.getPrincipal(), - token.getCredentials()); - } catch (AuthenticationException e) { - throw e; - } catch (Exception e) { - log.warn("unexpected failure in authentication", e); - throw new AuthenticationServiceException( - "unexpected failure in authentication", e); - } - } - - @Override - @Nonnull - @PerfLogged - protected final UserDetails retrieveUser(String username, - UsernamePasswordAuthenticationToken token) { - try { - return retrieveUser(username, token.getDetails()); - } catch (AuthenticationException e) { - throw e; - } catch (Exception e) { - log.warn("unexpected failure in authentication", e); - throw new AuthenticationServiceException( - "unexpected failure in authentication", e); - } - } - - @SuppressWarnings("serial") - public static class WorkflowSelfAuthority extends LiteralGrantedAuthority { - public WorkflowSelfAuthority(String wfid) { - super(wfid); - } - - public String getWorkflowID() { - return getAuthority(); - } - - @Override - public String toString() { - return "WORKFLOW(" + getAuthority() + ")"; - } - } - - public static class WorkflowSelfIDMapper implements LocalIdentityMapper { - private Log log = LogFactory.getLog("Taverna.Server.UserDB"); - private RunStore runStore; - - @PreDestroy - void closeLog() { - log = null; - } - - @Required - public void setRunStore(RunStore runStore) { - this.runStore = runStore; - } - - private String getUsernameForSelfAccess(WorkflowSelfAuthority authority) - throws UnknownRunException { - return runStore.getRun(authority.getWorkflowID()) - .getSecurityContext().getOwner().getName(); - } - - @Override - @PerfLogged - public String getUsernameForPrincipal(UsernamePrincipal user) { - Authentication auth = SecurityContextHolder.getContext() - .getAuthentication(); - if (auth == null || !auth.isAuthenticated()) - return null; - try { - for (GrantedAuthority authority : auth.getAuthorities()) - if (authority instanceof WorkflowSelfAuthority) - return getUsernameForSelfAccess((WorkflowSelfAuthority) authority); - } catch (UnknownRunException e) { - log.warn("workflow run disappeared during computation of workflow map identity"); - } - return null; - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/package-info.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/identity/package-info.java deleted file mode 100644 index dd1500a..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/identity/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (C) 2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -/** - * Implementations of beans that map global user identities to local - * usernames. - */ -package org.taverna.server.master.identity; http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interaction/InteractionFeedSupport.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/interaction/InteractionFeedSupport.java b/server-webapp/src/main/java/org/taverna/server/master/interaction/InteractionFeedSupport.java deleted file mode 100644 index 99e1d99..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/interaction/InteractionFeedSupport.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (C) 2013 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.interaction; - -import static java.lang.management.ManagementFactory.getPlatformMBeanServer; -import static java.util.Collections.reverse; -import static javax.management.Query.attr; -import static javax.management.Query.match; -import static javax.management.Query.value; -import static org.apache.commons.logging.LogFactory.getLog; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; -import javax.management.MBeanServer; -import javax.management.ObjectName; - -import org.apache.abdera.Abdera; -import org.apache.abdera.factory.Factory; -import org.apache.abdera.i18n.iri.IRI; -import org.apache.abdera.model.Document; -import org.apache.abdera.model.Entry; -import org.apache.abdera.model.Feed; -import org.apache.abdera.parser.Parser; -import org.apache.abdera.writer.Writer; -import org.springframework.beans.factory.annotation.Required; -import org.taverna.server.master.TavernaServerSupport; -import org.taverna.server.master.exceptions.FilesystemAccessException; -import org.taverna.server.master.exceptions.NoDirectoryEntryException; -import org.taverna.server.master.exceptions.NoUpdateException; -import org.taverna.server.master.interfaces.Directory; -import org.taverna.server.master.interfaces.DirectoryEntry; -import org.taverna.server.master.interfaces.File; -import org.taverna.server.master.interfaces.TavernaRun; -import org.taverna.server.master.interfaces.UriBuilderFactory; -import org.taverna.server.master.utils.FilenameUtils; - -/** - * Bean that supports interaction feeds. This glues together the Abdera - * serialization engine and the directory-based model used inside the server. - * - * @author Donal Fellows - */ -public class InteractionFeedSupport { - /** - * The name of the resource within the run resource that is the run's - * interaction feed resource. - */ - public static final String FEED_URL_DIR = "interaction"; - /** - * The name of the directory below the run working directory that will - * contain the entries of the interaction feed. - */ - public static final String FEED_DIR = "feed"; - /** - * Should the contents of the entry be stripped when describing the overall - * feed? This makes sense if (and only if) large entries are being pushed - * through the feed. - */ - private static final boolean STRIP_CONTENTS = false; - /** Maximum size of an entry before truncation. */ - private static final long MAX_ENTRY_SIZE = 50 * 1024; - /** Extension for entry files. */ - private static final String EXT = ".atom"; - - private TavernaServerSupport support; - private FilenameUtils utils; - private Writer writer; - private Parser parser; - private Factory factory; - private UriBuilderFactory uriBuilder; - - private AtomicInteger counter = new AtomicInteger(); - - @Required - public void setSupport(TavernaServerSupport support) { - this.support = support; - } - - @Required - public void setUtils(FilenameUtils utils) { - this.utils = utils; - } - - @Required - public void setAbdera(Abdera abdera) { - this.factory = abdera.getFactory(); - this.parser = abdera.getParser(); - this.writer = abdera.getWriterFactory().getWriter("prettyxml"); - } - - @Required - // webapp - public void setUriBuilder(UriBuilderFactory uriBuilder) { - this.uriBuilder = uriBuilder; - } - - private final Map<String, URL> endPoints = new HashMap<>(); - - @PostConstruct - void determinePorts() { - try { - MBeanServer mbs = getPlatformMBeanServer(); - for (ObjectName obj : mbs.queryNames(new ObjectName( - "*:type=Connector,*"), - match(attr("protocol"), value("HTTP/1.1")))) { - String scheme = mbs.getAttribute(obj, "scheme").toString(); - String port = obj.getKeyProperty("port"); - endPoints.put(scheme, new URL(scheme + "://localhost:" + port)); - } - getLog(getClass()).info( - "installed feed port publication mapping for " - + endPoints.keySet()); - } catch (Exception e) { - getLog(getClass()).error( - "failure in determining local port mapping", e); - } - } - - /** - * @param run - * The workflow run that defines which feed we are operating on. - * @return The URI of the feed - */ - public URI getFeedURI(TavernaRun run) { - return uriBuilder.getRunUriBuilder(run).path(FEED_URL_DIR).build(); - } - - @Nullable - public URL getLocalFeedBase(URI feedURI) { - if (feedURI == null) - return null; - return endPoints.get(feedURI.getScheme()); - } - - /** - * @param run - * The workflow run that defines which feed we are operating on. - * @param id - * The ID of the entry. - * @return The URI of the entry. - */ - public URI getEntryURI(TavernaRun run, String id) { - return uriBuilder.getRunUriBuilder(run) - .path(FEED_URL_DIR + "/{entryID}").build(id); - } - - private Entry getEntryFromFile(File f) throws FilesystemAccessException { - long size = f.getSize(); - if (size > MAX_ENTRY_SIZE) - throw new FilesystemAccessException("entry larger than 50kB"); - byte[] contents = f.getContents(0, (int) size); - Document<Entry> doc = parser.parse(new ByteArrayInputStream(contents)); - return doc.getRoot(); - } - - private void putEntryInFile(Directory dir, String name, Entry contents) - throws FilesystemAccessException, NoUpdateException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - writer.writeTo(contents, baos); - } catch (IOException e) { - throw new NoUpdateException("failed to serialize the ATOM entry", e); - } - File f = dir.makeEmptyFile(support.getPrincipal(), name); - f.appendContents(baos.toByteArray()); - } - - private List<DirectoryEntry> listPossibleEntries(TavernaRun run) - throws FilesystemAccessException, NoDirectoryEntryException { - List<DirectoryEntry> entries = new ArrayList<>(utils.getDirectory(run, - FEED_DIR).getContentsByDate()); - reverse(entries); - return entries; - } - - private String getRunURL(TavernaRun run) { - return new IRI(uriBuilder.getRunUriBuilder(run).build()).toString(); - } - - /** - * Get the interaction feed for a partciular run. - * - * @param run - * The workflow run that defines which feed we are operating on. - * @return The Abdera feed descriptor. - * @throws FilesystemAccessException - * If the feed directory can't be read for some reason. - * @throws NoDirectoryEntryException - * If the feed directory doesn't exist or an entry is - * unexpectedly removed. - */ - public Feed getRunFeed(TavernaRun run) throws FilesystemAccessException, - NoDirectoryEntryException { - URI feedURI = getFeedURI(run); - Feed feed = factory.newFeed(); - feed.setTitle("Interactions for Taverna Run \"" + run.getName() + "\""); - feed.addLink(new IRI(feedURI).toString(), "self"); - feed.addLink(getRunURL(run), "workflowrun"); - boolean fetchedDate = false; - for (DirectoryEntry de : listPossibleEntries(run)) { - if (!(de instanceof File)) - continue; - try { - Entry e = getEntryFromFile((File) de); - if (STRIP_CONTENTS) - e.setContentElement(null); - feed.addEntry(e); - if (fetchedDate) - continue; - Date last = e.getUpdated(); - if (last == null) - last = e.getPublished(); - if (last == null) - last = de.getModificationDate(); - feed.setUpdated(last); - fetchedDate = true; - } catch (FilesystemAccessException e) { - // Can't do anything about it, so we'll just drop the entry. - } - } - return feed; - } - - /** - * Gets the contents of a particular feed entry. - * - * @param run - * The workflow run that defines which feed we are operating on. - * @param entryID - * The identifier (from the path) of the entry to read. - * @return The description of the entry. - * @throws FilesystemAccessException - * If the entry can't be read or is too large. - * @throws NoDirectoryEntryException - * If the entry can't be found. - */ - public Entry getRunFeedEntry(TavernaRun run, String entryID) - throws FilesystemAccessException, NoDirectoryEntryException { - File entryFile = utils.getFile(run, FEED_DIR + "/" + entryID + EXT); - return getEntryFromFile(entryFile); - } - - /** - * Given a partial feed entry, store a complete feed entry in the filesystem - * for a particular run. Note that this does not permit update of an - * existing entry; the entry is always created new. - * - * @param run - * The workflow run that defines which feed we are operating on. - * @param entry - * The partial entry to store - * @return A link to the entry. - * @throws FilesystemAccessException - * If the entry can't be stored. - * @throws NoDirectoryEntryException - * If the run is improperly configured. - * @throws NoUpdateException - * If the user isn't allowed to do the write. - * @throws MalformedURLException - * If a generated URL is illegal (shouldn't happen). - */ - public Entry addRunFeedEntry(TavernaRun run, Entry entry) - throws FilesystemAccessException, NoDirectoryEntryException, - NoUpdateException { - support.permitUpdate(run); - Date now = new Date(); - entry.newId(); - String localId = "entry_" + counter.incrementAndGet(); - IRI selfLink = new IRI(getEntryURI(run, localId)); - entry.addLink(selfLink.toString(), "self"); - entry.addLink(getRunURL(run), "workflowrun"); - entry.setUpdated(now); - entry.setPublished(now); - putEntryInFile(utils.getDirectory(run, FEED_DIR), localId + EXT, entry); - return getEntryFromFile(utils.getFile(run, FEED_DIR + "/" + localId - + EXT)); - } - - /** - * Deletes an entry from a feed. - * - * @param run - * The workflow run that defines which feed we are operating on. - * @param entryID - * The ID of the entry to delete. - * @throws FilesystemAccessException - * If the entry can't be deleted - * @throws NoDirectoryEntryException - * If the entry can't be found. - * @throws NoUpdateException - * If the current user is not permitted to modify the run's - * characteristics. - */ - public void removeRunFeedEntry(TavernaRun run, String entryID) - throws FilesystemAccessException, NoDirectoryEntryException, - NoUpdateException { - support.permitUpdate(run); - utils.getFile(run, FEED_DIR + "/" + entryID + EXT).destroy(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interaction/package-info.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/interaction/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/interaction/package-info.java deleted file mode 100644 index 9efc30d..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/interaction/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (C) 2013 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -/** - * This package contains the Atom feed implementation for interactions for a particular workflow run. - * @author Donal Fellows - */ -package org.taverna.server.master.interaction; http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/Directory.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Directory.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/Directory.java deleted file mode 100644 index 9a0a84e..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Directory.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2010-2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.interfaces; - -import java.io.PipedInputStream; -import java.security.Principal; -import java.util.Collection; - -import org.taverna.server.master.exceptions.FilesystemAccessException; - -/** - * Represents a directory that is the working directory of a workflow run, or a - * sub-directory of it. - * - * @author Donal Fellows - * @see File - */ -public interface Directory extends DirectoryEntry { - /** - * @return A list of the contents of the directory. - * @throws FilesystemAccessException - * If things go wrong. - */ - Collection<DirectoryEntry> getContents() throws FilesystemAccessException; - - /** - * @return A list of the contents of the directory, in guaranteed date - * order. - * @throws FilesystemAccessException - * If things go wrong. - */ - Collection<DirectoryEntry> getContentsByDate() - throws FilesystemAccessException; - - /** - * @return The contents of the directory (and its sub-directories) as a zip. - * @throws FilesystemAccessException - * If things go wrong. - */ - ZipStream getContentsAsZip() throws FilesystemAccessException; - - /** - * Creates a sub-directory of this directory. - * - * @param actor - * Who this is being created by. - * @param name - * The name of the sub-directory. - * @return A handle to the newly-created directory. - * @throws FilesystemAccessException - * If the name is the same as some existing entry in the - * directory, or if something else goes wrong during creation. - */ - Directory makeSubdirectory(Principal actor, String name) - throws FilesystemAccessException; - - /** - * Creates an empty file in this directory. - * - * @param actor - * Who this is being created by. - * @param name - * The name of the file to create. - * @return A handle to the newly-created file. - * @throws FilesystemAccessException - * If the name is the same as some existing entry in the - * directory, or if something else goes wrong during creation. - */ - File makeEmptyFile(Principal actor, String name) - throws FilesystemAccessException; - - /** - * A simple pipe that produces the zipped contents of a directory. - * - * @author Donal Fellows - */ - public static class ZipStream extends PipedInputStream { - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/DirectoryEntry.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/DirectoryEntry.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/DirectoryEntry.java deleted file mode 100644 index b098152..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/DirectoryEntry.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2010-2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.interfaces; - -import java.util.Date; - -import org.taverna.server.master.exceptions.FilesystemAccessException; - -/** - * An entry in a {@link Directory} representing a file or sub-directory. - * - * @author Donal Fellows - * @see Directory - * @see File - */ -public interface DirectoryEntry extends Comparable<DirectoryEntry> { - /** - * @return The "local" name of the entry. This will never be "<tt>..</tt>" - * or contain the character "<tt>/</tt>". - */ - public String getName(); - - /** - * @return The "full" name of the entry. This is computed relative to the - * workflow run's working directory. It may contain the "<tt>/</tt>" - * character. - */ - public String getFullName(); - - /** - * @return The time that the entry was last modified. - */ - public Date getModificationDate(); - - /** - * Destroy this directory entry, deleting the file or sub-directory. The - * workflow run's working directory can never be manually destroyed. - * - * @throws FilesystemAccessException - * If the destroy fails for some reason. - */ - public void destroy() throws FilesystemAccessException; - // TODO: Permissions (or decide not to do anything about them) -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/File.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/File.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/File.java deleted file mode 100644 index e4e6590..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/File.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2010-2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.interfaces; - -import org.taverna.server.master.exceptions.FilesystemAccessException; - -/** - * Represents a file in the working directory of a workflow instance run, or in - * some sub-directory of it. - * - * @author Donal Fellows - * @see Directory - */ -public interface File extends DirectoryEntry { - /** - * @param offset - * Where in the file to start reading. - * @param length - * The length of file to read, or -1 to read to the end of the - * file. - * @return The literal byte contents of the section of the file, or null if - * the section doesn't exist. - * @throws FilesystemAccessException - * If the read of the file goes wrong. - */ - public byte[] getContents(int offset, int length) - throws FilesystemAccessException; - - /** - * Write the data to the file, totally replacing what was there before. - * - * @param data - * The literal bytes that will form the new contents of the file. - * @throws FilesystemAccessException - * If the write to the file goes wrong. - */ - public void setContents(byte[] data) throws FilesystemAccessException; - - /** - * Append the data to the file. - * - * @param data - * The literal bytes that will be added on to the end of the - * file. - * @throws FilesystemAccessException - * If the write to the file goes wrong. - */ - public void appendContents(byte[] data) throws FilesystemAccessException; - - /** - * @return The length of the file, in bytes. - * @throws FilesystemAccessException - * If the read of the file size goes wrong. - */ - public long getSize() throws FilesystemAccessException; - - /** - * Asks for the argument file to be copied to this one. - * - * @param from - * The source file. - * @throws FilesystemAccessException - * If anything goes wrong. - */ - public void copy(File from) throws FilesystemAccessException; -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/Input.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Input.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/Input.java deleted file mode 100644 index 31cb7cb..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Input.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2010 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.interfaces; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import org.taverna.server.master.common.Status; -import org.taverna.server.master.exceptions.BadStateChangeException; -import org.taverna.server.master.exceptions.FilesystemAccessException; - -/** - * This represents the assignment of inputs to input ports of the workflow. Note - * that the <tt>file</tt> and <tt>value</tt> properties are never set at the - * same time. - * - * @author Donal Fellows - */ -public interface Input { - /** - * @return The file currently assigned to this input port, or <tt>null</tt> - * if no file is assigned. - */ - @Nullable - public String getFile(); - - /** - * @return The name of this input port. This may not be changed. - */ - @Nonnull - public String getName(); - - /** - * @return The value currently assigned to this input port, or <tt>null</tt> - * if no value is assigned. - */ - @Nullable - public String getValue(); - - /** - * @return The delimiter for the input port, or <tt>null</tt> if the value - * is not to be split. - */ - @Nullable - public String getDelimiter(); - - /** - * Sets the file to use for this input. This overrides the use of the - * previous file and any set value. - * - * @param file - * The filename to use. Must not start with a <tt>/</tt> or - * contain any <tt>..</tt> segments. Will be interpreted relative - * to the run's working directory. - * @throws FilesystemAccessException - * If the filename is invalid. - * @throws BadStateChangeException - * If the run isn't in the {@link Status#Initialized - * Initialized} state. - */ - public void setFile(String file) throws FilesystemAccessException, - BadStateChangeException; - - /** - * Sets the value to use for this input. This overrides the use of the - * previous value and any set file. - * - * @param value - * The value to use. - * @throws BadStateChangeException - * If the run isn't in the {@link Status#Initialized - * Initialized} state. - */ - public void setValue(String value) throws BadStateChangeException; - - /** - * Sets (or clears) the delimiter for the input port. - * - * @param delimiter - * The delimiter character, or <tt>null</tt> if the value is not - * to be split. - * @throws BadStateChangeException - * If the run isn't in the {@link Status#Initialized - * Initialized} state. - */ - @Nullable - public void setDelimiter(String delimiter) throws BadStateChangeException; - -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/Listener.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Listener.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/Listener.java deleted file mode 100644 index d7998bc..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Listener.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2010 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.interfaces; - -import org.taverna.server.master.exceptions.BadPropertyValueException; -import org.taverna.server.master.exceptions.NoListenerException; - -/** - * An event listener that can be attached to a {@link TavernaRun}. - * - * @author Donal Fellows - */ -public interface Listener { - /** - * @return The name of the listener. - */ - public String getName(); - - /** - * @return The type of the listener. - */ - public String getType(); - - /** - * @return The configuration document for the listener. - */ - public String getConfiguration(); - - /** - * @return The supported properties of the listener. - */ - public String[] listProperties(); - - /** - * Get the value of a particular property, which should be listed in the - * {@link #listProperties()} method. - * - * @param propName - * The name of the property to read. - * @return The value of the property. - * @throws NoListenerException - * If no property with that name exists. - */ - public String getProperty(String propName) throws NoListenerException; - - /** - * Set the value of a particular property, which should be listed in the - * {@link #listProperties()} method. - * - * @param propName - * The name of the property to write. - * @param value - * The value to set the property to. - * @throws NoListenerException - * If no property with that name exists. - * @throws BadPropertyValueException - * If the value of the property is bad (e.g., wrong syntax). - */ - public void setProperty(String propName, String value) - throws NoListenerException, BadPropertyValueException; -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/LocalIdentityMapper.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/LocalIdentityMapper.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/LocalIdentityMapper.java deleted file mode 100644 index 37b104e..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/LocalIdentityMapper.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2010-2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.interfaces; - -import org.taverna.server.master.utils.UsernamePrincipal; - -/** - * This interface describes how to map from the identity understood by the - * webapp to the identity understood by the local execution system. - * - * @author Donal Fellows - */ -public interface LocalIdentityMapper { - /** - * Given a user's identity, get the local identity to use for executing - * their workflows. Note that it is assumed that there will never be a - * failure from this interface; it is <i>not</i> a security policy - * decision or enforcement point. - * - * @param user - * An identity token. - * @return A user name, which must be defined in the context that workflows - * will be running in. - */ - public String getUsernameForPrincipal(UsernamePrincipal user); -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/MessageDispatcher.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/MessageDispatcher.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/MessageDispatcher.java deleted file mode 100644 index 37dbf2c..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/MessageDispatcher.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2010-2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.interfaces; - -import javax.annotation.Nonnull; - -/** - * The interface supported by all notification message dispatchers. - * @author Donal Fellows - */ -public interface MessageDispatcher { - /** - * @return Whether this message dispatcher is actually available (fully - * configured, etc.) - */ - boolean isAvailable(); - - /** - * @return The name of this dispatcher, which must match the protocol - * supported by it (for a non-universal dispatcher) and the name of - * the message generator used to produce the message. - */ - String getName(); - - /** - * Dispatch a message to a recipient. - * - * @param originator - * The workflow run that produced the message. - * @param messageSubject - * The subject of the message to send. - * @param messageContent - * The plain-text content of the message to send. - * @param targetParameter - * A description of where it is to go. - * @throws Exception - * If anything goes wrong. - */ - void dispatch(@Nonnull TavernaRun originator, - @Nonnull String messageSubject, @Nonnull String messageContent, - @Nonnull String targetParameter) throws Exception; -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/Policy.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Policy.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/Policy.java deleted file mode 100644 index f57fe71..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Policy.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2010 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.interfaces; - -import java.net.URI; -import java.util.List; - -import org.taverna.server.master.common.Status; -import org.taverna.server.master.common.Workflow; -import org.taverna.server.master.exceptions.NoCreateException; -import org.taverna.server.master.exceptions.NoDestroyException; -import org.taverna.server.master.exceptions.NoUpdateException; -import org.taverna.server.master.utils.UsernamePrincipal; - -/** - * Simple policy interface. - * - * @author Donal Fellows - */ -public interface Policy { - /** - * @return The maximum number of runs that the system can support. - */ - int getMaxRuns(); - - /** - * Get the limit on the number of runs for this user. - * - * @param user - * Who to get the limit for - * @return The maximum number of runs for this user, or <tt>null</tt> if no - * per-user limit is imposed and only system-wide limits are to be - * enforced. - */ - Integer getMaxRuns(UsernamePrincipal user); - - /** - * Test whether the user can create an instance of the given workflow. - * - * @param user - * Who wants to do the creation. - * @param workflow - * The workflow they wish to instantiate. - * @throws NoCreateException - * If they may not instantiate it. - */ - void permitCreate(UsernamePrincipal user, Workflow workflow) - throws NoCreateException; - - /** - * Test whether the user can destroy a workflow instance run or manipulate - * its expiry date. - * - * @param user - * Who wants to do the deletion. - * @param run - * What they want to delete. - * @throws NoDestroyException - * If they may not destroy it. - */ - void permitDestroy(UsernamePrincipal user, TavernaRun run) - throws NoDestroyException; - - /** - * Return whether the user has access to a particular workflow run. - * <b>Note</b> that this does not throw any exceptions! - * - * @param user - * Who wants to read the workflow's state. - * @param run - * What do they want to read from. - * @return Whether they can read it. Note that this check is always applied - * before testing whether the workflow can be updated or deleted by - * the user. - */ - boolean permitAccess(UsernamePrincipal user, TavernaRun run); - - /** - * Test whether the user can modify a workflow run (other than for its - * expiry date). - * - * @param user - * Who wants to do the modification. - * @param run - * What they want to modify. - * @throws NoUpdateException - * If they may not modify it. - */ - void permitUpdate(UsernamePrincipal user, TavernaRun run) - throws NoUpdateException; - - /** - * Get the URIs of the workflows that the given user may execute. - * - * @param user - * Who are we finding out on behalf of. - * @return A list of workflow URIs that they may instantiate, or - * <tt>null</tt> if any workflow may be submitted. - */ - List<URI> listPermittedWorkflowURIs(UsernamePrincipal user); - - /** - * @return The maximum number of {@linkplain Status#Operating operating} - * runs that the system can support. - */ - int getOperatingLimit(); - - /** - * Set the URIs of the workflows that the given user may execute. - * - * @param user - * Who are we finding out on behalf of. - * @param permitted - * A list of workflow URIs that they may instantiate. - */ - void setPermittedWorkflowURIs(UsernamePrincipal user, List<URI> permitted); -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/RunStore.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/RunStore.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/RunStore.java deleted file mode 100644 index b5e84c5..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/RunStore.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2010 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.interfaces; - -import java.util.Map; - -import org.taverna.server.master.exceptions.UnknownRunException; -import org.taverna.server.master.utils.UsernamePrincipal; - -/** - * Interface to the mechanism that looks after the mapping of names to runs. - * Instances of this class may also be responsible for enforcing timely cleanup - * of expired workflows. - * - * @author Donal Fellows. - */ -public interface RunStore { - /** - * Obtain the workflow run for a given user and name. - * - * @param user - * Who wants to do the lookup. - * @param p - * The general policy system context. - * @param uuid - * The handle for the run. - * @return The workflow instance run. - * @throws UnknownRunException - * If the lookup fails (either because it does not exist or - * because it is not permitted for the user by the policy). - */ - TavernaRun getRun(UsernamePrincipal user, Policy p, String uuid) - throws UnknownRunException; - - /** - * Obtain the named workflow run. - * - * @param uuid - * The handle for the run. - * @return The workflow instance run. - * @throws UnknownRunException - * If the lookup fails (either because it does not exist or - * because it is not permitted for the user by the policy). - */ - public TavernaRun getRun(String uuid) throws UnknownRunException; - - /** - * List the runs that a particular user may access. - * - * @param user - * Who wants to do the lookup, or <code>null</code> if it is - * being done "by the system" when the full mapping should be - * returned. - * @param p - * The general policy system context. - * @return A mapping from run names to run instances. - */ - Map<String, TavernaRun> listRuns(UsernamePrincipal user, Policy p); - - /** - * Adds a workflow instance run to the store. Note that this operation is - * <i>not</i> expected to be security-checked; that is the callers' - * responsibility. - * - * @param run - * The run itself. - * @return The name of the run. - */ - String registerRun(TavernaRun run); - - /** - * Removes a run from the store. Note that this operation is <i>not</i> - * expected to be security-checked; that is the callers' responsibility. - * - * @param uuid - * The name of the run. - */ - void unregisterRun(String uuid); -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/SecurityContextFactory.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/SecurityContextFactory.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/SecurityContextFactory.java deleted file mode 100644 index 902c4d0..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/SecurityContextFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.interfaces; - -import java.io.Serializable; - -import org.taverna.server.master.utils.UsernamePrincipal; - -/** - * How to create instances of a security context. - * - * @author Donal Fellows - */ -public interface SecurityContextFactory extends Serializable { - /** - * Creates a security context. - * - * @param run - * Handle to remote run. Allows the security context to know how - * to apply itself to the workflow run. - * @param owner - * The identity of the owner of the workflow run. - * @return The security context. - * @throws Exception - * If anything goes wrong. - */ - TavernaSecurityContext create(TavernaRun run, UsernamePrincipal owner) - throws Exception; -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaRun.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaRun.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaRun.java deleted file mode 100644 index 399164d..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaRun.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2010-2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.interfaces; - -import java.io.Serializable; -import java.util.Date; -import java.util.List; - -import org.taverna.server.master.common.Workflow; -import org.taverna.server.master.common.Status; -import org.taverna.server.master.exceptions.BadStateChangeException; -import org.taverna.server.master.exceptions.FilesystemAccessException; -import org.taverna.server.master.exceptions.NoDestroyException; -import org.taverna.server.master.exceptions.UnknownRunException; - -/** - * The interface to a taverna workflow run, or "run" for short. - * - * @author Donal Fellows - */ -public interface TavernaRun extends Serializable { - /** - * @return The identifier of the run. - */ - String getId(); - - /** - * @return What was this run was create to execute. - */ - Workflow getWorkflow(); - - /** - * @return The name of the run. - */ - String getName(); - - /** - * @param name - * The new name of the run. May be truncated. - */ - void setName(String name); - - /** - * @return The name of the Baclava file to use for all inputs, or - * <tt>null</tt> if no Baclava file is set. - */ - String getInputBaclavaFile(); - - /** - * Sets the Baclava file to use for all inputs. This overrides the use of - * individual inputs. - * - * @param filename - * The filename to use. Must not start with a <tt>/</tt> or - * contain any <tt>..</tt> segments. Will be interpreted relative - * to the run's working directory. - * @throws FilesystemAccessException - * If the filename is invalid. - * @throws BadStateChangeException - * If the workflow is not in the {@link Status#Initialized - * Initialized} state. - */ - void setInputBaclavaFile(String filename) throws FilesystemAccessException, - BadStateChangeException; - - /** - * @return The list of input assignments. - */ - List<Input> getInputs(); - - /** - * Create an input assignment. - * - * @param name - * The name of the port that this will be an input for. - * @return The assignment reference. - * @throws BadStateChangeException - * If the workflow is not in the {@link Status#Initialized - * Initialized} state. - */ - Input makeInput(String name) throws BadStateChangeException; - - /** - * @return The file (relative to the working directory) to write the outputs - * of the run to as a Baclava document, or <tt>null</tt> if they are - * to be written to non-Baclava files in a directory called - * <tt>out</tt>. - */ - String getOutputBaclavaFile(); - - /** - * Sets where the output of the run is to be written to. This will cause the - * output to be generated as a Baclava document, rather than a collection of - * individual non-Baclava files in the subdirectory of the working directory - * called <tt>out</tt>. - * - * @param filename - * Where to write the Baclava file (or <tt>null</tt> to cause the - * output to be written to individual files); overwrites any - * previous setting of this value. - * @throws FilesystemAccessException - * If the filename starts with a <tt>/</tt> or contains a - * <tt>..</tt> segment. - * @throws BadStateChangeException - * If the workflow is not in the {@link Status#Initialized - * Initialized} state. - */ - void setOutputBaclavaFile(String filename) - throws FilesystemAccessException, BadStateChangeException; - - /** - * @return When this run will expire, becoming eligible for automated - * deletion. - */ - Date getExpiry(); - - /** - * Set when this run will expire. - * - * @param d - * Expiry time. Deletion will happen some time after that. - */ - void setExpiry(Date d); - - /** - * @return The current status of the run. - */ - Status getStatus(); - - /** - * Set the status of the run, which should cause it to move into the given - * state. This may cause some significant changes. - * - * @param s - * The state to try to change to. - * @return <tt>null</tt>, or a string describing the incomplete state change - * if the operation has internally timed out. - * @throws BadStateChangeException - * If the change to the given state is impossible. - */ - String setStatus(Status s) throws BadStateChangeException; - - /** - * @return Handle to the main working directory of the run. - * @throws FilesystemAccessException - */ - Directory getWorkingDirectory() throws FilesystemAccessException; - - /** - * @return The list of listener instances attached to the run. - */ - List<Listener> getListeners(); - - /** - * Add a listener to the run. - * - * @param listener - * The listener to add. - */ - void addListener(Listener listener); - - /** - * @return The security context structure for this run. - */ - TavernaSecurityContext getSecurityContext(); - - /** - * Kill off this run, removing all resources which it consumes. - * - * @throws NoDestroyException - * If the destruction failed. - */ - void destroy() throws NoDestroyException; - - /** - * @return When this workflow run was created. - */ - Date getCreationTimestamp(); - - /** - * @return When this workflow run was started, or <tt>null</tt> if it has - * never been started. - */ - Date getStartTimestamp(); - - /** - * @return When this workflow run was found to have finished, or - * <tt>null</tt> if it has never finished (either still running or - * never started). - */ - Date getFinishTimestamp(); - - /** - * Test if this run is really there. - * - * <p> - * <i>Implementation note:</i> Used to test communication fabrics, etc. so - * implementations of this interface that do not delegate to another object - * should do nothing. - * - * @throws UnknownRunException - * If things fail. - */ - void ping() throws UnknownRunException; - - /** - * @return whether the run generates provenance data - */ - boolean getGenerateProvenance(); - - /** - * @param generateProvenance - * whether the run generates provenance data - */ - void setGenerateProvenance(boolean generateProvenance); -}
