-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a44c127
commit 4c6f923
Showing
26 changed files
with
1,327 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,4 +22,7 @@ | |
/nbbuild/ | ||
/dist/ | ||
/nbdist/ | ||
/.nb-gradle/ | ||
/.nb-gradle/ | ||
|
||
/application.properties | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 123 additions & 0 deletions
123
src/main/java/com/jacobsonmt/idrbind/controllers/JobController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
package com.jacobsonmt.idrbind.controllers; | ||
|
||
import com.jacobsonmt.idrbind.model.IDRBindJob; | ||
import com.jacobsonmt.idrbind.model.IDRBindJobResult; | ||
import com.jacobsonmt.idrbind.services.JobManager; | ||
import lombok.extern.log4j.Log4j2; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.stereotype.Controller; | ||
import org.springframework.ui.Model; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.multipart.MultipartFile; | ||
import org.springframework.web.servlet.mvc.support.RedirectAttributes; | ||
|
||
import javax.servlet.http.HttpServletRequest; | ||
import java.io.IOException; | ||
import java.util.concurrent.ExecutionException; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.concurrent.TimeoutException; | ||
|
||
@Log4j2 | ||
@Controller | ||
public class JobController { | ||
|
||
@Autowired | ||
private JobManager jobManager; | ||
|
||
|
||
|
||
@PostMapping("/") | ||
public String handleFileUpload(@RequestParam("pdbFile") MultipartFile pdbFile, | ||
@RequestParam("sequence") MultipartFile sequence, | ||
@RequestParam("label") String label, | ||
@RequestParam(value = "email", required = false, defaultValue = "") String email, | ||
@RequestParam(value = "hidden", required = false, defaultValue = "false") boolean hidden, | ||
HttpServletRequest request, | ||
RedirectAttributes redirectAttributes) throws IOException { | ||
|
||
String ipAddress = request.getHeader( "X-FORWARDED-FOR" ); | ||
if ( ipAddress == null ) { | ||
ipAddress = request.getRemoteAddr(); | ||
} | ||
|
||
IDRBindJob job = jobManager.createJob( ipAddress, | ||
label, | ||
IDRBindJob.inputStreamToString( pdbFile.getInputStream() ), | ||
IDRBindJob.inputStreamToString( sequence.getInputStream() ), | ||
email, | ||
hidden ); | ||
jobManager.submit( job ); | ||
|
||
redirectAttributes.addFlashAttribute("message", | ||
"Job Submitted! View job <a href='job/" + job.getJobId() + "' target='_blank'>here</a>."); | ||
|
||
return "redirect:/"; | ||
} | ||
|
||
@GetMapping("/job/{jobId}") | ||
public String job( @PathVariable("jobId") String jobId, | ||
Model model) throws IOException { | ||
|
||
IDRBindJob job = jobManager.getSavedJob( jobId ); | ||
|
||
if (job==null) { | ||
return "/"; | ||
} | ||
|
||
model.addAttribute("job", jobManager.getSavedJob( jobId ).toValueObject( true ) ); | ||
|
||
return "job"; | ||
} | ||
|
||
@GetMapping("/job/{jobId}/resultPDB") | ||
public ResponseEntity<String> jobResultPDB( @PathVariable("jobId") String jobId) { | ||
IDRBindJob job = jobManager.getSavedJob( jobId ); | ||
|
||
// test for not null and complete | ||
if ( job != null && job.isComplete() && !job.isFailed() ) { | ||
try { | ||
IDRBindJobResult result = job.getFuture().get( 1, TimeUnit.SECONDS ); | ||
|
||
return ResponseEntity.ok() | ||
.contentType( MediaType.parseMediaType("application/octet-stream")) | ||
.header( HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + job.getLabel() + "-result.pdb\"") | ||
.body(result.getResultPDB()); | ||
|
||
} catch ( InterruptedException | ExecutionException | TimeoutException e ) { | ||
log.warn( e ); | ||
ResponseEntity.status( 500 ).body( "" ); | ||
} | ||
} | ||
return ResponseEntity.badRequest().body( "" ); | ||
} | ||
|
||
@GetMapping("/job/{jobId}/resultCSV") | ||
public ResponseEntity<String> jobResultCSV( @PathVariable("jobId") String jobId) { | ||
IDRBindJob job = jobManager.getSavedJob( jobId ); | ||
|
||
// test for not null and complete | ||
if ( job != null && job.isComplete() && !job.isFailed() ) { | ||
try { | ||
IDRBindJobResult result = job.getFuture().get( 1, TimeUnit.SECONDS ); | ||
|
||
return ResponseEntity.ok() | ||
.contentType( MediaType.parseMediaType("application/octet-stream")) | ||
.header( HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + job.getLabel() + "-result.csv\"") | ||
.body(result.getResultCSV()); | ||
|
||
} catch ( InterruptedException | ExecutionException | TimeoutException e ) { | ||
log.warn( e ); | ||
ResponseEntity.status( 500 ).body( "" ); | ||
} | ||
} | ||
return ResponseEntity.badRequest().body( "" ); | ||
} | ||
|
||
|
||
} |
47 changes: 47 additions & 0 deletions
47
src/main/java/com/jacobsonmt/idrbind/controllers/MainController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package com.jacobsonmt.idrbind.controllers; | ||
|
||
import com.jacobsonmt.idrbind.services.JobManager; | ||
import lombok.extern.log4j.Log4j2; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.stereotype.Controller; | ||
import org.springframework.ui.Model; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
|
||
import java.io.IOException; | ||
|
||
@Log4j2 | ||
@Controller | ||
public class MainController { | ||
|
||
@Autowired | ||
private JobManager jobManager; | ||
|
||
@GetMapping("/") | ||
public String index( Model model) throws IOException { | ||
|
||
return "index"; | ||
} | ||
|
||
@GetMapping("/queue") | ||
public String queue( Model model) throws IOException { | ||
|
||
model.addAttribute("jobs", jobManager.listPublicJobs() ); | ||
|
||
return "queue"; | ||
} | ||
|
||
@GetMapping("/documentation") | ||
public String documentation( Model model) throws IOException { | ||
return "documentation"; | ||
} | ||
|
||
@GetMapping("/faq") | ||
public String faq( Model model) throws IOException { | ||
return "faq"; | ||
} | ||
|
||
@GetMapping("/contact") | ||
public String contact( Model model) throws IOException { | ||
return "contact"; | ||
} | ||
} |
194 changes: 194 additions & 0 deletions
194
src/main/java/com/jacobsonmt/idrbind/model/IDRBindJob.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
package com.jacobsonmt.idrbind.model; | ||
|
||
import com.jacobsonmt.idrbind.services.JobManager; | ||
import lombok.*; | ||
import lombok.extern.log4j.Log4j2; | ||
import org.springframework.util.StopWatch; | ||
|
||
import javax.ws.rs.core.StreamingOutput; | ||
import java.io.*; | ||
import java.nio.charset.Charset; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.Date; | ||
import java.util.concurrent.*; | ||
|
||
@Log4j2 | ||
@Getter | ||
@Setter | ||
@Builder | ||
@ToString(of = {"jobId", "userId", "label", "hidden"}) | ||
@EqualsAndHashCode(of = {"jobId"}) | ||
public class IDRBindJob implements Callable<IDRBindJobResult> { | ||
|
||
// Path to resources | ||
private String command; | ||
private String commandWorkingDirectory; | ||
private String inputPDBFullPath; | ||
private String inputProteinChainFullPath; | ||
private String outputScoredPDBFullPath; | ||
private String outputCSVFullPath; | ||
|
||
|
||
// Information on creation of job | ||
private String userId; | ||
private String jobId; | ||
private String label; | ||
private String inputPDBContent; | ||
private String inputProteinChainIds; | ||
@Builder.Default private boolean hidden = true; | ||
private Date submittedDate; | ||
private String email; | ||
|
||
// Information on running / completion | ||
@Builder.Default private boolean running = false; | ||
@Builder.Default private boolean failed = false; | ||
@Builder.Default private boolean complete = false; | ||
private Integer position; | ||
private String status; | ||
|
||
// Results | ||
private Future<IDRBindJobResult> future; | ||
private StreamingOutput resultFile; | ||
private long executionTime; | ||
|
||
// Saving Job information / results for later | ||
@Builder.Default private boolean saved = false; | ||
private Long saveExpiredDate; | ||
|
||
// Back-reference to owning JobManager | ||
private JobManager jobManager; | ||
|
||
@Override | ||
public IDRBindJobResult call() throws Exception { | ||
|
||
try { | ||
|
||
log.info( "Starting job (" + label + ") for user: (" + userId + ")" ); | ||
|
||
this.running = true; | ||
this.status = "Processing"; | ||
|
||
jobManager.onJobStart( this ); | ||
|
||
// Write content to input | ||
File pdbFile = new File( inputPDBFullPath ); | ||
writeToFile( pdbFile, inputPDBContent ); | ||
|
||
File chainFile = new File( inputProteinChainFullPath ); | ||
writeToFile( chainFile, inputProteinChainIds ); | ||
|
||
// Execute script | ||
StopWatch sw = new StopWatch(); | ||
sw.start(); | ||
executeCommand( "./" + command, commandWorkingDirectory ); | ||
sw.stop(); | ||
this.executionTime = sw.getTotalTimeMillis() / 1000; | ||
|
||
// Get output | ||
String resultPDB = inputStreamToString( new FileInputStream( outputScoredPDBFullPath ) ); | ||
String resultCSV = inputStreamToString( new FileInputStream( outputCSVFullPath ) ); | ||
|
||
log.info( "Finished job (" + label + ") for user: (" + userId + ")" ); | ||
this.running = false; | ||
this.complete = true; | ||
|
||
jobManager.onJobComplete( this ); | ||
jobManager = null; | ||
|
||
return new IDRBindJobResult( resultPDB, resultCSV ); | ||
} catch ( Exception e ) { | ||
log.error( e ); | ||
this.complete = true; | ||
this.running = false; | ||
this.failed = true; | ||
jobManager = null; | ||
this.status = "Failed"; | ||
return new IDRBindJobResult( "", "" ); | ||
} | ||
|
||
} | ||
|
||
private static void writeToFile(File file, String fileContents) throws IOException { | ||
|
||
try (FileOutputStream fop = new FileOutputStream( file )) { | ||
|
||
// if file doesn't exists, then create it | ||
if (!file.exists()) { | ||
file.createNewFile(); | ||
} | ||
|
||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fop)); | ||
writer.write(fileContents); | ||
writer.newLine(); | ||
writer.flush(); | ||
writer.close(); | ||
|
||
} | ||
|
||
} | ||
|
||
private static String executeCommand( String command, String path ) { | ||
|
||
StringBuffer output = new StringBuffer(); | ||
|
||
Process p; | ||
try { | ||
p = Runtime.getRuntime().exec( command, null, new File( path ) ); | ||
p.waitFor(); | ||
BufferedReader reader = new BufferedReader( new InputStreamReader( p.getInputStream() ) ); | ||
|
||
String line = ""; | ||
while ( ( line = reader.readLine() ) != null ) { | ||
output.append( line + "\r\n" ); | ||
} | ||
|
||
} catch ( Exception e ) { | ||
e.printStackTrace(); | ||
} | ||
|
||
return output.toString(); | ||
} | ||
|
||
public static String inputStreamToString(InputStream inputStream) throws IOException { | ||
StringBuilder textBuilder = new StringBuilder(); | ||
try (Reader reader = new BufferedReader(new InputStreamReader | ||
(inputStream, Charset.forName(StandardCharsets.UTF_8.name())))) { | ||
int c = 0; | ||
while ((c = reader.read()) != -1) { | ||
textBuilder.append((char) c); | ||
} | ||
} | ||
return textBuilder.toString(); | ||
} | ||
|
||
@Getter | ||
@AllArgsConstructor | ||
public static final class IDRBindJobVO { | ||
private final String jobId; | ||
private final String label; | ||
private final String status; | ||
private final boolean running; | ||
private final boolean failed; | ||
private final boolean complete; | ||
private Integer position; | ||
private final String email; | ||
private final boolean hidden; | ||
private final Date submitted; | ||
private final IDRBindJobResult result; | ||
} | ||
|
||
public IDRBindJobVO toValueObject(boolean obfuscateEmail) { | ||
|
||
IDRBindJobResult result = null; | ||
if ( this.isComplete() ) { | ||
try { | ||
result = this.getFuture().get( 1, TimeUnit.SECONDS ); | ||
} catch ( InterruptedException | ExecutionException | TimeoutException e ) { | ||
log.error( e ); | ||
} | ||
} | ||
|
||
return new IDRBindJobVO( jobId, label, status, running, failed, complete, position, obfuscateEmail ? email.replaceAll("(\\w{0,3})(\\w+.*)(@.*)", "$1****$3") : email, hidden, submittedDate, result ); | ||
} | ||
|
||
} |
Oops, something went wrong.