Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix devfile component preferences deserialization through GSON #14306

Merged
merged 8 commits into from
Sep 10, 2019
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
Expand Down Expand Up @@ -511,6 +512,8 @@ private static Gson buildDtoParser(
builder.registerTypeHierarchyAdapter(Map.class, new NullOrEmptyMapAdapter());
}

builder.registerTypeAdapterFactory(new SerializableInterfaceAdapterFactory());

return builder.create();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.dto.server;

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.Serializable;

/**
* This adapter is required for fields of {@link java.io.Serializable} type to be treated as {@link
* Object}
*/
public class SerializableInterfaceAdapterFactory implements TypeAdapterFactory {

@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (Serializable.class.equals(type.getRawType())) {
return (TypeAdapter<T>) new SerializableAdapter(gson.getAdapter(Object.class));
}
return null;
}

private static class SerializableAdapter extends TypeAdapter<Object> {

TypeAdapter objectAdapter;

public SerializableAdapter(TypeAdapter objectAdapter) {
this.objectAdapter = objectAdapter;
}

@Override
public void write(JsonWriter out, Object value) throws IOException {
objectAdapter.write(out, value);
}

@Override
public Object read(JsonReader in) throws IOException {
JsonToken token = in.peek();
if (token.equals(JsonToken.NUMBER)) {
String str = in.nextString();
try {
return Integer.parseInt(str);
mkuznyetsov marked this conversation as resolved.
Show resolved Hide resolved
} catch (NumberFormatException e) {
try {
return Long.parseLong(str);
} catch (NumberFormatException e1) {
try {
return Double.parseDouble(str);
} catch (NumberFormatException e3) {
throw e3;
}
}
}
}
return objectAdapter.read(in);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.eclipse.che.dto.definitions.DtoWithAny;
import org.eclipse.che.dto.definitions.DtoWithDelegate;
import org.eclipse.che.dto.definitions.DtoWithFieldNames;
import org.eclipse.che.dto.definitions.DtoWithSerializable;
import org.eclipse.che.dto.definitions.SimpleDto;
import org.eclipse.che.dto.definitions.model.Model;
import org.eclipse.che.dto.definitions.model.ModelComponentDto;
Expand Down Expand Up @@ -435,4 +436,36 @@ public void shouldThrowExceptionWhenThereIsClassType() {
public void shouldThrowExceptionWhenInterfaceIsNotAnnotatedAsDto() {
DtoFactory.newDto(DTOHierarchy.GrandchildWithoutDto.class);
}

@Test
public void checkDtoDeserializationWithSerializableFields() {
final int fooId = 1;
final String fooString = "some string";
final int fooInt = 1234567890;
final long fooLong = 1234514362645634611L;
final double fooDouble = 1.2345;

JsonObject jsonMap = new JsonObject();
jsonMap.add("fooInt", new JsonPrimitive(fooInt));
jsonMap.add("fooLong", new JsonPrimitive(fooLong));
jsonMap.add("fooBoolean", new JsonPrimitive(true));
jsonMap.add("fooDouble", new JsonPrimitive(fooDouble));
jsonMap.add("fooString", new JsonPrimitive(fooString));

JsonObject json = new JsonObject();
json.add("id", new JsonPrimitive(fooId));
json.add("object", new JsonPrimitive(fooString));
json.add("objectMap", jsonMap);

DtoWithSerializable dto =
dtoFactory.createDtoFromJson(json.toString(), DtoWithSerializable.class);

assertEquals(dto.getId(), fooId);
assertEquals(dto.getObject(), fooString);
assertEquals(dto.getObjectMap().get("fooInt"), fooInt);
assertEquals(dto.getObjectMap().get("fooLong"), fooLong);
assertEquals(dto.getObjectMap().get("fooBoolean"), true);
assertEquals(dto.getObjectMap().get("fooDouble"), fooDouble);
assertEquals(dto.getObjectMap().get("fooString"), fooString);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.dto.definitions;

import java.io.Serializable;
import java.util.Map;
import org.eclipse.che.dto.shared.DTO;

/** DTO for testing serialization of fields with {@link java.io.Serializable} type */
@DTO
public interface DtoWithSerializable {
int getId();

DtoWithSerializable withId(int id);

Serializable getObject();

void setObject(Serializable object);

DtoWithSerializable withObject(Serializable object);

Map<String, Serializable> getObjectMap();

void setObjectMap(Map<String, Serializable> map);

DtoWithSerializable withObjectMap(Map<String, Serializable> map);
}