Java tutorial
/* * Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no * obligations to provide maintenance, support, updates, enhancements or * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be * liable to any party for direct, indirect, special, incidental or * consequential damages, including lost profits, arising out of the use of this * software and its documentation, even if Memorial Sloan-Kettering Cancer * Center has been advised of the possibility of such damage. */ /* * This file is part of cBioPortal. * * cBioPortal is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.mskcc.cbio.portal.util; import org.mskcc.cbio.portal.dao.*; import org.mskcc.cbio.portal.model.*; import org.mskcc.cbio.portal.web_api.ConnectionManager; import org.apache.commons.io.*; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.methods.*; import java.text.SimpleDateFormat; import java.util.Calendar; import java.io.File; import java.net.*; /** * Provides methods for linking to IGV. * * @author Benjamin Gross. */ public class IGVLinking { private static final String TOKEN_REGEX = "<TOKEN>"; private static final String SAMPLE_REGEX = "<SAMPLE_ID>"; private static final String KNOWN_ID = "KNOWN_ID"; private static final String TUMOR_BAM_SIGNATURE = "-Tumor"; private static final String NORMAL_BAM_SIGNATURE = "-Normal"; public static String[] getIGVArgsForSegViewing(String cancerStudyStableId, String encodedGeneList) throws Exception { CancerStudy cancerStudy = DaoCancerStudy.getCancerStudyByStableId(cancerStudyStableId); CopyNumberSegmentFile cnsf = DaoCopyNumberSegmentFile.getCopyNumberSegmentFile(cancerStudy.getInternalId()); return new String[] { GlobalProperties.getSegfileUrl() + cnsf.filename, encodedGeneList, cnsf.referenceGenomeId.toString(), cnsf.filename }; } // returns null if exception has been thrown during processing public static String[] getIGVArgsForBAMViewing(String cancerStudyStableId, String caseId, String locus) { if (!IGVLinking.validBAMViewingArgs(cancerStudyStableId, caseId, locus) || !IGVLinking.encryptionBinLocated()) { return null; } String trackName = caseId; String tumorBAMFileURL = getBAMFileURL(caseId); if (tumorBAMFileURL == null) return null; // code added to view normal alongside tumor file String normalCaseId = getNormalSampleId(caseId); if (normalCaseId != null) { String normalBAMFileURL = getBAMFileURL(normalCaseId); if (normalBAMFileURL != null) { tumorBAMFileURL += "," + normalBAMFileURL; trackName += "," + normalCaseId; } } String encodedLocus = getEncoded(locus); if (encodedLocus == null) return null; return new String[] { tumorBAMFileURL, encodedLocus, CopyNumberSegmentFile.ReferenceGenomeId.hg19.toString(), trackName }; } public static boolean validBAMViewingArgs(String cancerStudy, String caseId, String locus) { return (caseId != null && caseId.length() > 0 && locus != null && locus.length() > 0 && cancerStudy != null && cancerStudy.length() > 0 && bamExists(cancerStudy, caseId)); } public static boolean bamExists(String cancerStudy, String caseId) { return GlobalProperties.getIGVBAMLinkingStudies().contains(cancerStudy) && knownCaseId(caseId); } private static boolean encryptionBinLocated() { return new File(GlobalProperties.getProperty(GlobalProperties.OPENSSL_BINARY)).exists(); } private static String getBAMFileURL(String caseId) { String token = IGVLinking.getToken(caseId); return (token == null) ? null : GlobalProperties.getProperty(GlobalProperties.BROAD_BAM_URL).replace(TOKEN_REGEX, token); } private static String getToken(String caseId) { File messageToEncrypt = null; File token = null; String urlEncodedToken = null; try { messageToEncrypt = getMessageToEncrypt(caseId, IGVLinking.getCurrentTime()); token = IGVLinking.encrypt(messageToEncrypt); urlEncodedToken = IGVLinking.getURLEncodedToken(token); } catch (Exception e) { urlEncodedToken = null; } finally { FileUtils.deleteQuietly(messageToEncrypt); FileUtils.deleteQuietly(token); } return urlEncodedToken; } private static String getCurrentTime() { return Long.toString(Calendar.getInstance().getTime().getTime()); } private static File getMessageToEncrypt(String caseId, String timestamp) throws Exception { File token = FileUtils.getFile(FileUtils.getTempDirectoryPath(), "broad-bam-token.txt"); FileUtils.writeStringToFile(token, timestamp + " " + caseId, "UTF-8", false); return token; } private static String getURLEncodedToken(File token) throws Exception { return URLEncoder.encode(IGVLinking.getFileContents(token), "US-ASCII"); } private static String getFileContents(File file) throws Exception { StringBuilder sb = new StringBuilder(); LineIterator it = null; try { it = FileUtils.lineIterator(file, "UTF-8"); while (it.hasNext()) { sb.append(it.nextLine()); } } finally { if (it != null) it.close(); } return sb.toString(); } private static String getEncoded(String toEncode) { String encoded = null; try { encoded = URLEncoder.encode(toEncode, "US-ASCII"); } catch (Exception e) { } return encoded; } private static File encrypt(File messageToEncrypt) throws Exception { File encryptedMessage = null; File signedMessage = null; File base64Message = null; try { encryptedMessage = IGVLinking.getEncryptedMessage(messageToEncrypt); signedMessage = IGVLinking.getSignedMessage(encryptedMessage); base64Message = IGVLinking.getBase64Message(signedMessage); } catch (Exception e) { FileUtils.deleteQuietly(base64Message); throw e; } finally { FileUtils.deleteQuietly(encryptedMessage); FileUtils.deleteQuietly(signedMessage); } return base64Message; } private static File getEncryptedMessage(File messageToEncrypt) throws Exception { File encryptedMessage = null; try { encryptedMessage = FileUtils.getFile(FileUtils.getTempDirectoryPath(), "broad-bam-encrypted.txt"); IGVLinking.execute(IGVLinking.getEncryptCommand(messageToEncrypt, encryptedMessage)); } catch (Exception e) { FileUtils.deleteQuietly(encryptedMessage); throw e; } return encryptedMessage; } private static String getEncryptCommand(File messageToEncrypt, File encryptedMessage) throws Exception { return (GlobalProperties.getProperty(GlobalProperties.OPENSSL_BINARY) + " rsautl -encrypt" + " -inkey " + GlobalProperties.getProperty(GlobalProperties.ENCRYPTION_KEY) + " -keyform PEM -pubin" + " -in " + messageToEncrypt.getCanonicalPath() + " -out " + encryptedMessage.getCanonicalPath()); } private static File getSignedMessage(File encryptedMessage) throws Exception { File signedMessage = null; try { signedMessage = FileUtils.getFile(FileUtils.getTempDirectoryPath(), "broad-bam-signed-encrypted.txt"); IGVLinking.execute(IGVLinking.getSignCommand(encryptedMessage, signedMessage)); } catch (Exception e) { FileUtils.deleteQuietly(signedMessage); throw e; } return signedMessage; } private static String getSignCommand(File encryptedMessage, File signedMessage) throws Exception { return (GlobalProperties.getProperty(GlobalProperties.OPENSSL_BINARY) + " rsautl -sign" + " -inkey " + GlobalProperties.getProperty(GlobalProperties.SIGNATURE_KEY) + " -keyform PEM" + " -in " + encryptedMessage.getCanonicalPath() + " -out " + signedMessage.getCanonicalPath()); } private static File getBase64Message(File signedMessage) throws Exception { File base64Message = null; try { base64Message = FileUtils.getFile(FileUtils.getTempDirectoryPath(), "broad-bam-base64-signed-encrypted.txt"); IGVLinking.execute(IGVLinking.getBase64Command(signedMessage, base64Message)); } catch (Exception e) { FileUtils.deleteQuietly(base64Message); throw e; } return base64Message; } private static String getBase64Command(File signedMessage, File base64Message) throws Exception { return (GlobalProperties.getProperty(GlobalProperties.OPENSSL_BINARY) + " enc -base64" + " -in " + signedMessage.getCanonicalPath() + " -out " + base64Message.getCanonicalPath()); } private static void execute(String command) throws Exception { Process process = Runtime.getRuntime().exec(command); process.waitFor(); if (process.exitValue() != 0) throw new RuntimeException(); } private static boolean knownCaseId(String caseId) { String url = getBAMCheckingURL(caseId); if (url == null) return false; HttpClient client = getHttpClient(); GetMethod method = new GetMethod(url); try { if (client.executeMethod(method) == HttpStatus.SC_OK) { return processSampleIdCheckResult(method.getResponseBodyAsString()); } } catch (Exception e) { } finally { method.releaseConnection(); } return false; } private static String getBAMCheckingURL(String caseId) { String encodedCaseId = getEncoded(caseId); String url = GlobalProperties.getProperty(GlobalProperties.BROAD_BAM_CHECKING_URL); return (url != null && !url.isEmpty() && encodedCaseId != null) ? url.replace(SAMPLE_REGEX, encodedCaseId) : null; } private static HttpClient getHttpClient() { MultiThreadedHttpConnectionManager connectionManager = ConnectionManager.getConnectionManager(); return new HttpClient(connectionManager); } private static boolean processSampleIdCheckResult(String responseBody) { return (responseBody.equalsIgnoreCase(KNOWN_ID)); } private static String getNormalSampleId(String tumorSampleId) { // most normal id's are simply the tumorSampleId with "Normal" replaced with "Tumor" String normalId = tumorSampleId.replace(TUMOR_BAM_SIGNATURE, NORMAL_BAM_SIGNATURE); if (knownCaseId(normalId)) return normalId; // in some cases, we need to truncate everything // following & including "Tumor" and replace with "Normal" String tumorSampleIdPrefix = getTumorSampleIdPrefix(tumorSampleId); if (tumorSampleIdPrefix != null) { String encodedTumorSampleId = getEncoded(tumorSampleIdPrefix + NORMAL_BAM_SIGNATURE); if (encodedTumorSampleId != null && knownCaseId(encodedTumorSampleId)) { return tumorSampleIdPrefix + NORMAL_BAM_SIGNATURE; } } return null; } private static String getTumorSampleIdPrefix(String tumorSampleId) { int tumorSignatureIndex = tumorSampleId.indexOf(TUMOR_BAM_SIGNATURE); return (tumorSignatureIndex > 0) ? tumorSampleId.substring(0, tumorSignatureIndex) : null; } }