diff --git a/sdk-java/src/main/java/ly/count/sdk/java/internal/ImmediateRequestMaker.java b/sdk-java/src/main/java/ly/count/sdk/java/internal/ImmediateRequestMaker.java index 5d8bf8f2..abced9ad 100644 --- a/sdk-java/src/main/java/ly/count/sdk/java/internal/ImmediateRequestMaker.java +++ b/sdk-java/src/main/java/ly/count/sdk/java/internal/ImmediateRequestMaker.java @@ -67,7 +67,7 @@ private JSONObject doInBackground(String requestData, String customEndpoint, Tra request.endpoint(customEndpoint); //getting connection ready try { - connection = cp.connection(request, null); + connection = cp.connection(request); } catch (IOException e) { L.e("[ImmediateRequestMaker] IOException while preparing remote config update request :[" + e + "]"); return null; diff --git a/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleUserProfile.java b/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleUserProfile.java index 2560aff1..6ed7d352 100644 --- a/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleUserProfile.java +++ b/sdk-java/src/main/java/ly/count/sdk/java/internal/ModuleUserProfile.java @@ -13,7 +13,6 @@ public class ModuleUserProfile extends ModuleBase { static final String CUSTOM_KEY = "custom"; - static final String PICTURE_IN_USER_PROFILE = "[CLY]_USER_PROFILE_PICTURE"; boolean isSynced = true; UserProfile userProfileInterface; private final Map sets; @@ -114,7 +113,7 @@ void perform(JSONObject changes) throws JSONException { } else if (value instanceof byte[]) { internalConfig.sdk.user().picture = (byte[]) value; //set a special value to indicate that the picture information is already stored in memory - changes.put(PredefinedUserPropertyKeys.PICTURE_PATH, PICTURE_IN_USER_PROFILE); + changes.put(PredefinedUserPropertyKeys.PICTURE_PATH, Utils.Base64.encode((byte[]) value)); } break; case PredefinedUserPropertyKeys.PICTURE_PATH: @@ -220,7 +219,7 @@ private Params prepareRequestParamsForUserProfile() { L.w("Won't send picturePath" + e); } } - if (!json.isEmpty() || internalConfig.sdk.user().picturePath != null || internalConfig.sdk.user().picture != null) { + if (!json.isEmpty() || params.has(PredefinedUserPropertyKeys.PICTURE_PATH)) { params.add("user_details", json.toString()); return params; } else { diff --git a/sdk-java/src/main/java/ly/count/sdk/java/internal/SDKCore.java b/sdk-java/src/main/java/ly/count/sdk/java/internal/SDKCore.java index d435745f..31b0fc68 100644 --- a/sdk-java/src/main/java/ly/count/sdk/java/internal/SDKCore.java +++ b/sdk-java/src/main/java/ly/count/sdk/java/internal/SDKCore.java @@ -557,16 +557,7 @@ public Integer remaningRequests() { } } - try { - user = Storage.read(config, new UserImpl(config)); - if (user == null) { - user = new UserImpl(config); - } - } catch (Throwable e) { - L.e("[SDKCore] Cannot happen" + e); - user = new UserImpl(config); - } - + user = new UserImpl(config); initFinished(config); } diff --git a/sdk-java/src/main/java/ly/count/sdk/java/internal/Transport.java b/sdk-java/src/main/java/ly/count/sdk/java/internal/Transport.java index 3a24a92b..8c4230c4 100644 --- a/sdk-java/src/main/java/ly/count/sdk/java/internal/Transport.java +++ b/sdk-java/src/main/java/ly/count/sdk/java/internal/Transport.java @@ -26,6 +26,7 @@ import java.security.spec.X509EncodedKeySpec; import java.util.ArrayList; import java.util.Arrays; +import java.util.Base64; import java.util.List; import java.util.Map; import java.util.Set; @@ -36,7 +37,6 @@ import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; import ly.count.sdk.java.PredefinedUserPropertyKeys; -import ly.count.sdk.java.User; import org.json.JSONObject; /** @@ -118,11 +118,10 @@ public HttpURLConnection openConnection(String url, String params, boolean using * set SSL context, calculate and add checksum, load and send user picture if needed. * * @param request request to send - * @param user user to check for picture * @return connection, not {@link HttpURLConnection} yet * @throws IOException from {@link HttpURLConnection} in case of error */ - HttpURLConnection connection(final Request request, final User user) throws IOException { + HttpURLConnection connection(final Request request) throws IOException { String endpoint = request.params.remove(Request.ENDPOINT); if (!request.params.has("device_id") && config.getDeviceId() != null) { @@ -160,7 +159,7 @@ HttpURLConnection connection(final Request request, final User user) throws IOEx PrintWriter writer = null; try { L.d("[network] Picture path value " + picturePathValue); - byte[] pictureByteData = picturePathValue == null ? null : getPictureDataFromGivenValue(user, picturePathValue); + byte[] pictureByteData = picturePathValue == null ? null : getPictureDataFromGivenValue(picturePathValue); if (pictureByteData != null) { String boundary = Long.toHexString(System.currentTimeMillis()); @@ -240,36 +239,35 @@ void addMultipart(OutputStream output, PrintWriter writer, String boundary, Stri * If we have the bytes, give them * Otherwise load them from disk * - * @param user - * @param picture - * @return + * @param picture picture path or base64 encoded byte array + * @return picture data */ - byte[] getPictureDataFromGivenValue(User user, String picture) { - if (user == null) { - return null; - } - - byte[] data = null; - if (ModuleUserProfile.PICTURE_IN_USER_PROFILE.equals(picture)) { - //if the value is this special value then we know that we will send over bytes that are already provided by the integrator - //those stored bytes are already in a internal data structure, use them - data = user.picture(); - } else { - //otherwise we assume it is a local path, and we try to read it from disk - try { - File file = new File(picture); - if (!file.exists()) { - return null; - } - data = Files.readAllBytes(file.toPath()); - } catch (Throwable t) { - L.w("[Transport] getPictureDataFromGivenValue, Error while reading picture from disk " + t); + byte[] getPictureDataFromGivenValue(String picture) { + byte[] data; + //firstly, we assume it is a local path, and we try to read it from disk + try { + File file = new File(picture); + if (!file.exists()) { + return null; } + data = Files.readAllBytes(file.toPath()); + } catch (Throwable t) { + //if we can't read it from disk, we assume it is a base64 encoded byte array + data = readBase64String(picture); } return data; } + private byte[] readBase64String(String string) { + try { + return Base64.getDecoder().decode(string); + } catch (IllegalArgumentException e) { + L.w("[Transport] readBase64String, Error while reading base64 string " + e); + return null; + } + } + String response(HttpURLConnection connection) { BufferedReader reader = null; try { @@ -319,7 +317,7 @@ public Boolean send() { Class requestOwner = request.owner(); request.params.remove(Request.MODULE); - connection = connection(request, SDKCore.instance.user()); + connection = connection(request); connection.connect(); int code = connection.getResponseCode(); diff --git a/sdk-java/src/main/java/ly/count/sdk/java/internal/UserEditorImpl.java b/sdk-java/src/main/java/ly/count/sdk/java/internal/UserEditorImpl.java index b57495c1..4d988eaa 100644 --- a/sdk-java/src/main/java/ly/count/sdk/java/internal/UserEditorImpl.java +++ b/sdk-java/src/main/java/ly/count/sdk/java/internal/UserEditorImpl.java @@ -275,7 +275,6 @@ public User commit() { try { Countly.instance().userProfile().save(); - Storage.push(SDKCore.instance.config, user); // todo this is not need it is for another task } catch (JSONException e) { L.e("[UserEditorImpl] Exception while committing changes to User profile" + e); } diff --git a/sdk-java/src/main/java/ly/count/sdk/java/internal/UserImpl.java b/sdk-java/src/main/java/ly/count/sdk/java/internal/UserImpl.java index 8e04eb31..31686ec2 100644 --- a/sdk-java/src/main/java/ly/count/sdk/java/internal/UserImpl.java +++ b/sdk-java/src/main/java/ly/count/sdk/java/internal/UserImpl.java @@ -1,12 +1,8 @@ package ly.count.sdk.java.internal; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.*; - +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import ly.count.sdk.java.User; import ly.count.sdk.java.UserEditor; @@ -14,7 +10,7 @@ * Class for user profile data access & manipulation */ -public class UserImpl extends User implements Storable { +public class UserImpl extends User { private Log L = null; String id; @@ -102,131 +98,6 @@ public UserEditor edit() { return new UserEditorImpl(this, L); } - @Override - public byte[] store(Log L) { - ByteArrayOutputStream bytes = null; - ObjectOutputStream stream = null; - try { - bytes = new ByteArrayOutputStream(); - stream = new ObjectOutputStream(bytes); - stream.writeObject(name); - stream.writeObject(username); - stream.writeObject(email); - stream.writeObject(org); - stream.writeObject(phone); - stream.writeInt(picture == null ? 0 : picture.length); - if (picture != null) { - stream.write(picture); - } - stream.writeObject(picturePath); - stream.writeObject(gender == null ? null : gender.toString()); - stream.writeInt(birthyear == null ? -1 : birthyear); - stream.writeObject(locale); - stream.writeObject(country); - stream.writeObject(city); - stream.writeObject(location); - stream.writeObject(null);//this is for the removed "cohorts" functionality. just to keep the correct order. Throw away in the future - stream.writeObject(custom); - stream.close(); - return bytes.toByteArray(); - } catch (IOException e) { - if (L != null) { - L.e("[UserImpl Cannot serialize session" + e); - } - } finally { - if (stream != null) { - try { - stream.close(); - } catch (IOException e) { - if (L != null) { - L.e("[UserImpl Cannot happen" + e); - } - } - } - if (bytes != null) { - try { - bytes.close(); - } catch (IOException e) { - if (L != null) { - L.e("[UserImpl Cannot happen" + e); - } - } - } - } - return null; - } - - @SuppressWarnings("unchecked") - public boolean restore(byte[] data, Log L) { - ByteArrayInputStream bytes = null; - ObjectInputStream stream = null; - - try { - bytes = new ByteArrayInputStream(data); - stream = new ObjectInputStream(bytes); - name = (String) stream.readObject(); - username = (String) stream.readObject(); - email = (String) stream.readObject(); - org = (String) stream.readObject(); - phone = (String) stream.readObject(); - - int picLength = stream.readInt(); - if (picLength != 0) { - picture = new byte[picLength]; - stream.readFully(picture); - } - picturePath = (String) stream.readObject(); - - String g = (String) stream.readObject(); - if (g != null) { - gender = Gender.fromString(g); - } - - int y = stream.readInt(); - if (y != -1) { - birthyear = y; - } - locale = (String) stream.readObject(); - country = (String) stream.readObject(); - city = (String) stream.readObject(); - location = (String) stream.readObject(); - - Set throwawayCohorts = (Set) stream.readObject();//this is for keeping backwards compatibility. Throw away in the future - - custom = (Map) stream.readObject(); - if (custom == null) { - custom = new HashMap<>(); - } - - return true; - } catch (IOException | ClassNotFoundException e) { - if (L != null) { - L.e("[UserImpl Cannot deserialize session" + e); - } - } finally { - if (stream != null) { - try { - stream.close(); - } catch (IOException e) { - if (L != null) { - L.e("[UserImpl Cannot happen" + e); - } - } - } - if (bytes != null) { - try { - bytes.close(); - } catch (IOException e) { - if (L != null) { - L.e("[UserImpl Cannot happen" + e); - } - } - } - } - - return false; - } - @Override public String toString() { return "UserImpl{" + @@ -247,20 +118,4 @@ public String toString() { ", custom=" + custom + '}'; } - - @Override - public Long storageId() { - return 0L; - } - - @Override - public String storagePrefix() { - return "user"; - } - - @Override - public void setId(Long id) { - this.id = id.toString(); - //todo remove this - } } diff --git a/sdk-java/src/test/java/ly/count/sdk/java/internal/TestUtils.java b/sdk-java/src/test/java/ly/count/sdk/java/internal/TestUtils.java index fda18add..92efc262 100644 --- a/sdk-java/src/test/java/ly/count/sdk/java/internal/TestUtils.java +++ b/sdk-java/src/test/java/ly/count/sdk/java/internal/TestUtils.java @@ -270,18 +270,16 @@ private static File[] getRequestFiles(File targetFolder) { private static Map parseRequestParams(File file) throws IOException { try (Scanner scanner = new Scanner(file)) { String firstLine = scanner.nextLine(); - String urlDecodedStr = Utils.urldecode(firstLine); - - if (urlDecodedStr == null) { + if (Utils.isEmptyOrNull(firstLine)) { return new HashMap<>(); } - String[] params = urlDecodedStr.split("&"); + String[] params = firstLine.split("&"); Map paramMap = new HashMap<>(); for (String param : params) { String[] pair = param.split("="); - paramMap.put(pair[0], pair.length == 1 ? "" : pair[1]); + paramMap.put(Utils.urldecode(pair[0]), pair.length == 1 ? "" : Utils.urldecode(pair[1])); } return paramMap; diff --git a/sdk-java/src/test/java/ly/count/sdk/java/internal/UserEditorTests.java b/sdk-java/src/test/java/ly/count/sdk/java/internal/UserEditorTests.java index a4dab7af..e4278c6b 100644 --- a/sdk-java/src/test/java/ly/count/sdk/java/internal/UserEditorTests.java +++ b/sdk-java/src/test/java/ly/count/sdk/java/internal/UserEditorTests.java @@ -112,7 +112,7 @@ public void setPicture_binaryData() { sessionHandler(() -> Countly.instance().user().edit().setPicture(imgData).commit()); validatePictureAndPath(null, imgData); Countly.session().end(); - validateUserDetailsRequestInRQ(map("user_details", "{}", "picturePath", ModuleUserProfile.PICTURE_IN_USER_PROFILE)); + validateUserDetailsRequestInRQ(map("user_details", "{}", "picturePath", Utils.Base64.encode(imgData))); } /**