| /* |
| */ |
| package org.taverna.server.master.worker; |
| |
| import static java.util.Arrays.asList; |
| import static java.util.Collections.emptyList; |
| import static org.taverna.server.master.worker.RunConnection.COUNT_QUERY; |
| import static org.taverna.server.master.worker.RunConnection.NAMES_QUERY; |
| import static org.taverna.server.master.worker.RunConnection.SCHEMA; |
| import static org.taverna.server.master.worker.RunConnection.TABLE; |
| import static org.taverna.server.master.worker.RunConnection.TIMEOUT_QUERY; |
| import static org.taverna.server.master.worker.RunConnection.UNTERMINATED_QUERY; |
| |
| import java.io.IOException; |
| import java.rmi.MarshalledObject; |
| import java.util.Date; |
| import java.util.HashSet; |
| import java.util.List; |
| |
| import javax.annotation.Nonnull; |
| import javax.jdo.annotations.Column; |
| import javax.jdo.annotations.Join; |
| import javax.jdo.annotations.PersistenceCapable; |
| import javax.jdo.annotations.Persistent; |
| import javax.jdo.annotations.PrimaryKey; |
| import javax.jdo.annotations.Queries; |
| import javax.jdo.annotations.Query; |
| |
| import org.taverna.server.localworker.remote.RemoteSingleRun; |
| import org.taverna.server.master.common.Credential; |
| import org.taverna.server.master.common.Trust; |
| import org.taverna.server.master.common.Workflow; |
| import org.taverna.server.master.interfaces.SecurityContextFactory; |
| import org.taverna.server.master.utils.UsernamePrincipal; |
| |
| /** |
| * The representation of the connections to the runs that actually participates |
| * in the persistence system. |
| * |
| * @author Donal Fellows |
| */ |
| @PersistenceCapable(table = TABLE, schema = SCHEMA) |
| @Queries({ |
| @Query(name = "count", language = "SQL", value = COUNT_QUERY, unique = "true", resultClass = Integer.class), |
| @Query(name = "names", language = "SQL", value = NAMES_QUERY, unique = "false", resultClass = String.class), |
| @Query(name = "unterminated", language = "SQL", value = UNTERMINATED_QUERY, unique = "false", resultClass = String.class), |
| @Query(name = "timedout", language = "SQL", value = TIMEOUT_QUERY, unique = "false", resultClass = String.class) }) |
| public class RunConnection { |
| static final String SCHEMA = "TAVERNA"; |
| static final String TABLE = "RUN_CONNECTION"; |
| private static final String FULL_NAME = SCHEMA + "." + TABLE; |
| static final String COUNT_QUERY = "SELECT count(*) FROM " + FULL_NAME; |
| static final String NAMES_QUERY = "SELECT ID FROM " + FULL_NAME; |
| static final String TIMEOUT_QUERY = "SELECT ID FROM " + FULL_NAME |
| + " WHERE expiry < CURRENT_TIMESTAMP"; |
| static final String UNTERMINATED_QUERY = "SELECT ID FROM " + FULL_NAME |
| + " WHERE doneTransitionToFinished = 0"; |
| static final int NAME_LENGTH = 48; |
| |
| @PrimaryKey |
| @Column(length = 40) |
| private String id; |
| |
| @Persistent(defaultFetchGroup = "true") |
| @Column(length = NAME_LENGTH) |
| private String name; |
| |
| @Persistent(defaultFetchGroup = "true") |
| private Date creationInstant; |
| |
| @Persistent(defaultFetchGroup = "true", serialized = "true") |
| @Column(jdbcType = "BLOB", sqlType = "BLOB") |
| private Workflow workflow; |
| |
| @Persistent(defaultFetchGroup = "true") |
| private Date expiry; |
| |
| @Persistent(defaultFetchGroup = "true") |
| @Join(table = TABLE + "_READERS", column = "ID") |
| private String[] readers; |
| |
| @Persistent(defaultFetchGroup = "true") |
| @Join(table = TABLE + "_WRITERS", column = "ID") |
| private String[] writers; |
| |
| @Persistent(defaultFetchGroup = "true") |
| @Join(table = TABLE + "_DESTROYERS", column = "ID") |
| private String[] destroyers; |
| |
| @Persistent(defaultFetchGroup = "true", serialized = "true") |
| @Column(jdbcType = "BLOB", sqlType = "BLOB") |
| private MarshalledObject<RemoteSingleRun> run; |
| |
| @Persistent(defaultFetchGroup = "true") |
| private int doneTransitionToFinished; |
| |
| @Persistent(defaultFetchGroup = "true") |
| private int generateProvenance; |
| |
| @Persistent(defaultFetchGroup = "true") |
| @Column(length = 128) |
| String owner; |
| |
| @Persistent(defaultFetchGroup = "true") |
| @Column(length = 36) |
| private String securityToken; |
| |
| @Persistent(defaultFetchGroup = "true", serialized = "true") |
| @Column(jdbcType = "BLOB", sqlType = "BLOB") |
| private SecurityContextFactory securityContextFactory; |
| @Persistent(defaultFetchGroup = "true", serialized = "true") |
| @Column(jdbcType = "BLOB", sqlType = "BLOB") |
| private Credential[] credentials; |
| @Persistent(defaultFetchGroup = "true", serialized = "true") |
| @Column(jdbcType = "BLOB", sqlType = "BLOB") |
| private Trust[] trust; |
| |
| private static final String[] STRING_ARY = new String[0]; |
| |
| public String getId() { |
| return id; |
| } |
| |
| public boolean isFinished() { |
| return doneTransitionToFinished != 0; |
| } |
| |
| public void setFinished(boolean finished) { |
| doneTransitionToFinished = (finished ? 1 : 0); |
| } |
| |
| public boolean isProvenanceGenerated() { |
| return generateProvenance != 0; |
| } |
| |
| public void setProvenanceGenerated(boolean generate) { |
| generateProvenance = (generate ? 1 : 0); |
| } |
| |
| /** |
| * Manufacture a persistent representation of the given workflow run. Must |
| * be called within the context of a transaction. |
| * |
| * @param rrd |
| * The remote delegate of the workflow run. |
| * @return The persistent object. |
| * @throws IOException |
| * If serialisation fails. |
| */ |
| @Nonnull |
| public static RunConnection toDBform(@Nonnull RemoteRunDelegate rrd) |
| throws IOException { |
| RunConnection rc = new RunConnection(); |
| rc.id = rrd.id; |
| rc.makeChanges(rrd); |
| return rc; |
| } |
| |
| private static List<String> list(String[] ary) { |
| if (ary == null) |
| return emptyList(); |
| return asList(ary); |
| } |
| |
| /** |
| * Get the remote run delegate for a particular persistent connection. Must |
| * be called within the context of a transaction. |
| * |
| * @param db |
| * The database facade. |
| * @return The delegate object. |
| * @throws Exception |
| * If anything goes wrong. |
| */ |
| @Nonnull |
| public RemoteRunDelegate fromDBform(@Nonnull RunDBSupport db) |
| throws Exception { |
| RemoteRunDelegate rrd = new RemoteRunDelegate(); |
| rrd.id = getId(); |
| rrd.creationInstant = creationInstant; |
| rrd.workflow = workflow; |
| rrd.expiry = expiry; |
| rrd.readers = new HashSet<>(list(readers)); |
| rrd.writers = new HashSet<>(list(writers)); |
| rrd.destroyers = new HashSet<>(list(destroyers)); |
| rrd.run = run.get(); |
| rrd.doneTransitionToFinished = isFinished(); |
| rrd.generateProvenance = isProvenanceGenerated(); |
| rrd.secContext = securityContextFactory.create(rrd, |
| new UsernamePrincipal(owner)); |
| ((SecurityContextDelegate)rrd.secContext).setCredentialsAndTrust(credentials,trust); |
| rrd.db = db; |
| rrd.factory = db.getFactory(); |
| rrd.name = name; |
| return rrd; |
| } |
| |
| /** |
| * Flush changes from a remote run delegate to the database. Must be called |
| * within the context of a transaction. |
| * |
| * @param rrd |
| * The remote run delegate object that has potential changes. |
| * @throws IOException |
| * If anything goes wrong in serialization. |
| */ |
| public void makeChanges(@Nonnull RemoteRunDelegate rrd) throws IOException { |
| // Properties that are set exactly once |
| if (creationInstant == null) { |
| creationInstant = rrd.getCreationTimestamp(); |
| workflow = rrd.getWorkflow(); |
| run = new MarshalledObject<>(rrd.run); |
| securityContextFactory = rrd.getSecurityContext().getFactory(); |
| owner = rrd.getSecurityContext().getOwner().getName(); |
| securityToken = ((org.taverna.server.master.worker.SecurityContextFactory) securityContextFactory) |
| .issueNewPassword(); |
| } |
| // Properties that are set multiple times |
| expiry = rrd.getExpiry(); |
| readers = rrd.getReaders().toArray(STRING_ARY); |
| writers = rrd.getWriters().toArray(STRING_ARY); |
| destroyers = rrd.getDestroyers().toArray(STRING_ARY); |
| credentials = rrd.getSecurityContext().getCredentials(); |
| trust = rrd.getSecurityContext().getTrusted(); |
| if (rrd.name.length() > NAME_LENGTH) |
| this.name = rrd.name.substring(0, NAME_LENGTH); |
| else |
| this.name = rrd.name; |
| setFinished(rrd.doneTransitionToFinished); |
| setProvenanceGenerated(rrd.generateProvenance); |
| } |
| |
| public String getSecurityToken() { |
| return securityToken; |
| } |
| } |