/************************************************************************** OmegaT - Computer Assisted Translation (CAT) tool with fuzzy matching, translation memory, keyword search, glossaries, and translation leveraging into updated projects. Copyright (C) 2014 Alex Buloichik, Didier Briel Home page: http://www.omegat.org/ Support center: http://groups.yahoo.com/group/OmegaT/ This file is part of OmegaT. OmegaT is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OmegaT 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. **************************************************************************/ package org.omegat.gui.glossary.taas; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.StringReader; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.List; import java.util.logging.Logger; import javax.xml.bind.JAXBContext; import org.apache.commons.io.IOUtils; import org.omegat.util.CredentialsManager; import org.omegat.util.Language; import org.omegat.util.Log; import org.omegat.util.OStrings; import org.omegat.util.StringUtil; import gen.taas.TaasArrayOfTerm; import gen.taas.TaasCollection; import gen.taas.TaasCollections; import gen.taas.TaasDomain; import gen.taas.TaasDomains; import gen.taas.TaasExtractionResult; import gen.taas.TaasTerm; /** * Client for TaaS REST service. * * @author Alex Buloichik (alex73mail@gmail.com) */ @SuppressWarnings("serial") public class TaaSClient { private static final Logger LOGGER = Logger.getLogger(TaaSClient.class.getName()); private static final String PROPERTY_API_KEY = "taas.user.key"; public static final String WS_URL = "https://api.taas-project.eu"; /** Machine user name */ public static final String M_USERNAME = "OmegaT"; /** Machine password */ public static final String M_PASSWORD = "Ts1DW4^UpE"; private static final String BASIC_AUTH = "Basic " + Base64.getMimeEncoder() .encodeToString((M_USERNAME + ":" + M_PASSWORD).getBytes(StandardCharsets.ISO_8859_1)); /** * 1-statistical terminology annotation, 2- statistical terminology annotation with references to * terminology entries, 4- Terminology DB based terminology annotation (fast) */ public static final String EXTRACTION_METHOD = "4"; private JAXBContext context; private String taasUserKey; public void init() throws Exception { loadApiKey(); if (isAllowed()) { initContext(); } } public String getApiKey() { return taasUserKey; } private void loadApiKey() { String property = System.getProperty(PROPERTY_API_KEY); if (!StringUtil.isEmpty(property)) { taasUserKey = property; } else { taasUserKey = CredentialsManager.getInstance().retrieve(PROPERTY_API_KEY).orElse(""); } } public void setApiKey(String key, boolean temporary) throws Exception { taasUserKey = key; storeApiKey(key, temporary); if (isAllowed()) { initContext(); } } private void storeApiKey(String key, boolean temporary) { System.setProperty(PROPERTY_API_KEY, key); CredentialsManager.getInstance().store(PROPERTY_API_KEY, temporary ? "" : key); } public boolean isApiKeyStoredTemporarily() { return !CredentialsManager.getInstance().isStored(PROPERTY_API_KEY) && !System.getProperty(PROPERTY_API_KEY, "").isEmpty(); } private void initContext() throws Exception { if (context == null) { context = JAXBContext.newInstance(TaasCollections.class, TaasArrayOfTerm.class, TaasExtractionResult.class, TaasDomains.class); } } public boolean isAllowed() { return !StringUtil.isEmpty(taasUserKey); } /** * Request specified URL and check response code. */ HttpURLConnection requestGet(String url) throws IOException, Unauthorized, FormatError { Log.logInfoRB("TAAS_REQUEST", url); HttpURLConnection conn; conn = (HttpURLConnection) new URL(url).openConnection(); conn.setRequestProperty("Authorization", BASIC_AUTH); if (!StringUtil.isEmpty(taasUserKey)) { conn.setRequestProperty("TaaS-User-Key", taasUserKey); } conn.setRequestProperty("Accept", "text/xml"); if (conn.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) { throw new Unauthorized(); } if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) { throw new FormatError(conn.getResponseCode() + " " + conn.getResponseMessage()); } return conn; } /** * Request specified URL and check response code. */ HttpURLConnection requestPost(String url, String body) throws IOException, Unauthorized, FormatError { Log.logInfoRB("TAAS_REQUEST", url); HttpURLConnection conn; conn = (HttpURLConnection) new URL(url).openConnection(); conn.setRequestProperty("Authorization", BASIC_AUTH); if (taasUserKey != null) { conn.setRequestProperty("TaaS-User-Key", taasUserKey); } conn.setRequestProperty("Accept", "text/xml"); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "text/plain");// ; charset=UTF-8 conn.setDoOutput(true); OutputStream out = conn.getOutputStream(); try { out.write(body.getBytes(StandardCharsets.UTF_8)); } finally { out.close(); } if (conn.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) { throw new Unauthorized(); } if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) { throw new FormatError(conn.getResponseCode() + " " + conn.getResponseMessage()); } return conn; } /** * Check content type of response. */ void checkXMLContentType(HttpURLConnection conn) throws FormatError { String contentType = conn.getHeaderField("Content-Type"); if (contentType == null) { throw new FormatError("Empty Content-Type header"); } String ct = contentType.replace(" ", "").toLowerCase(); if (!"text/xml".equals(ct) && !"application/xml".equals(ct)) { throw new FormatError("Wrong Content-Type header: " + contentType); } } /** * Check content type of response. */ void checkXMLUTF8ContentType(HttpURLConnection conn) throws FormatError { String contentType = conn.getHeaderField("Content-Type"); if (contentType == null) { throw new FormatError("Empty Content-Type header"); } String ct = contentType.replace(" ", "").toLowerCase(); if (!"text/xml;charset=utf-8".equals(ct) && !"application/xml;charset=utf-8".equals(ct)) { throw new FormatError("Wrong Content-Type header: " + contentType); } } /** * Read content as UTF-8 string. */ String readUTF8(HttpURLConnection conn) throws IOException { InputStream in = conn.getInputStream(); try { return IOUtils.toString(in, StandardCharsets.UTF_8); } finally { in.close(); } } /** * Get a List of Collections. */ List<TaasCollection> getCollectionsList() throws IOException, Unauthorized, FormatError { HttpURLConnection conn = requestGet(WS_URL + "/collections"); checkXMLUTF8ContentType(conn); String data = readUTF8(conn); TaasCollections result; try { result = (TaasCollections) context.createUnmarshaller().unmarshal(new StringReader(data)); } catch (Exception ex) { throw new FormatError("Wrong content: " + ex.getMessage()); } Log.logDebug(LOGGER, "getCollectionsList() returns {0} collections", result.getCollection().size()); return result.getCollection(); } /** * Get a List of Domains. */ List<TaasDomain> getDomainsList() throws IOException, Unauthorized, FormatError { HttpURLConnection conn = requestGet(WS_URL + "/domains"); checkXMLUTF8ContentType(conn); String data = readUTF8(conn); TaasDomains result; try { result = (TaasDomains) context.createUnmarshaller().unmarshal(new StringReader(data)); } catch (Exception ex) { throw new FormatError("Wrong content: " + ex.getMessage()); } Log.logDebug(LOGGER, "getDomainsList() returns {0} domains", result.getDomain().size()); return result.getDomain(); } /** * Download specific collection into file. */ void downloadCollection(long collectionId, File outFile) throws Exception { HttpURLConnection conn = requestGet(WS_URL + "/collections/" + collectionId); checkXMLContentType(conn); InputStream in = conn.getInputStream(); try { OutputStream out = new BufferedOutputStream(new FileOutputStream(outFile)); try { TaaSPlugin.filterTaasResult(in, out); } finally { out.close(); } } finally { in.close(); } Log.logDebug(LOGGER, "Collection {0} downloaded", collectionId); } /** * Look ups translation for given term. */ List<TaasTerm> termLookup(Language sourceLang, Language targetLang, String term) throws IOException, Unauthorized, FormatError { HttpURLConnection conn = requestGet(WS_URL + "/lookup/" + sourceLang.getLanguageCode().toLowerCase() + "/" + URLEncoder.encode(term, "UTF-8") + "?targetLang=" + targetLang.getLanguageCode().toLowerCase()); checkXMLUTF8ContentType(conn); String data = readUTF8(conn); TaasArrayOfTerm result; try { result = (TaasArrayOfTerm) context.createUnmarshaller().unmarshal(new StringReader(data)); } catch (Exception ex) { throw new FormatError("Wrong content: " + ex.getMessage()); } Log.logDebug(LOGGER, "termLookup returns {0} results", result.getTerm().size()); return result.getTerm(); } /** * Term Extraction method. Domain can be null for request all domains. */ TaasExtractionResult termExtraction(Language sourceLang, Language targetLang, String text, String domain) throws IOException, Unauthorized, FormatError { StringBuilder r = new StringBuilder(); r.append(WS_URL).append("/extraction/"); r.append("?sourceLang=").append(sourceLang.getLanguageCode().toLowerCase()); r.append("&targetLang=").append(targetLang.getLanguageCode().toLowerCase()); r.append("&method=").append(EXTRACTION_METHOD); if (!StringUtil.isEmpty(domain)) { r.append("&domain=").append(URLEncoder.encode(domain, "UTF-8")); } HttpURLConnection conn = requestPost(r.toString(), text); checkXMLUTF8ContentType(conn); String data = readUTF8(conn); TaasExtractionResult result; try { result = (TaasExtractionResult) context.createUnmarshaller().unmarshal(new StringReader(data)); } catch (Exception ex) { throw new FormatError("Wrong content: " + ex.getMessage()); } Log.logDebug(LOGGER, "termExtraction returns data"); return result; } public static class Unauthorized extends Exception { public Unauthorized() { super(OStrings.getString("TAAS_UNAUTHORIZED_ERROR")); } } public static class FormatError extends Exception { public FormatError(String text) { super(text); } } }