Commit befc0ebd authored by Philip Makedonski's avatar Philip Makedonski
Browse files

+ first attempt at a protocol server client, #48, #45, #6, #2

parent ae209564
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -11,7 +11,8 @@ Require-Bundle: org.eclipse.xtext,
 org.eclipse.osgi,
 org.eclipse.core.resources,
 org.eclipse.emf.common,
 org.eclipse.xtext.xbase
 org.eclipse.xtext.xbase,
 com.google.gson
Export-Package: org.etsi.mts.tdl,
 org.etsi.mts.tdl.resources,
 org.etsi.mts.tdl.scoping,
+177 −0
Original line number Diff line number Diff line
package org.etsi.mts.tdl.transform;
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.*;


public class HttpFileClient {
    
    private static final String CRLF = "\r\n";
    private static final String BOUNDARY = "----WebKitFormBoundary" + System.currentTimeMillis();
    
    /**
     * Response container holding the JSON data and additional metadata
     */
    public static class ApiResponse {
        private final String jsonBody;
        private final int statusCode;
        private final Map<String, List<String>> headers;
        
        public ApiResponse(String jsonBody, int statusCode, Map<String, List<String>> headers) {
            this.jsonBody = jsonBody;
            this.statusCode = statusCode;
            this.headers = headers;
        }
        
        public String getJsonBody() { return jsonBody; }
        public int getStatusCode() { return statusCode; }
        public Map<String, List<String>> getHeaders() { return headers; }
        public String getHeader(String name) {
            List<String> values = headers.get(name);
            return values != null && !values.isEmpty() ? values.get(0) : null;
        }
    }
    
    /**
     * Upload one or more files via POST to the specified URL
     * 
     * @param url API endpoint URL
     * @param files Map of field names to file paths
     * @param additionalFields Optional text fields to include in the request
     * @return ApiResponse containing JSON and metadata
     */
    public static ApiResponse uploadFiles(String url, Map<String, Path> files, 
                                         Map<String, String> additionalFields) throws IOException {
        log("CLIENT: Starting upload to " + url);
        URL apiUrl = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) apiUrl.openConnection();
        
        try {
            // Configure connection
            log("CLIENT: Configuring connection");
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
            conn.setRequestProperty("Accept", "application/json");
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setChunkedStreamingMode(8192); // Use chunked mode to avoid hanging
            
            log("CLIENT: Getting output stream");
            // Write multipart request body
            try (OutputStream out = conn.getOutputStream()) {
                log("CLIENT: Got output stream, writing data");
                
                // Add additional text fields if provided
                if (additionalFields != null) {
                    for (Map.Entry<String, String> field : additionalFields.entrySet()) {
                        log("CLIENT: Writing field: " + field.getKey());
                        writeField(out, field.getKey(), field.getValue());
                    }
                }
                
                // Add files
                for (Map.Entry<String, Path> file : files.entrySet()) {
                    log("CLIENT: Writing file: " + file.getValue().getFileName());
//                    writeFile(out, file.getKey(), file.getValue());
                    writeFile(out, "files[]", file.getValue());
                }
                
                // End multipart request
                log("CLIENT: Writing end boundary");
                String endBoundary = "--" + BOUNDARY + "--" + CRLF;
                out.write(endBoundary.getBytes(StandardCharsets.UTF_8));
                out.flush();
                log("CLIENT: Finished writing request body");
            }
            
            // Read response
            log("CLIENT: Getting response code");
            int statusCode = conn.getResponseCode();
            log("CLIENT: Response code: " + statusCode);
            InputStream responseStream = statusCode >= 400 ? conn.getErrorStream() : conn.getInputStream();
            
            String jsonResponse = readInputStream(responseStream);
//            log("CLIENT: Got response: " + jsonResponse);
            Map<String, List<String>> headers = conn.getHeaderFields();
            
            return new ApiResponse(jsonResponse, statusCode, headers);
            
        } finally {
            conn.disconnect();
        }
    }
    
    private static void writeField(OutputStream out, String name, String value) throws IOException {
        StringBuilder sb = new StringBuilder();
        sb.append("--").append(BOUNDARY).append(CRLF);
        sb.append("Content-Disposition: form-data; name=\"").append(name).append("\"").append(CRLF);
        sb.append(CRLF);
        sb.append(value).append(CRLF);
        out.write(sb.toString().getBytes(StandardCharsets.UTF_8));
    }
    
    private static void writeFile(OutputStream out, String fieldName, Path filePath) throws IOException {
        String fileName = filePath.getFileName().toString();
        
        StringBuilder sb = new StringBuilder();
        sb.append("--").append(BOUNDARY).append(CRLF);
        sb.append("Content-Disposition: form-data; name=\"")
          .append(fieldName).append("\"; filename=\"")
          .append(fileName).append("\"").append(CRLF);
        sb.append("Content-Type: ").append(probeContentType(filePath)).append(CRLF);
        sb.append(CRLF);
        out.write(sb.toString().getBytes(StandardCharsets.UTF_8));
        
        // Write file bytes
        Files.copy(filePath, out);
        
        out.write(CRLF.getBytes(StandardCharsets.UTF_8));
    }
    
    /**
     * Upload a single file
     */
    public static ApiResponse uploadFile(String url, String fieldName, Path filePath) throws IOException {
        Map<String, Path> files = new HashMap<>();
        files.put(fieldName, filePath);
        return uploadFiles(url, files, null);
    }
    
    /**
     * Probe content type or return default
     */
    private static String probeContentType(Path path) {
        try {
            String type = Files.probeContentType(path);
            return type != null ? type : "application/octet-stream";
        } catch (IOException e) {
            return "application/octet-stream";
        }
    }
    
    /**
     * Read input stream to string
     */
    private static String readInputStream(InputStream is) throws IOException {
        if (is == null) return "";
        
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(is, StandardCharsets.UTF_8))) {
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line).append("\n");
            }
            return sb.toString().trim();
        }
    }
    
    
    public static void log(String message) {
		System.out.println(message);
    }
}
 No newline at end of file
+65 −0
Original line number Diff line number Diff line
package org.etsi.mts.tdl.transform;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.etsi.mts.tdl.transform.HttpFileClient.ApiResponse;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;


public class ProtocolServerBridge {
	public String convertASN1toTDLRemote(String uri, List<String> asnFilePaths, String targetPath) {
		Map<String, Path> files = new HashMap<>();
		int i = 1;
        for (String p : asnFilePaths) {
        	files.put("files"+i, Paths.get(p));
        	i++;
        }
        
        Map<String, String> fields = new HashMap<>();
//        fields.put("backend", "titan");
//        fields.put("command", "compiler");
        fields.put("format", "tdl");
        
        try {
        	ApiResponse response = HttpFileClient.uploadFiles(
        			uri,
        			files,
        			fields
        			);
        	log("\nASN.1 files submitted..:");
        	log("Status: " + response.getStatusCode());
        	String body = response.getJsonBody();
            JsonObject jsonElement = JsonParser.parseString(body).getAsJsonArray().get(0).getAsJsonObject();
            String tdl = jsonElement.get("tdl").getAsString();

        	//TODO: get right part of body
        	System.out.println("Response: \n" + tdl);
        	//Files.writeString(Path.of(targetPath), tdl, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
        	//TODO: handle
        	return tdl;
        } catch (IOException e) {
        	// TODO Auto-generated catch block
        	e.printStackTrace();
        }
        
        return "";
	}
	
	private void log(String message) {
		System.out.println(message);
	}
	
}