diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/AbstractSkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/AbstractSkinServer.java new file mode 100644 index 00000000..fcf5238f --- /dev/null +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/AbstractSkinServer.java @@ -0,0 +1,47 @@ +package com.voxelmodpack.hdskins.skins; + +import java.io.IOException; +import java.net.URI; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +import javax.annotation.Nullable; + +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.exceptions.AuthenticationException; +import com.mojang.authlib.minecraft.MinecraftProfileTexture; +import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; +import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload; +import com.voxelmodpack.hdskins.HDSkinManager; + +import net.minecraft.util.Session; + +public abstract class AbstractSkinServer implements SkinServer { + + + @Override + public final Optional loadProfileData(GameProfile profile) { + return Optional.ofNullable(getProfileData(profile)); + } + + @Override + public Map getPreviewTextures(GameProfile profile) { + return loadProfileData(profile) + .map(MinecraftTexturesPayload::getTextures) + .orElse(Collections.emptyMap()); + } + + @Override + public final CompletableFuture uploadSkin(Session session, @Nullable URI image, Type type, Map metadata) { + return CallableFutures.asyncFailableFuture(() -> { + return doUpload(session, image, type, metadata); + }, HDSkinManager.skinUploadExecutor); + } + + protected abstract MinecraftTexturesPayload getProfileData(GameProfile profile); + + protected abstract SkinUploadResponse doUpload(Session session, URI image, Type type, Map metadata) throws AuthenticationException, IOException; + +} diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/BethlehemSkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/BethlehemSkinServer.java index cd98f9f2..eb0183d5 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/BethlehemSkinServer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/BethlehemSkinServer.java @@ -1,26 +1,24 @@ package com.voxelmodpack.hdskins.skins; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableMap.Builder; -import com.google.gson.JsonObject; -import com.google.gson.annotations.Expose; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; -import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload; -import com.mojang.util.UUIDTypeAdapter; -import com.voxelmodpack.hdskins.HDSkinManager; -import net.minecraft.util.Session; -import org.apache.commons.lang3.builder.ToStringBuilder; - import java.io.IOException; import java.net.URI; import java.util.Locale; import java.util.Map; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; +import com.google.gson.annotations.Expose; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.exceptions.AuthenticationException; +import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; +import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload; +import com.mojang.util.UUIDTypeAdapter; + +import net.minecraft.util.Session; @ServerType("bethlehem") -public class BethlehemSkinServer implements SkinServer { +public class BethlehemSkinServer extends AbstractSkinServer { private static final String SERVER_ID = "7853dfddc358333843ad55a2c7485c4aa0380a51"; @@ -32,28 +30,24 @@ public class BethlehemSkinServer implements SkinServer { } @Override - public Optional loadProfileData(GameProfile profile) { - NetClient client = new NetClient("GET", getPath(profile)); + protected MinecraftTexturesPayload getProfileData(GameProfile profile) { + try (NetClient client = new NetClient("GET", getPath(profile))) { + if (!client.send()) { + return null; + } - String json = client.getResponseText(); - - JsonObject s = gson.fromJson(json, JsonObject.class); - - if (s.has("success") && s.get("success").getAsBoolean()) { - s = s.get("data").getAsJsonObject(); - - return Optional.ofNullable(gson.fromJson(s, MinecraftTexturesPayload.class)); + return gson.fromJson(client.getResponseText(), MinecraftTexturesPayload.class); + } catch (IOException e) { + return null; } - - return Optional.empty(); } @Override - public CompletableFuture uploadSkin(Session session, URI image, Type type, Map metadata) { - return CallableFutures.asyncFailableFuture(() -> { - SkinServer.verifyServerConnection(session, SERVER_ID); + protected SkinUploadResponse doUpload(Session session, URI image, Type type, Map metadata) throws AuthenticationException, IOException { + SkinServer.verifyServerConnection(session, SERVER_ID); - NetClient client = new NetClient("POST", address).putHeaders(createHeaders(session, type, image, metadata)); + try (NetClient client = new NetClient("POST", address)) { + client.putHeaders(createHeaders(session, type, image, metadata)); if (image != null) { client.putFile(type.toString().toLowerCase(Locale.US), "image/png", image); @@ -64,7 +58,7 @@ public class BethlehemSkinServer implements SkinServer { } return new SkinUploadResponse(client.getResponseText()); - }, HDSkinManager.skinUploadExecutor); + } } protected Map createHeaders(Session session, Type type, URI image, Map metadata) { diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/CallableFutures.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/CallableFutures.java index 53f087a2..39a93aa7 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/CallableFutures.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/CallableFutures.java @@ -17,10 +17,4 @@ public class CallableFutures { }); return ret; } - - public static CompletableFuture failedFuture(Exception e) { - CompletableFuture ret = new CompletableFuture<>(); - ret.completeExceptionally(e); - return ret; - } } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java index 44c0ff69..9c84e9e3 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java @@ -2,33 +2,30 @@ package com.voxelmodpack.hdskins.skins; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; import com.google.gson.annotations.Expose; import com.mojang.authlib.GameProfile; +import com.mojang.authlib.exceptions.AuthenticationException; import com.mojang.authlib.minecraft.MinecraftProfileTexture; +import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload; import com.mojang.util.UUIDTypeAdapter; -import com.voxelmodpack.hdskins.HDSkinManager; -import com.voxelmodpack.hdskins.upload.ThreadMultipartPostUpload; + import net.minecraft.util.Session; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.IOException; -import java.net.HttpURLConnection; import java.net.URI; -import java.net.URL; import java.util.Collections; import java.util.EnumMap; import java.util.Locale; import java.util.Map; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; - import javax.annotation.Nullable; @ServerType("legacy") -public class LegacySkinServer implements SkinServer { +public class LegacySkinServer extends AbstractSkinServer { private static final String SERVER_ID = "7853dfddc358333843ad55a2c7485c4aa0380a51"; @@ -36,6 +33,7 @@ public class LegacySkinServer implements SkinServer { @Expose private final String address; + @Expose private final String gateway; @@ -45,28 +43,33 @@ public class LegacySkinServer implements SkinServer { } @Override - public Map getPreviewTextures(GameProfile profile) { + public Map getPreviewTextures(GameProfile profile) { if (Strings.isNullOrEmpty(gateway)) { return Collections.emptyMap(); } - Map map = new EnumMap<>(MinecraftProfileTexture.Type.class); - for (MinecraftProfileTexture.Type type : MinecraftProfileTexture.Type.values()) { + + Map map = new EnumMap<>(Type.class); + + for (Type type : Type.values()) { map.put(type, new MinecraftProfileTexture(getPath(gateway, type, profile), null)); } + return map; } + @SuppressWarnings("deprecation") @Override - public Optional loadProfileData(GameProfile profile) { - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (MinecraftProfileTexture.Type type : MinecraftProfileTexture.Type.values()) { + protected MinecraftTexturesPayload getProfileData(GameProfile profile) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + for (Type type : Type.values()) { String url = getPath(address, type, profile); - try { - HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection(); - if (urlConnection.getResponseCode() / 100 != 2) { - throw new IOException("Bad response code: " + urlConnection.getResponseCode()); + + try (NetClient client = new NetClient("GET", url)) { + if (!client.send()) { + throw new IOException("Bad response code: " + client.getResponseCode()); } + builder.put(type, new MinecraftProfileTexture(url, null)); logger.debug("Found skin for {} at {}", profile.getName(), url); } catch (IOException e) { @@ -74,58 +77,59 @@ public class LegacySkinServer implements SkinServer { } } - Map map = builder.build(); + Map map = builder.build(); + if (map.isEmpty()) { logger.debug("No textures found for {} at {}", profile, address); - return Optional.empty(); + return null; } - return Optional.of(TexturesPayloadBuilder.createTexturesPayload(profile, map)); + return TexturesPayloadBuilder.createTexturesPayload(profile, map); } - @SuppressWarnings("deprecation") @Override - public CompletableFuture uploadSkin(Session session, @Nullable URI image, MinecraftProfileTexture.Type type, Map metadata) { - if (Strings.isNullOrEmpty(gateway)) { - return CallableFutures.failedFuture(new NullPointerException("gateway url is blank")); - } + protected SkinUploadResponse doUpload(Session session, URI image, Type type, Map metadata) throws AuthenticationException, IOException { + SkinServer.verifyServerConnection(session, SERVER_ID); - return CallableFutures.asyncFailableFuture(() -> { - SkinServer.verifyServerConnection(session, SERVER_ID); - String model = metadata.getOrDefault("model", "default"); - Map data = image == null ? getClearData(session, type) : getUploadData(session, type, model, image); - ThreadMultipartPostUpload upload = new ThreadMultipartPostUpload(gateway, data); - String response = upload.uploadMultipart(); - if (response.startsWith("ERROR: ")) { + try (NetClient client = new NetClient("POST", address)) { + client.putHeaders(createHeaders(session, type, image, metadata)); + + if (image != null) { + client.putFile(type.toString().toLowerCase(Locale.US), "image/png", image); + } + + String response = client.getResponseText(); + + if (response.startsWith("ERROR: ")) { // lol @ "ERROR: OK" response = response.substring(7); } + if (!response.equalsIgnoreCase("OK") && !response.endsWith("OK")) throw new IOException(response); return new SkinUploadResponse(response); - - }, HDSkinManager.skinUploadExecutor); + } } - private static Map getData(Session session, MinecraftProfileTexture.Type type, String model, String param, Object val) { - return ImmutableMap.of( - "user", session.getUsername(), - "uuid", UUIDTypeAdapter.fromUUID(session.getProfile().getId()), - "type", type.toString().toLowerCase(Locale.US), - "model", model, - param, val); + + protected Map createHeaders(Session session, Type type, URI image, Map metadata) { + Builder builder = ImmutableMap.builder() + .put("user", session.getUsername()) + .put("uuid", UUIDTypeAdapter.fromUUID(session.getProfile().getId())) + .put("type", type.toString().toLowerCase(Locale.US)); + + if (image == null) { + builder.put("clear", "1"); + } else { + builder.put("model", metadata.getOrDefault("mode", "default")); + } + + return builder.build(); } - private static Map getClearData(Session session, MinecraftProfileTexture.Type type) { - return getData(session, type, "default", "clear", "1"); - } - - private static Map getUploadData(Session session, MinecraftProfileTexture.Type type, String model, URI skinFile) { - return getData(session, type, model, type.toString().toLowerCase(Locale.US), skinFile); - } - - private static String getPath(String address, MinecraftProfileTexture.Type type, GameProfile profile) { + private static String getPath(String address, Type type, GameProfile profile) { String uuid = UUIDTypeAdapter.fromUUID(profile.getId()); String path = type.toString().toLowerCase() + "s"; + return String.format("%s/%s/%s.png", address, path, uuid); } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/NetClient.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/NetClient.java index 0e91c50d..e3b5437f 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/NetClient.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/NetClient.java @@ -1,6 +1,7 @@ package com.voxelmodpack.hdskins.skins; import java.io.BufferedReader; +import java.io.Closeable; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; @@ -15,21 +16,36 @@ import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.RequestBuilder; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; /** * Ew. Why so many builders? >.< */ -public class NetClient { +public class NetClient implements Closeable { - private final RequestBuilder rqBuilder; + private CloseableHttpClient client; + + private RequestBuilder rqBuilder; private Map headers; private CloseableHttpResponse response = null; public NetClient(String method, String uri) { + start(method, uri); + } + + public NetClient start(String method, String uri) { rqBuilder = RequestBuilder.create(method).setUri(uri); + headers = null; + + if (response != null) { + IOUtils.closeQuietly(response); + response = null; + } + + return this; } public NetClient putFile(String key, String contentType, URI file) { @@ -50,12 +66,18 @@ public class NetClient { public boolean send() { HttpUriRequest request = rqBuilder.build(); - for (Map.Entry parameter : headers.entrySet()) { - request.addHeader(parameter.getKey(), parameter.getValue().toString()); + if (headers != null) { + for (Map.Entry parameter : headers.entrySet()) { + request.addHeader(parameter.getKey(), parameter.getValue().toString()); + } + } + + if (client == null) { + client = HttpClients.createSystem(); } try { - response = HttpClients.createSystem().execute(request); + response = client.execute(request); return getResponseCode() == HttpStatus.SC_OK; } catch (IOException e) { } @@ -78,11 +100,7 @@ public class NetClient { } } - BufferedReader reader = null; - - try { - reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); - + try (BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))) { StringBuilder builder = new StringBuilder(); int ch; @@ -93,10 +111,21 @@ public class NetClient { return builder.toString(); } catch (IOException e) { - } finally { - IOUtils.closeQuietly(reader); } return ""; } + + @Override + public void close() throws IOException { + if (response != null) { + IOUtils.closeQuietly(response); + response = null; + } + + if (client != null) { + IOUtils.closeQuietly(client); + client = null; + } + } } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java index dce9d855..74137ea8 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java @@ -15,7 +15,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.util.Session; import java.net.URI; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -36,13 +35,10 @@ public interface SkinServer extends Exposable { Optional loadProfileData(GameProfile profile); - default Map getPreviewTextures(GameProfile profile) { - return loadProfileData(profile).map(MinecraftTexturesPayload::getTextures).orElse(Collections.emptyMap()); - } + Map getPreviewTextures(GameProfile profile); CompletableFuture uploadSkin(Session session, @Nullable URI image, MinecraftProfileTexture.Type type, Map metadata); - public static void verifyServerConnection(Session session, String serverId) throws AuthenticationException { MinecraftSessionService service = Minecraft.getMinecraft().getSessionService(); service.joinServer(session.getProfile(), session.getToken(), serverId); diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/ValhallaSkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/ValhallaSkinServer.java index 5ea734e4..d07b7fa1 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/ValhallaSkinServer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/ValhallaSkinServer.java @@ -6,9 +6,12 @@ import com.google.gson.annotations.Expose; import com.mojang.authlib.GameProfile; import com.mojang.authlib.exceptions.AuthenticationException; import com.mojang.authlib.minecraft.MinecraftProfileTexture; +import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload; import com.mojang.util.UUIDTypeAdapter; -import com.voxelmodpack.hdskins.HDSkinManager; + +import javax.annotation.Nullable; + import net.minecraft.client.Minecraft; import net.minecraft.util.Session; import org.apache.commons.lang3.builder.ToStringBuilder; @@ -34,14 +37,10 @@ import java.io.Reader; import java.net.URI; import java.util.Locale; import java.util.Map; -import java.util.Optional; import java.util.UUID; -import java.util.concurrent.CompletableFuture; - -import javax.annotation.Nullable; @ServerType("valhalla") -public class ValhallaSkinServer implements SkinServer { +public class ValhallaSkinServer extends AbstractSkinServer { @Expose private final String address; @@ -53,44 +52,39 @@ public class ValhallaSkinServer implements SkinServer { } @Override - public Optional loadProfileData(GameProfile profile) { + protected MinecraftTexturesPayload getProfileData(GameProfile profile) { try (CloseableHttpClient client = HttpClients.createSystem(); CloseableHttpResponse response = client.execute(new HttpGet(getTexturesURI(profile)))) { - if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { - - return Optional.of(readJson(response, MinecraftTexturesPayload.class)); + return readJson(response, MinecraftTexturesPayload.class); } + } catch (IOException e) { e.printStackTrace(); } - return Optional.empty(); + return null; } @Override - public CompletableFuture uploadSkin(Session session, @Nullable URI image, MinecraftProfileTexture.Type type, Map metadata) { - return CallableFutures.asyncFailableFuture(() -> { - try (CloseableHttpClient client = HttpClients.createSystem()) { - authorize(client, session); + protected SkinUploadResponse doUpload(Session session, URI image, Type type, Map metadata) throws AuthenticationException, IOException { + try (CloseableHttpClient client = HttpClients.createSystem()) { + authorize(client, session); - try { + try { + return upload(client, session, image, type, metadata); + } catch (IOException e) { + if (e.getMessage().equals("Authorization failed")) { + accessToken = null; + authorize(client, session); return upload(client, session, image, type, metadata); - } catch (IOException e) { - if (e.getMessage().equals("Authorization failed")) { - accessToken = null; - authorize(client, session); - return upload(client, session, image, type, metadata); - } - throw e; } + throw e; } - }, HDSkinManager.skinUploadExecutor); + } } - private SkinUploadResponse upload(CloseableHttpClient client, Session session, @Nullable URI image, - MinecraftProfileTexture.Type type, Map metadata) - throws IOException { + private SkinUploadResponse upload(CloseableHttpClient client, Session session, @Nullable URI image, MinecraftProfileTexture.Type type, Map metadata) throws IOException { GameProfile profile = session.getProfile(); if (image == null) { @@ -151,7 +145,7 @@ public class ValhallaSkinServer implements SkinServer { } GameProfile profile = session.getProfile(); - String token = session.getToken(); + AuthHandshake handshake = authHandshake(client, profile.getName()); if (handshake.offline) { @@ -159,7 +153,7 @@ public class ValhallaSkinServer implements SkinServer { } // join the session server - Minecraft.getMinecraft().getSessionService().joinServer(profile, token, handshake.serverId); + Minecraft.getMinecraft().getSessionService().joinServer(profile, session.getToken(), handshake.serverId); AuthResponse response = authResponse(client, profile.getName(), handshake.verifyToken); if (!response.userId.equals(profile.getId())) { @@ -232,7 +226,7 @@ public class ValhallaSkinServer implements SkinServer { public String toString() { return new ToStringBuilder(this, IndentedToStringStyle.INSTANCE) .append("address", address) - .toString(); + .build(); } @SuppressWarnings("WeakerAccess") @@ -248,6 +242,5 @@ public class ValhallaSkinServer implements SkinServer { private String accessToken; private UUID userId; - } } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/upload/ThreadMultipartPostUpload.java b/src/hdskins/java/com/voxelmodpack/hdskins/upload/ThreadMultipartPostUpload.java deleted file mode 100644 index d9933a24..00000000 --- a/src/hdskins/java/com/voxelmodpack/hdskins/upload/ThreadMultipartPostUpload.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.voxelmodpack.hdskins.upload; - -import org.apache.commons.io.IOUtils; - -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URI; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Map; -import java.util.Map.Entry; - -import javax.annotation.Nullable; - -/** - * Uploader for Multipart form data - * - * @author Adam Mummery-Smith - * @deprecated Use httpmime multipart upload - */ -@Deprecated -public class ThreadMultipartPostUpload { - protected final Map sourceData; - - protected final String method; - - protected final String authorization; - - protected final String urlString; - - protected HttpURLConnection httpClient; - - protected static final String CRLF = "\r\n"; - - protected static final String twoHyphens = "--"; - - protected static final String boundary = "----------AaB03x"; - - public String response; - - public ThreadMultipartPostUpload(String method, String url, Map sourceData, @Nullable String authorization) { - this.method = method; - this.urlString = url; - this.sourceData = sourceData; - this.authorization = authorization; - } - - public ThreadMultipartPostUpload(String url, Map sourceData) { - this("POST", url, sourceData, null); - } - - public String uploadMultipart() throws IOException { - // open a URL connection - URL url = new URL(this.urlString); - - // Open a HTTP connection to the URL - this.httpClient = (HttpURLConnection) url.openConnection(); - this.httpClient.setDoOutput(true); - this.httpClient.setUseCaches(false); - - this.httpClient.setRequestMethod(this.method); - this.httpClient.setRequestProperty("Connection", "Close"); - this.httpClient.addRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"); // For CloudFlare - - if (this.sourceData.size() > 0) { - this.httpClient.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); - } - - if (this.authorization != null) { - this.httpClient.addRequestProperty("Authorization", this.authorization); - } - - try (DataOutputStream outputStream = new DataOutputStream(this.httpClient.getOutputStream())) { - - for (Entry data : this.sourceData.entrySet()) { - outputStream.writeBytes(twoHyphens + boundary + CRLF); - - String paramName = data.getKey(); - Object paramData = data.getValue(); - - if (paramData instanceof URI) { - Path uploadPath = Paths.get((URI) paramData); - - outputStream.writeBytes("Content-Disposition: form-data; name=\"" + paramName + "\"; filename=\"" + uploadPath.getFileName() + "\"" + CRLF); - outputStream.writeBytes("Content-Type: image/png" + CRLF + CRLF); - - - Files.copy(uploadPath, outputStream); - } else { - outputStream.writeBytes("Content-Disposition: form-data; name=\"" + paramName + "\"" + CRLF + CRLF); - - outputStream.writeBytes(paramData.toString()); - } - - outputStream.writeBytes(ThreadMultipartPostUpload.CRLF); - } - - outputStream.writeBytes(twoHyphens + boundary + twoHyphens + CRLF); - } - - try (InputStream input = this.httpClient.getInputStream()) { - return IOUtils.toString(input, StandardCharsets.UTF_8); - } - } - -}