Mercurial > hg > release > thermostat-1.0
changeset 1282:a4c836ada099
Improve prepared parameter serialization.
Reviewed-by: neugens
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-October/008374.html
line wrap: on
line diff
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/PreparedParameter.java Wed Oct 02 18:14:39 2013 +0200 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/PreparedParameter.java Wed Oct 02 15:07:46 2013 +0200 @@ -44,16 +44,13 @@ public class PreparedParameter { private Object value; - // The simple type of value. Even if value is an array. + // The type of the value field. This is the instantiable component type for + // Pojo array values. private Class<?> type; - // true if and only if value is an array of simple types - // as specified by the type instance variable. - private boolean isArrayType; - PreparedParameter(Object value, Class<?> type, boolean isArrayType) { + PreparedParameter(Object value, Class<?> type) { this.value = value; this.type = type; - this.isArrayType = isArrayType; } public PreparedParameter() { @@ -75,12 +72,4 @@ public void setType(Class<?> type) { this.type = type; } - - public boolean isArrayType() { - return isArrayType; - } - - public void setArrayType(boolean isArrayType) { - this.isArrayType = isArrayType; - } }
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/PreparedParameters.java Wed Oct 02 18:14:39 2013 +0200 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/PreparedParameters.java Wed Oct 02 15:07:46 2013 +0200 @@ -37,6 +37,7 @@ package com.redhat.thermostat.storage.core; import java.lang.reflect.Modifier; +import java.util.Objects; import com.redhat.thermostat.storage.model.Pojo; @@ -60,66 +61,72 @@ @Override public void setLong(int paramIndex, long paramValue) { - setType(paramIndex, paramValue, Long.class, false); + setType(paramIndex, paramValue, long.class); } @Override public void setLongList(int paramIndex, long[] paramValue) { - setType(paramIndex, paramValue, Long.class, true); + setType(paramIndex, paramValue, long[].class); } @Override public void setInt(int paramIndex, int paramValue) { - setType(paramIndex, paramValue, Integer.class, false); + setType(paramIndex, paramValue, int.class); } @Override public void setIntList(int paramIndex, int[] paramValue) { - setType(paramIndex, paramValue, Integer.class, true); + setType(paramIndex, paramValue, int[].class); } @Override public void setBoolean(int paramIndex, boolean paramValue) { - setType(paramIndex, paramValue, Boolean.class, false); + setType(paramIndex, paramValue, boolean.class); } @Override public void setBooleanList(int paramIndex, boolean[] paramValue) { - setType(paramIndex, paramValue, Boolean.class, true); + setType(paramIndex, paramValue, boolean[].class); } @Override public void setString(int paramIndex, String paramValue) { - setType(paramIndex, paramValue, String.class, false); + setType(paramIndex, paramValue, String.class); } @Override public void setStringList(int paramIndex, String[] paramValue) { - setType(paramIndex, paramValue, String.class, true); + setType(paramIndex, paramValue, String[].class); } @Override public void setDouble(int paramIndex, double paramValue) { - setType(paramIndex, paramValue, Double.class, false); + setType(paramIndex, paramValue, double.class); } @Override public void setDoubleList(int paramIndex, double[] paramValue) { - setType(paramIndex, paramValue, Double.class, true); + setType(paramIndex, paramValue, double[].class); } @Override public void setPojo(int paramIndex, Pojo paramValue) { + // null Pojo value would make array and non-array types + // indistinguishable for serialization + Objects.requireNonNull(paramValue); Class<?> runtimeType = paramValue.getClass(); performPojoChecks(runtimeType, "Type"); - setType(paramIndex, paramValue, runtimeType, false); + setType(paramIndex, paramValue, runtimeType); } @Override public void setPojoList(int paramIndex, Pojo[] paramValue) { + // null Pojo value would make array and non-array types + // indistinguishable for serialization + Objects.requireNonNull(paramValue); Class<?> componentType = paramValue.getClass().getComponentType(); performPojoChecks(componentType, "Component type"); - setType(paramIndex, paramValue, componentType, true); + setType(paramIndex, paramValue, componentType); } private void performPojoChecks(Class<?> type, String errorMsgPrefix) { @@ -132,11 +139,11 @@ } } - private void setType(int paramIndex, Object paramValue, Class<?> paramType, boolean isArrayType) { + private void setType(int paramIndex, Object paramValue, Class<?> paramType) { if (paramIndex >= params.length) { throw new IllegalArgumentException("Parameter index '" + paramIndex + "' out of range."); } - PreparedParameter param = new PreparedParameter(paramValue, paramType, isArrayType); + PreparedParameter param = new PreparedParameter(paramValue, paramType); params[paramIndex] = param; }
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/BasicDescriptorParser.java Wed Oct 02 18:14:39 2013 +0200 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/BasicDescriptorParser.java Wed Oct 02 15:07:46 2013 +0200 @@ -544,12 +544,11 @@ patchNode.setParameterIndex(placeHolderCount - 1); patchNode.setLHS(isLHS); // figure out the expected type - FreeVarTypeToken expectedType = getType(term.substring(1)); + Class<?> expectedType = getType(term.substring(1)); if (expectedType == null) { throw new DescriptorParsingException("Unknown type of free parameter: '" + term + "'"); } - patchNode.setType(expectedType.componentType); - patchNode.setArrayType(expectedType.isArrayType); + patchNode.setType(expectedType); node.setValue(patchNode); return; } @@ -609,7 +608,7 @@ return term.substring(1, term.length() - 1); } - private FreeVarTypeToken getType(String term) { + private Class<?> getType(String term) { if (term.equals("")) { // illegal type return null; @@ -617,53 +616,53 @@ // free variable types can have 1 or 2 characters. assert(term.length() > 0 && term.length() < 3); char switchChar = term.charAt(0); - FreeVarTypeToken typeToken = null; + Class<?> typeToken = null; switch (switchChar) { case 'i': { if (term.length() == 1) { - typeToken = new FreeVarTypeToken(Integer.class, false); + typeToken = int.class; } else if (term.length() == 2 && term.charAt(1) == '[') { - typeToken = new FreeVarTypeToken(Integer.class, true); + typeToken = int[].class; } break; } case 'l': { if (term.length() == 1) { - typeToken = new FreeVarTypeToken(Long.class, false); + typeToken = long.class; } else if (term.length() == 2 && term.charAt(1) == '[') { - typeToken = new FreeVarTypeToken(Long.class, true); + typeToken = long[].class; } break; } case 's': { if (term.length() == 1) { - typeToken = new FreeVarTypeToken(String.class, false); + typeToken = String.class; } else if (term.length() == 2 && term.charAt(1) == '[') { - typeToken = new FreeVarTypeToken(String.class, true); + typeToken = String[].class; } break; } case 'b': { if (term.length() == 1) { - typeToken = new FreeVarTypeToken(Boolean.class, false); + typeToken = boolean.class; } else if (term.length() == 2 && term.charAt(1) == '[') { - typeToken = new FreeVarTypeToken(Boolean.class, true); + typeToken = boolean[].class; } break; } case 'd': { if (term.length() == 1) { - typeToken = new FreeVarTypeToken(Double.class, false); + typeToken = double.class; } else if (term.length() == 2 && term.charAt(1) == '[') { - typeToken = new FreeVarTypeToken(Double.class, true); + typeToken = double[].class; } break; } case 'p': { if (term.length() == 1) { - typeToken = new FreeVarTypeToken(Pojo.class, false); + typeToken = Pojo.class; } else if (term.length() == 2 && term.charAt(1) == '[') { - typeToken = new FreeVarTypeToken(Pojo.class, true); + typeToken = Pojo[].class; } break; } @@ -822,15 +821,4 @@ throw new DescriptorParsingException("Unknown statement type: '" + tokens[currTokenIndex] + "'"); } } - - private static class FreeVarTypeToken { - - private final boolean isArrayType; - private final Class<?> componentType; - - private FreeVarTypeToken(Class<?> componentType, boolean isArrayType) { - this.isArrayType = isArrayType; - this.componentType = componentType; - } - } }
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/LimitExpression.java Wed Oct 02 18:14:39 2013 +0200 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/LimitExpression.java Wed Oct 02 15:07:46 2013 +0200 @@ -68,7 +68,7 @@ try { PreparedParameter param = params[unfinished.getParameterIndex()]; Class<?> typeClass = param.getType(); - if (typeClass != Integer.class || param.isArrayType()) { + if (typeClass != int.class) { String msg = "Invalid parameter type for limit expression. Expected integer!"; IllegalArgumentException e = new IllegalArgumentException(msg); throw e;
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/SortMember.java Wed Oct 02 18:14:39 2013 +0200 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/SortMember.java Wed Oct 02 15:07:46 2013 +0200 @@ -82,7 +82,7 @@ Unfinished unfinished = (Unfinished)getSortKey(); PreparedParameter p = params[unfinished.getParameterIndex()]; // Should only allow patching of ?s type NOT ?s[ - if (p.getType() != String.class || p.isArrayType()) { + if (p.getType() != String.class) { String msg = "Illegal parameter type for index " + unfinished.getParameterIndex() + ". Expected String!";
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/TerminalNode.java Wed Oct 02 18:14:39 2013 +0200 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/TerminalNode.java Wed Oct 02 15:07:46 2013 +0200 @@ -92,16 +92,24 @@ PreparedParameter param) throws IllegalPatchException { if (patch.getType() == Pojo.class) { // handle pojo case + Object value = param.getValue(); if (Pojo.class.isAssignableFrom(param.getType()) && - patch.isArrayType() == param.isArrayType()) { + value != null && !value.getClass().isArray()) { return; // pojo-type match: OK } // dead-end IllegalArgumentException iae = constructIllegalArgumentException(patch, param); throw new IllegalPatchException(iae); + } else if (patch.getType() == Pojo[].class) { + // handle pojo list case + Object value = param.getValue(); + if (Pojo.class.isAssignableFrom(param.getType()) && value != null + && value.getClass().isArray()) { + return; // pojo-list type match: OK + } } else { // primitive types or primitive list types - if (param.getType() != patch.getType() || param.isArrayType() != patch.isArrayType()) { + if (param.getType() != patch.getType()) { IllegalArgumentException iae = constructIllegalArgumentException(patch, param); throw new IllegalPatchException(iae); } @@ -111,11 +119,14 @@ private IllegalArgumentException constructIllegalArgumentException( UnfinishedValueNode patch, PreparedParameter param) { - String patchArrayPrefix = patch.isArrayType() ? "[" : ""; - String paramArrayPrefix = param.isArrayType() ? "[" : ""; + Object value = param.getValue(); + String paramArrayPrefix = ""; + if (value != null && value.getClass().isArray()) { + paramArrayPrefix = "["; + } String msg = TerminalNode.class.getSimpleName() + " invalid type when attempting to patch. Expected " - + patchArrayPrefix + patch.getType().getName() + " but was " + + patch.getType().getName() + " but was " + paramArrayPrefix + param.getType().getName(); IllegalArgumentException iae = new IllegalArgumentException(msg); return iae;
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/UnfinishedValueNode.java Wed Oct 02 18:14:39 2013 +0200 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/statement/UnfinishedValueNode.java Wed Oct 02 15:07:46 2013 +0200 @@ -54,9 +54,6 @@ private boolean isLHS; // Specifies the expected (component) type of this free parameter. private Class<?> type; - // Specifies if the free parameter is an array type. If so, the - // type instance variable represents the component type. - private boolean isArrayType; Class<?> getType() { return type; @@ -83,14 +80,6 @@ public void setParameterIndex(int parameterIndex) { this.parameterIndex = parameterIndex; } - - public boolean isArrayType() { - return isArrayType; - } - - public void setArrayType(boolean isArrayType) { - this.isArrayType = isArrayType; - } @Override public String toString() { @@ -109,13 +98,12 @@ } UnfinishedValueNode o = (UnfinishedValueNode)other; return basics && Objects.equals(isLHS(), o.isLHS) && - Objects.equals(getType(), o.getType()) && - isArrayType() == o.isArrayType(); + Objects.equals(getType(), o.getType()); } @Override public int hashCode() { - return Objects.hash(getParameterIndex(), isLHS(), getType(), isArrayType()); + return Objects.hash(getParameterIndex(), isLHS(), getType()); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/core/PreparedParamentersTest.java Wed Oct 02 15:07:46 2013 +0200 @@ -0,0 +1,137 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.storage.core; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import org.junit.Test; + +import com.redhat.thermostat.storage.model.AgentInformation; + +public class PreparedParamentersTest { + + @Test + public void cannotSetNullPojo() { + PreparedParameters params = new PreparedParameters(1); + try { + params.setPojo(0, null); + fail("should not be able to set null Pojo"); + } catch (NullPointerException e) { + // passs + } + } + + @Test + public void cannotSetNullPojoList() { + PreparedParameters params = new PreparedParameters(1); + try { + params.setPojoList(0, null); + fail("should not be able to set null Pojo list"); + } catch (NullPointerException e) { + // passs + } + } + + @Test + public void canSetPojoType() { + PreparedParameters params = new PreparedParameters(1); + AgentInformation info = new AgentInformation(); + params.setPojo(0, info); + assertEquals(AgentInformation.class, params.getParams()[0].getType()); + assertEquals(info, params.getParams()[0].getValue()); + } + + @Test + public void canSetPojoListType() { + PreparedParameters params = new PreparedParameters(1); + AgentInformation info = new AgentInformation(); + params.setPojoList(0, new AgentInformation[] { info }); + PreparedParameter p = params.getParams()[0]; + assertEquals("Type should be component type", AgentInformation.class, p.getType()); + assertEquals(info, ((AgentInformation[])p.getValue())[0]); + } + + @Test + public void testTypeInt() { + PreparedParameters params = new PreparedParameters(1); + params.setInt(0, -1); + assertEquals(int.class, params.getParams()[0].getType()); + } + + @Test + public void testTypeIntList() { + PreparedParameters params = new PreparedParameters(1); + params.setIntList(0, new int[] { -1 }); + assertEquals(int[].class, params.getParams()[0].getType()); + } + + @Test + public void testTypeLong() { + PreparedParameters params = new PreparedParameters(1); + params.setLong(0, -1); + assertEquals(long.class, params.getParams()[0].getType()); + } + + @Test + public void testTypeLongList() { + PreparedParameters params = new PreparedParameters(1); + params.setLongList(0, new long[] { -1 }); + assertEquals(long[].class, params.getParams()[0].getType()); + } + + @Test + public void testTypeBoolList() { + PreparedParameters params = new PreparedParameters(1); + params.setBooleanList(0, new boolean[] { true } ); + assertEquals(boolean[].class, params.getParams()[0].getType()); + } + + @Test + public void testTypeDouble() { + PreparedParameters params = new PreparedParameters(1); + params.setDouble(0, Math.E); + assertEquals(double.class, params.getParams()[0].getType()); + } + + @Test + public void testTypeDoubleList() { + PreparedParameters params = new PreparedParameters(1); + params.setDoubleList(0, new double[] { Math.E }); + assertEquals(double[].class, params.getParams()[0].getType()); + } +}
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/BasicDescriptorParserTest.java Wed Oct 02 18:14:39 2013 +0200 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/BasicDescriptorParserTest.java Wed Oct 02 15:07:46 2013 +0200 @@ -221,7 +221,7 @@ String descrString = "QUERY " + AgentInfoDAO.CATEGORY.getName() + " WHERE 'a' != ?d"; UnfinishedValueNode unfinished = new UnfinishedValueNode(); unfinished.setLHS(false); - unfinished.setType(Double.class); + unfinished.setType(double.class); unfinished.setParameterIndex(0); doTestType(descrString, unfinished, 1); } @@ -236,8 +236,7 @@ String descString = "ADD " + AgentInfoDAO.CATEGORY.getName() + " SET 'a' = ?s["; UnfinishedValueNode unfinished = new UnfinishedValueNode(); unfinished.setLHS(false); - unfinished.setType(String.class); - unfinished.setArrayType(true); + unfinished.setType(String[].class); unfinished.setParameterIndex(0); doListTypeTest(descString, unfinished); } @@ -252,8 +251,7 @@ String descString = "ADD " + AgentInfoDAO.CATEGORY.getName() + " SET 'a' = ?d["; UnfinishedValueNode unfinished = new UnfinishedValueNode(); unfinished.setLHS(false); - unfinished.setType(Double.class); - unfinished.setArrayType(true); + unfinished.setType(double[].class); unfinished.setParameterIndex(0); doListTypeTest(descString, unfinished); } @@ -268,8 +266,7 @@ String descString = "ADD " + AgentInfoDAO.CATEGORY.getName() + " SET 'a' = ?i["; UnfinishedValueNode unfinished = new UnfinishedValueNode(); unfinished.setLHS(false); - unfinished.setType(Integer.class); - unfinished.setArrayType(true); + unfinished.setType(int[].class); unfinished.setParameterIndex(0); doListTypeTest(descString, unfinished); } @@ -284,8 +281,7 @@ String descString = "ADD " + AgentInfoDAO.CATEGORY.getName() + " SET 'a' = ?b["; UnfinishedValueNode unfinished = new UnfinishedValueNode(); unfinished.setLHS(false); - unfinished.setType(Boolean.class); - unfinished.setArrayType(true); + unfinished.setType(boolean[].class); unfinished.setParameterIndex(0); doListTypeTest(descString, unfinished); } @@ -300,8 +296,7 @@ String descString = "ADD " + AgentInfoDAO.CATEGORY.getName() + " SET 'a' = ?l["; UnfinishedValueNode unfinished = new UnfinishedValueNode(); unfinished.setLHS(false); - unfinished.setType(Long.class); - unfinished.setArrayType(true); + unfinished.setType(long[].class); unfinished.setParameterIndex(0); doListTypeTest(descString, unfinished); } @@ -331,8 +326,7 @@ String descString = "ADD " + AgentInfoDAO.CATEGORY.getName() + " SET 'a' = ?p["; UnfinishedValueNode unfinished = new UnfinishedValueNode(); unfinished.setLHS(false); - unfinished.setType(Pojo.class); - unfinished.setArrayType(true); + unfinished.setType(Pojo[].class); unfinished.setParameterIndex(0); doListTypeTest(descString, unfinished); } @@ -371,7 +365,7 @@ String descrString = "QUERY " + AgentInfoDAO.CATEGORY.getName() + " WHERE 'a' != ?i"; UnfinishedValueNode unfinished = new UnfinishedValueNode(); unfinished.setLHS(false); - unfinished.setType(Integer.class); + unfinished.setType(int.class); unfinished.setParameterIndex(0); doTestType(descrString, unfinished, 1); } @@ -381,7 +375,7 @@ String descrString = "QUERY " + AgentInfoDAO.CATEGORY.getName() + " WHERE 'a' != ?l"; UnfinishedValueNode unfinished = new UnfinishedValueNode(); unfinished.setLHS(false); - unfinished.setType(Long.class); + unfinished.setType(long.class); unfinished.setParameterIndex(0); doTestType(descrString, unfinished, 1); } @@ -391,7 +385,7 @@ String descrString = "QUERY " + AgentInfoDAO.CATEGORY.getName() + " WHERE 'a' != ?b"; UnfinishedValueNode unfinished = new UnfinishedValueNode(); unfinished.setLHS(false); - unfinished.setType(Boolean.class); + unfinished.setType(boolean.class); unfinished.setParameterIndex(0); doTestType(descrString, unfinished, 1); } @@ -540,7 +534,7 @@ lessThan.setLeftChild(e); UnfinishedValueNode f = new UnfinishedValueNode(); f.setParameterIndex(0); - f.setType(Integer.class); + f.setType(int.class); f.setLHS(false); TerminalNode fReal = new TerminalNode(lessThan); fReal.setValue(f); @@ -668,7 +662,7 @@ lessThan.setLeftChild(e); UnfinishedValueNode f = new UnfinishedValueNode(); f.setParameterIndex(0); - f.setType(Integer.class); + f.setType(int.class); f.setLHS(false); TerminalNode fReal = new TerminalNode(lessThan); fReal.setValue(f); @@ -1029,7 +1023,7 @@ UnfinishedValueNode patch2 = new UnfinishedValueNode(); patch2.setParameterIndex(1); patch2.setLHS(false); - patch2.setType(Integer.class); + patch2.setType(int.class); TerminalNode y = new TerminalNode(greaterEqual); y.setValue(patch2); greaterEqual.setRightChild(y); @@ -1227,7 +1221,7 @@ UnfinishedValueNode patch2 = new UnfinishedValueNode(); patch2.setLHS(false); patch2.setParameterIndex(2); - patch2.setType(Boolean.class); + patch2.setType(boolean.class); TerminalNode y = new TerminalNode(lessThan); y.setValue(patch2); lessThan.setRightChild(y); @@ -1530,7 +1524,7 @@ UnfinishedValueNode node = new UnfinishedValueNode(); node.setParameterIndex(1); node.setLHS(false); - node.setType(Integer.class); + node.setType(int.class); fooVal.setValue(node); equality.setRightChild(fooVal); assertTrue(WhereExpressions.equals(expectedWhere, where));
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/LimitExpressionTest.java Wed Oct 02 18:14:39 2013 +0200 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/LimitExpressionTest.java Wed Oct 02 15:07:46 2013 +0200 @@ -62,8 +62,7 @@ @Test public void canPatchWithInt() { PreparedParameter p = new PreparedParameter(); - p.setType(Integer.class); - p.setArrayType(false); + p.setType(int.class); p.setValue(3); PatchedLimitExpression pLimit = null; @@ -80,8 +79,7 @@ @Test public void rejectPatchWithIntList() { PreparedParameter p = new PreparedParameter(); - p.setType(Integer.class); - p.setArrayType(true); + p.setType(int[].class); p.setValue(new int[] { 3 }); try { @@ -97,7 +95,6 @@ public void rejectPatchWithString() { PreparedParameter p = new PreparedParameter(); p.setType(String.class); - p.setArrayType(false); p.setValue("foo"); try {
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/ParsedStatementImplTest.java Wed Oct 02 18:14:39 2013 +0200 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/ParsedStatementImplTest.java Wed Oct 02 15:07:46 2013 +0200 @@ -119,7 +119,7 @@ TerminalNode d = new TerminalNode(rightEqual); UnfinishedValueNode dPatch = new UnfinishedValueNode(); dPatch.setParameterIndex(1); - dPatch.setType(Integer.class); + dPatch.setType(int.class); d.setValue(dPatch); rightEqual.setRightChild(d); suffixExpn.setWhereExpn(expn); @@ -176,7 +176,7 @@ TerminalNode b = new TerminalNode(and); UnfinishedValueNode bPatch = new UnfinishedValueNode(); bPatch.setParameterIndex(0); - bPatch.setType(Boolean.class); + bPatch.setType(boolean.class); b.setValue(bPatch); and.setLeftChild(a); and.setRightChild(b); @@ -244,7 +244,7 @@ TerminalNode b = new TerminalNode(and); UnfinishedValueNode bPatch = new UnfinishedValueNode(); bPatch.setParameterIndex(1); - bPatch.setType(Boolean.class); + bPatch.setType(boolean.class); b.setValue(bPatch); and.setLeftChild(a); and.setRightChild(b); @@ -341,7 +341,7 @@ UnfinishedValueNode timeStampUnfinished = new UnfinishedValueNode(); timeStampUnfinished.setLHS(false); timeStampUnfinished.setParameterIndex(1); - timeStampUnfinished.setType(Long.class); + timeStampUnfinished.setType(long.class); timeStampVal.setValue(timeStampUnfinished); fooTimeStamp.setValue(timeStampVal); setList.addValue(fooTimeStamp); @@ -396,8 +396,7 @@ TerminalNode somePropertyVal = new TerminalNode(null); UnfinishedValueNode unfinishedPojoList = new UnfinishedValueNode(); unfinishedPojoList.setLHS(false); - unfinishedPojoList.setType(Pojo.class); - unfinishedPojoList.setArrayType(true); + unfinishedPojoList.setType(Pojo[].class); unfinishedPojoList.setParameterIndex(0); somePropertyVal.setValue(unfinishedPojoList); SetListValue value = new SetListValue(); @@ -476,7 +475,7 @@ UnfinishedValueNode timeStampUnfinished = new UnfinishedValueNode(); timeStampUnfinished.setLHS(false); timeStampUnfinished.setParameterIndex(1); - timeStampUnfinished.setType(Long.class); + timeStampUnfinished.setType(long.class); timeStampVal.setValue(timeStampUnfinished); fooTimeStamp.setValue(timeStampVal); setList.addValue(fooTimeStamp); @@ -491,7 +490,7 @@ TerminalNode fooPatch = new TerminalNode(equals); UnfinishedValueNode patch2 = new UnfinishedValueNode(); patch2.setLHS(false); - patch2.setType(Integer.class); + patch2.setType(int.class); patch2.setParameterIndex(2); fooPatch.setValue(patch2); TerminalNode foo = new TerminalNode(equals); @@ -558,7 +557,7 @@ TerminalNode fooPatch = new TerminalNode(equals); UnfinishedValueNode patch2 = new UnfinishedValueNode(); patch2.setLHS(false); - patch2.setType(Integer.class); + patch2.setType(int.class); patch2.setParameterIndex(1); fooPatch.setValue(patch2); TerminalNode foo = new TerminalNode(equals);
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/SortMemberTest.java Wed Oct 02 18:14:39 2013 +0200 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/SortMemberTest.java Wed Oct 02 15:07:46 2013 +0200 @@ -66,7 +66,6 @@ public void testPatchWithString() { PreparedParameter p = new PreparedParameter(); p.setType(String.class); - p.setArrayType(false); p.setValue("foo"); PatchedSortMemberExpression expn = null; try { @@ -83,8 +82,7 @@ @Test public void rejectPatchWithStringList() { PreparedParameter p = new PreparedParameter(); - p.setType(String.class); - p.setArrayType(true); + p.setType(String[].class); p.setValue(new String[] { "foo" }); try { member.patch(new PreparedParameter[] { p }); @@ -98,8 +96,7 @@ @Test public void rejectPatchWithNumber() { PreparedParameter p = new PreparedParameter(); - p.setType(Integer.class); - p.setArrayType(false); + p.setType(int.class); p.setValue(1); try { member.patch(new PreparedParameter[] { p });
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/TerminalNodeTest.java Wed Oct 02 18:14:39 2013 +0200 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/statement/TerminalNodeTest.java Wed Oct 02 15:07:46 2013 +0200 @@ -58,13 +58,11 @@ unfinished.setLHS(false); unfinished.setParameterIndex(0); unfinished.setType(String.class); - unfinished.setArrayType(false); node.setValue(unfinished); PreparedParameter p = new PreparedParameter(); p.setType(String.class); - p.setArrayType(false); p.setValue("foo-bar"); PatchedWhereExpression expn = null; @@ -86,13 +84,11 @@ unfinished.setLHS(false); unfinished.setParameterIndex(0); unfinished.setType(Pojo.class); - unfinished.setArrayType(false); node.setValue(unfinished); PreparedParameter p = new PreparedParameter(); p.setType(AgentInformation.class); - p.setArrayType(false); AgentInformation info = new AgentInformation("foo-bar"); p.setValue(info); @@ -115,13 +111,11 @@ unfinished.setLHS(false); unfinished.setParameterIndex(0); unfinished.setType(String.class); - unfinished.setArrayType(false); node.setValue(unfinished); PreparedParameter p = new PreparedParameter(); - p.setType(String.class); - p.setArrayType(true); + p.setType(String[].class); p.setValue(new String[] { "foo-bar" }); try { @@ -140,13 +134,11 @@ unfinished.setLHS(false); unfinished.setParameterIndex(0); unfinished.setType(Pojo.class); - unfinished.setArrayType(false); node.setValue(unfinished); PreparedParameter p = new PreparedParameter(); p.setType(AgentInformation.class); - p.setArrayType(true); AgentInformation info = new AgentInformation("testing"); p.setValue(new AgentInformation[] { info }); @@ -165,14 +157,12 @@ UnfinishedValueNode unfinished = new UnfinishedValueNode(); unfinished.setLHS(false); unfinished.setParameterIndex(0); - unfinished.setType(Integer.class); - unfinished.setArrayType(false); + unfinished.setType(int.class); node.setValue(unfinished); PreparedParameter p = new PreparedParameter(); - p.setType(String.class); - p.setArrayType(true); + p.setType(String[].class); p.setValue(new String[] { "foo-bar" }); try {
--- a/web/client/src/test/java/com/redhat/thermostat/web/client/internal/WebStorageTest.java Wed Oct 02 18:14:39 2013 +0200 +++ b/web/client/src/test/java/com/redhat/thermostat/web/client/internal/WebStorageTest.java Wed Oct 02 15:07:46 2013 +0200 @@ -414,7 +414,6 @@ stmt.setString(0, "fluff"); assertEquals("fluff", params.getParams()[0].getValue()); assertEquals(String.class, params.getParams()[0].getType()); - assertFalse(params.getParams()[0].isArrayType()); prepareServer(gson.toJson(PreparedStatementResponseCode.WRITE_GENERIC_FAILURE));
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/PreparedParameterSerializer.java Wed Oct 02 18:14:39 2013 +0200 +++ b/web/common/src/main/java/com/redhat/thermostat/web/common/PreparedParameterSerializer.java Wed Oct 02 15:07:46 2013 +0200 @@ -65,47 +65,56 @@ private static final Logger logger = LoggingUtils.getLogger(PreparedParameterSerializer.class); private static final String PROP_TYPE = "type"; - private static final String PROP_IS_ARRAY_TYPE = "isArray"; private static final String PROP_VALUE = "value"; - private static final Set<Class<?>> WRAPPER_CLASSES; - // maps wrapper classes to primitives: - // Integer.class => int.class , Double.class => double.class, etc. - private static final Map<Class<?>, Class<?>> TO_PRIMITIVE_ARRAY_MAP; + private static final Set<Class<?>> VALID_CLASSES; + private static final Set<Class<?>> PRIMITIVES_NOT_ALLOWING_NULL_VAL; + // maps type names to classes: + // "int" => int.class , "double" => double.class, "[I" => int[].class + // and so on. + private static final Map<String, Class<?>> CLASSES_LOOKUP_TABLE; static { - WRAPPER_CLASSES = new HashSet<>(); - TO_PRIMITIVE_ARRAY_MAP = new HashMap<>(); - WRAPPER_CLASSES.add(Integer.class); - TO_PRIMITIVE_ARRAY_MAP.put(Integer.class, int.class); - WRAPPER_CLASSES.add(Long.class); - TO_PRIMITIVE_ARRAY_MAP.put(Long.class, long.class); - WRAPPER_CLASSES.add(Boolean.class); - TO_PRIMITIVE_ARRAY_MAP.put(Boolean.class, boolean.class); - WRAPPER_CLASSES.add(Double.class); - TO_PRIMITIVE_ARRAY_MAP.put(Double.class, double.class); - + VALID_CLASSES = new HashSet<>(); + CLASSES_LOOKUP_TABLE = new HashMap<>(); + CLASSES_LOOKUP_TABLE.put(int.class.getName(), int.class); + CLASSES_LOOKUP_TABLE.put(long.class.getName(), long.class); + CLASSES_LOOKUP_TABLE.put(boolean.class.getName(), boolean.class); + CLASSES_LOOKUP_TABLE.put(double.class.getName(), double.class); + CLASSES_LOOKUP_TABLE.put(String.class.getName(), String.class); + CLASSES_LOOKUP_TABLE.put(int[].class.getName(), int[].class); + CLASSES_LOOKUP_TABLE.put(long[].class.getName(), long[].class); + CLASSES_LOOKUP_TABLE.put(boolean[].class.getName(), boolean[].class); + CLASSES_LOOKUP_TABLE.put(double[].class.getName(), double[].class); + CLASSES_LOOKUP_TABLE.put(String[].class.getName(), String[].class); + VALID_CLASSES.addAll(CLASSES_LOOKUP_TABLE.values()); + PRIMITIVES_NOT_ALLOWING_NULL_VAL = new HashSet<>(); + PRIMITIVES_NOT_ALLOWING_NULL_VAL.add(int.class); + PRIMITIVES_NOT_ALLOWING_NULL_VAL.add(long.class); + PRIMITIVES_NOT_ALLOWING_NULL_VAL.add(boolean.class); + PRIMITIVES_NOT_ALLOWING_NULL_VAL.add(double.class); } @Override public JsonElement serialize(PreparedParameter param, Type type, JsonSerializationContext ctxt) { JsonObject result = new JsonObject(); - JsonElement valueElem = serializeValue(ctxt, param.getValue(), param.getType(), param.isArrayType()); + JsonElement valueElem = serializeValue(ctxt, param.getValue(), param.getType()); result.add(PROP_VALUE, valueElem); JsonPrimitive typeElem = new JsonPrimitive(param.getType().getName()); result.add(PROP_TYPE, typeElem); - JsonPrimitive arrayType = new JsonPrimitive(param.isArrayType()); - result.add(PROP_IS_ARRAY_TYPE, arrayType); return result; } - private JsonElement serializeValue(JsonSerializationContext ctxt, Object value, Class<?> compType, boolean isArray) { + private JsonElement serializeValue(JsonSerializationContext ctxt, Object value, Class<?> type) { JsonElement element; - if (isArray) { - Class<?> arrayType = Array.newInstance(compType, 0).getClass(); - element = ctxt.serialize(value, arrayType); + // Special case pojo list types: the value class is of array type for + // them, but the type is the component type. + if (value != null && value.getClass().isArray() && !type.isArray()) { + assert(Pojo.class.isAssignableFrom(type)); + Class<?> arrayType = Array.newInstance(type, 0).getClass(); + element = ctxt.serialize(value, arrayType); } else { - element = ctxt.serialize(value, compType); + element = ctxt.serialize(value, type); } return element; } @@ -120,53 +129,60 @@ Class<?> typeVal = deserializeTypeVal(className); validateSaneClassName(typeVal); JsonElement valueElement = jsonElem.getAsJsonObject().get(PROP_VALUE); - JsonElement isArrayElement = jsonElem.getAsJsonObject().get(PROP_IS_ARRAY_TYPE); - boolean isArray = isArrayElement.getAsBoolean(); - Object value = deserializeValue(ctxt, valueElement, typeVal, isArray); + Object value = deserializeValue(ctxt, valueElement, typeVal); PreparedParameter param = new PreparedParameter(); param.setType(typeVal); param.setValue(value); - param.setArrayType(isArray); return param; } private Class<?> deserializeTypeVal(String className) { Class<?> typeVal = null; - try { - typeVal = Class.forName(className); - } catch (ClassNotFoundException e) { - logger.log(Level.WARNING, "Failed to resolve class type for '" - + className + "'."); + if (CLASSES_LOOKUP_TABLE.containsKey(className)) { + typeVal = CLASSES_LOOKUP_TABLE.get(className); + } else { + try { + // We need this for Pojo + Pojo list type params. For pojo + // lists the name we get passed is the component type of the + // array. + typeVal = Class.forName(className); + } catch (ClassNotFoundException e) { + logger.log(Level.WARNING, "Failed to resolve class type for '" + + className + "'."); + } } - ; return typeVal; } private Object deserializeValue(JsonDeserializationContext ctxt, - JsonElement valueElement, Class<?> valType, boolean isArray) { - if (!isArray) { - // By telling GSON the type, we get the correctly casted - // value back. - return ctxt.deserialize(valueElement, valType); - } else { + JsonElement valueElement, Class<?> valType) { + // special case for Pojo/Pojo list types. In that case, the valType + // is the component type for arrays. In order to distinguish pojo + // lists from pojos, we use JSON's array info about the value element. + if (valueElement != null && valueElement.isJsonArray() && !valType.isArray()) { + assert(Pojo.class.isAssignableFrom(valType)); Class<?> arrayType = Array.newInstance(valType, 0).getClass(); - Object array; - // Make sure we get primitive type arrays if this is an array type - // of one of the wrapped primitives. - if (WRAPPER_CLASSES.contains(valType)) { - Class<?> primType = Array.newInstance(TO_PRIMITIVE_ARRAY_MAP.get(valType), 0).getClass(); - array = ctxt.deserialize(valueElement, primType); - } else { - array = ctxt.deserialize(valueElement, arrayType); - } - return array; + return ctxt.deserialize(valueElement, arrayType); + } else { + Object value = ctxt.deserialize(valueElement, valType); + validatePrimitivesForNull(value, valType); + return value; } } - // Allow wrapper classes, String + Pojo types, refuse everything else + private void validatePrimitivesForNull(Object value, Class<?> valType) { + if (PRIMITIVES_NOT_ALLOWING_NULL_VAL.contains(valType) && value == null) { + // illegal value for primitive type. according to JLS spec they all + // have default values and are never null. + throw new IllegalStateException( valType + " primitive" + + " does not accept a null value!"); + } + } + + // Allow valid classes + Pojo types, refuse everything else private void validateSaneClassName(Class<?> clazz) { - if (WRAPPER_CLASSES.contains(clazz) || - String.class == clazz || + // isAssignableFrom throws NPE if clazz is null. + if (VALID_CLASSES.contains(clazz) || Pojo.class.isAssignableFrom(clazz)) { return; }
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/PreparedParameterSerializerTest.java Wed Oct 02 18:14:39 2013 +0200 +++ b/web/common/src/test/java/com/redhat/thermostat/web/common/PreparedParameterSerializerTest.java Wed Oct 02 15:07:46 2013 +0200 @@ -37,7 +37,6 @@ package com.redhat.thermostat.web.common; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -69,44 +68,34 @@ @Test public void canDeserializeBasic() { // String - String jsonStr = "{ \"type\": \"java.lang.String\" , \"value\": \"testing\" , \"isArray\": false}"; + String jsonStr = "{ \"type\": \"java.lang.String\" , \"value\": \"testing\" }"; PreparedParameter param = gson.fromJson(jsonStr, PreparedParameter.class); assertEquals(String.class, param.getType()); assertEquals("testing", param.getValue()); - assertFalse(param.isArrayType()); // Integer - jsonStr = "{ \"type\": \"java.lang.Integer\" , \"value\": -1 , \"isArray\": false}"; + jsonStr = "{ \"type\": \"int\" , \"value\": -1}"; param = gson.fromJson(jsonStr, PreparedParameter.class); - assertEquals(Integer.class, param.getType()); - assertTrue(param.getValue() instanceof Integer); + assertEquals(int.class, param.getType()); assertEquals(-1, param.getValue()); - assertFalse(param.isArrayType()); // Long - jsonStr = "{ \"type\": \"java.lang.Long\" , \"value\": -10 , \"isArray\": false}"; + jsonStr = "{ \"type\": \"long\" , \"value\": -10}"; param = gson.fromJson(jsonStr, PreparedParameter.class); - assertEquals(Long.class, param.getType()); - assertTrue(param.getValue() instanceof Long); + assertEquals(long.class, param.getType()); assertEquals(-10L, param.getValue()); - assertFalse(param.isArrayType()); - jsonStr = "{ \"type\": \"java.lang.Long\" , \"value\": 30000000003 , \"isArray\": false}"; + jsonStr = "{ \"type\": \"long\" , \"value\": 30000000003}"; param = gson.fromJson(jsonStr, PreparedParameter.class); - assertEquals(Long.class, param.getType()); - assertTrue(param.getValue() instanceof Long); + assertEquals(long.class, param.getType()); assertEquals(30000000003L, param.getValue()); - assertFalse(param.isArrayType()); // Boolean - jsonStr = "{ \"type\": \"java.lang.Boolean\" , \"value\": true , \"isArray\": false}"; + jsonStr = "{ \"type\": \"boolean\" , \"value\": true}"; param = gson.fromJson(jsonStr, PreparedParameter.class); - assertEquals(Boolean.class, param.getType()); - assertTrue(param.getValue() instanceof Boolean); + assertEquals(boolean.class, param.getType()); assertEquals(true, param.getValue()); - assertFalse(param.isArrayType()); // String[] String strArrayVal = "[ \"testing1\", \"testing2\", \"3\" ]"; - jsonStr = "{ \"type\": \"java.lang.String\" , \"value\": " + strArrayVal + " , \"isArray\": true}"; + jsonStr = "{ \"type\": \"[Ljava.lang.String;\" , \"value\": " + strArrayVal + "}"; param = gson.fromJson(jsonStr, PreparedParameter.class); - assertEquals(String.class, param.getType()); - assertTrue(param.isArrayType()); + assertEquals(String[].class, param.getType()); assertTrue(param.getValue() instanceof String[]); String[] vals = (String[])param.getValue(); assertEquals(3, vals.length); @@ -116,6 +105,90 @@ } @Test + public void allowsBooleanListNullDeserialization() { + String jsonStr = "{ \"type\": \"[Z\" , \"value\": null}"; + PreparedParameter p = gson.fromJson(jsonStr, PreparedParameter.class); + assertEquals(boolean[].class, p.getType()); + assertEquals(null, p.getValue()); + } + + @Test + public void allowsIntListNullDeserialization() { + String jsonStr = "{ \"type\": \"[I\" , \"value\": null}"; + PreparedParameter p = gson.fromJson(jsonStr, PreparedParameter.class); + assertEquals(int[].class, p.getType()); + assertEquals(null, p.getValue()); + } + + @Test + public void allowsLongListNullDeserialization() { + String jsonStr = "{ \"type\": \"[J\" , \"value\": null}"; + PreparedParameter p = gson.fromJson(jsonStr, PreparedParameter.class); + assertEquals(long[].class, p.getType()); + assertEquals(null, p.getValue()); + } + + @Test + public void allowsDoubleListNullDeserialization() { + String jsonStr = "{ \"type\": \"[D\" , \"value\": null}"; + PreparedParameter p = gson.fromJson(jsonStr, PreparedParameter.class); + assertEquals(double[].class, p.getType()); + assertEquals(null, p.getValue()); + } + + @Test + public void allowsStringNullDeserialization() { + String jsonStr = "{ \"type\": \"java.lang.String\" , \"value\": null}"; + PreparedParameter p = gson.fromJson(jsonStr, PreparedParameter.class); + assertEquals(String.class, p.getType()); + assertEquals(null, p.getValue()); + } + + @Test + public void allowsStringListNullDeserialization() { + String jsonStr = "{ \"type\": \"[Ljava.lang.String;\" , \"value\": null}"; + PreparedParameter p = gson.fromJson(jsonStr, PreparedParameter.class); + assertEquals(String[].class, p.getType()); + assertEquals(null, p.getValue()); + } + + @Test + public void rejectNullForBooleanPrimitive() { + String jsonStr = "{ \"type\": \"boolean\" , \"value\": null}"; + doPrimitiveNullTest(jsonStr, "boolean"); + } + + @Test + public void rejectNullForIntPrimitive() { + String jsonStr = "{ \"type\": \"int\" , \"value\": null}"; + doPrimitiveNullTest(jsonStr, "int"); + } + + @Test + public void rejectNullForDoublePrimitive() { + String jsonStr = "{ \"type\": \"double\" , \"value\": null}"; + doPrimitiveNullTest(jsonStr, "double"); + } + + @Test + public void rejectNullForLongPrimitive() { + String jsonStr = "{ \"type\": \"long\" , \"value\": null}"; + doPrimitiveNullTest(jsonStr, "long"); + } + + private void doPrimitiveNullTest(String jsonStr, String typeName) { + try { + gson.fromJson(jsonStr, PreparedParameter.class); + // The Java language spec does not permit this + fail(typeName + " null primitive should not deserialize"); + } catch (Exception e) { + // pass + Throwable cause = e.getCause(); + assertEquals(typeName + " primitive does not accept a null value!", cause.getMessage()); + } + } + + @Test public void failsDeserializationWrongTypeClass() { String jsonStr = "{ \"type\": \"java.io.File\" , \"value\": true}"; try { @@ -129,41 +202,88 @@ } @Test + public void failsDeserializationIfStringForInt() { + String jsonStr = "{ \"type\": \"int\" , \"value\":\"testing\"}"; + try { + gson.fromJson(jsonStr, PreparedParameter.class); + fail("should have failed to serialize"); + } catch (Exception e) { + // pass + Throwable cause = e.getCause(); + assertTrue(cause instanceof NumberFormatException); + } + } + + @Test + public void failsDeserializationIfBooleanForInt() { + String jsonStr = "{ \"type\": \"int\" , \"value\": true}"; + try { + gson.fromJson(jsonStr, PreparedParameter.class); + fail("should have failed to serialize"); + } catch (Exception e) { + // pass + Throwable cause = e.getCause(); + assertTrue(cause instanceof IllegalStateException); + } + } + + @Test + public void failsDeserializationIfIntForIntList() { + String jsonStr = "{ \"type\": \"[I\" , \"value\": -1}"; + try { + gson.fromJson(jsonStr, PreparedParameter.class); + fail("should have failed to serialize"); + } catch (Exception e) { + // pass + Throwable cause = e.getCause(); + assertTrue(cause instanceof IllegalStateException); + } + } + + @Test + public void failsDeserializationIfDoubleForInt() { + String jsonStr = "{ \"type\": \"int\" , \"value\": -1.3}"; + try { + gson.fromJson(jsonStr, PreparedParameter.class); + fail("should have failed to serialize"); + } catch (Exception e) { + // pass + Throwable cause = e.getCause(); + assertTrue(cause instanceof NumberFormatException); + } + } + + @Test public void canSerializeBasic() { // String - String expected = "{\"value\":\"testing\",\"type\":\"java.lang.String\",\"isArray\":false}"; + String expected = "{\"value\":\"testing\",\"type\":\"java.lang.String\"}"; PreparedParameter param = new PreparedParameter(); param.setType(String.class); param.setValue("testing"); - param.setArrayType(false); String actual = gson.toJson(param); assertEquals(expected, actual); // Integer - expected = "{\"value\":-1,\"type\":\"java.lang.Integer\",\"isArray\":false}"; - param.setType(Integer.class); + expected = "{\"value\":-1,\"type\":\"int\"}"; + param.setType(int.class); param.setValue(-1); - param.setArrayType(false); actual = gson.toJson(param); assertEquals(expected, actual); // Long - expected = "{\"value\":30000000003,\"type\":\"java.lang.Long\",\"isArray\":false}"; - param.setType(Long.class); + expected = "{\"value\":30000000003,\"type\":\"long\"}"; + param.setType(long.class); param.setValue(30000000003L); - param.setArrayType(false); actual = gson.toJson(param); assertEquals(expected, actual); // boolean - expected = "{\"value\":true,\"type\":\"java.lang.Boolean\",\"isArray\":false}"; - param.setType(Boolean.class); + expected = "{\"value\":true,\"type\":\"boolean\"}"; + param.setType(boolean.class); param.setValue(true); - param.setArrayType(false); actual = gson.toJson(param); assertEquals(expected, actual); // String[] String strArrayVal = "[\"testing1\",\"testing2\",\"3\"]"; - expected = "{\"value\":" + strArrayVal + ",\"type\":\"java.lang.String\",\"isArray\":true}"; - param.setType(String.class); - param.setArrayType(true); + expected = "{\"value\":" + strArrayVal + ",\"type\":\"[Ljava.lang.String;\"}"; + param.setType(String[].class); String[] array = new String[] { "testing1", "testing2", "3" }; @@ -175,9 +295,8 @@ @Test public void canSerializeDeserializeInteger() { PreparedParameter expected = new PreparedParameter(); - expected.setType(Integer.class); + expected.setType(int.class); expected.setValue(3); - expected.setArrayType(false); String jsonStr = gson.toJson(expected, PreparedParameter.class); assertParameterEquals(expected, jsonStr); } @@ -185,13 +304,8 @@ @Test public void canSerializeDeserializeIntegerArray() { PreparedParameter expected = new PreparedParameter(); - expected.setType(Integer.class); - // it's important for the expected type to be of primitive array type, - // rather than Integer[]. we want the serializer to deserialize to - // primitive types if possible. asserted in method assertParameterEquals() - // Note that model classes use primitive array types as well. + expected.setType(int[].class); expected.setValue(new int[] { 0, 3, 20 }); - expected.setArrayType(true); String jsonStr = gson.toJson(expected, PreparedParameter.class); assertParameterEquals(expected, jsonStr); } @@ -199,9 +313,8 @@ @Test public void canSerializeDeserializeDouble() { PreparedParameter expected = new PreparedParameter(); - expected.setType(Double.class); + expected.setType(double.class); expected.setValue(Math.E); - expected.setArrayType(false); String jsonStr = gson.toJson(expected, PreparedParameter.class); assertParameterEquals(expected, jsonStr); } @@ -209,13 +322,8 @@ @Test public void canSerializeDeserializeDoubleArray() { PreparedParameter expected = new PreparedParameter(); - expected.setType(Double.class); - // it's important for the expected type to be of primitive array type, - // rather than Double[]. we want the serializer to deserialize to - // primitive types if possible. asserted in method assertParameterEquals() - // Note that model classes use primitive array types as well. + expected.setType(double[].class); expected.setValue(new double[] { 3.3, 1.0, Math.PI }); - expected.setArrayType(true); String jsonStr = gson.toJson(expected, PreparedParameter.class); assertParameterEquals(expected, jsonStr); } @@ -223,9 +331,8 @@ @Test public void canSerializeDeserializeLong() { PreparedParameter expected = new PreparedParameter(); - expected.setType(Long.class); + expected.setType(long.class); expected.setValue(30000000003L); - expected.setArrayType(false); String jsonStr = gson.toJson(expected, PreparedParameter.class); assertParameterEquals(expected, jsonStr); } @@ -233,13 +340,8 @@ @Test public void canSerializeDeserializeLongArray() { PreparedParameter expected = new PreparedParameter(); - expected.setType(Long.class); - // it's important for the expected type to be of primitive array type, - // rather than Long[]. we want the serializer to deserialize to - // primitive types if possible. asserted in method assertParameterEquals() - // Note that model classes use primitive array types as well. + expected.setType(long[].class); expected.setValue(new long[] { 3000000000L, 3, 20 }); - expected.setArrayType(true); String jsonStr = gson.toJson(expected, PreparedParameter.class); assertParameterEquals(expected, jsonStr); } @@ -249,7 +351,6 @@ PreparedParameter expected = new PreparedParameter(); expected.setType(String.class); expected.setValue("testing"); - expected.setArrayType(false); String jsonStr = gson.toJson(expected, PreparedParameter.class); assertParameterEquals(expected, jsonStr); } @@ -257,8 +358,7 @@ @Test public void canSerializeDeserializeStringArray() { PreparedParameter expected = new PreparedParameter(); - expected.setType(String.class); - expected.setArrayType(true); + expected.setType(String[].class); String[] expectedArray = new String[] { "one", "two", "three" }; @@ -270,13 +370,13 @@ @Test public void canSerializeDeserializeBoolean() { PreparedParameter expected = new PreparedParameter(); - expected.setType(Boolean.class); + expected.setType(boolean.class); expected.setValue(false); String jsonStr = gson.toJson(expected, PreparedParameter.class); assertParameterEquals(expected, jsonStr); expected = new PreparedParameter(); - expected.setType(Boolean.class); + expected.setType(boolean.class); expected.setValue(true); jsonStr = gson.toJson(expected, PreparedParameter.class); assertParameterEquals(expected, jsonStr); @@ -285,13 +385,8 @@ @Test public void canSerializeDeserializeBooleanArray() { PreparedParameter expected = new PreparedParameter(); - expected.setType(Boolean.class); - // it's important for the expected type to be of primitive array type, - // rather than Boolean[]. we want the serializer to deserialize to - // primitive types if possible. asserted in method assertParameterEquals() - // Note that model classes use primitive array types as well. + expected.setType(boolean[].class); expected.setValue(new boolean[] { true, false, false, true }); - expected.setArrayType(true); String jsonStr = gson.toJson(expected, PreparedParameter.class); assertParameterEquals(expected, jsonStr); } @@ -303,7 +398,6 @@ AgentInformation info = new AgentInformation("foo-writer"); expected.setType(info.getClass()); expected.setValue(info); - expected.setArrayType(false); String jsonStr = gson.toJson(expected, PreparedParameter.class); assertParameterEquals(expected, jsonStr); @@ -315,7 +409,13 @@ expected = new PreparedParameter(); expected.setType(info.getClass()); expected.setValue(info); - expected.setArrayType(false); + jsonStr = gson.toJson(expected, PreparedParameter.class); + assertParameterEquals(expected, jsonStr); + + // null pojo + expected = new PreparedParameter(); + expected.setType(AgentInformation.class); + expected.setValue(null); jsonStr = gson.toJson(expected, PreparedParameter.class); assertParameterEquals(expected, jsonStr); } @@ -328,13 +428,11 @@ pair.setValue("bar"); expected.setType(pair.getClass()); expected.setValue(pair); - expected.setArrayType(false); String jsonStr = gson.toJson(expected, PreparedParameter.class); PreparedParameter actual = gson.fromJson(jsonStr, PreparedParameter.class); assertEquals(expected.getType(), actual.getType()); - assertTrue(expected.isArrayType() == actual.isArrayType()); assertTrue(actual.getValue() instanceof KeyValuePair); KeyValuePair actualPair = (KeyValuePair)actual.getValue(); assertEquals(pair.getKey(), actualPair.getKey()); @@ -353,7 +451,6 @@ info1, info2 }; PreparedParameter param = new PreparedParameter(); - param.setArrayType(true); param.setType(AgentInformation.class); param.setValue(infos); String jsonStr = gson.toJson(param, PreparedParameter.class); @@ -364,17 +461,15 @@ String jsonStr) { PreparedParameter actual = gson.fromJson(jsonStr, PreparedParameter.class); assertEquals(expected.getType(), actual.getType()); - assertEquals(expected.isArrayType(), actual.isArrayType()); - if (actual.isArrayType()) { + if (actual.getValue() != null && actual.getValue().getClass().isArray()) { // compare element by element Object values = actual.getValue(); Object expectedVals = expected.getValue(); - Class<?> expectedType = expectedVals.getClass(); int expectedLength = Array.getLength(expectedVals); int actualLength = Array.getLength(values); assertEquals(expectedLength, actualLength); // Make sure the deserialized array is of the correct expected type - assertTrue(values.getClass() == expectedType); + assertEquals(expectedVals.getClass(), values.getClass()); for (int i = 0; i < expectedLength; i++) { Object exp = Array.get(expectedVals, i); Object act = Array.get(values, i);
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/PreparedParametersSerializerTest.java Wed Oct 02 18:14:39 2013 +0200 +++ b/web/common/src/test/java/com/redhat/thermostat/web/common/PreparedParametersSerializerTest.java Wed Oct 02 15:07:46 2013 +0200 @@ -37,6 +37,7 @@ package com.redhat.thermostat.web.common; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Test; @@ -121,11 +122,9 @@ PreparedParameter param1 = actual[0]; assertEquals("foo-param", param1.getValue()); assertEquals(String.class, param1.getType()); - assertEquals(false, param1.isArrayType()); PreparedParameter param2 = actual[1]; - assertEquals(Long.class, param2.getType()); - assertEquals(true, param2.isArrayType()); + assertEquals(long[].class, param2.getType()); long[] twoActuals = (long[])param2.getValue(); assertEquals(3, twoActuals.length); assertEquals(3000000000L, (long)twoActuals[0]); @@ -134,7 +133,7 @@ PreparedParameter param3 = actual[2]; assertEquals(AgentInformation.class, param3.getType()); - assertEquals(true, param3.isArrayType()); + assertTrue(param3.getValue().getClass().isArray()); Pojo[] pojos = (Pojo[])param3.getValue(); assertEquals(2, pojos.length); for (int i = 0; i < pojos.length; i++) {
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/WebPreparedStatementSerializerTest.java Wed Oct 02 18:14:39 2013 +0200 +++ b/web/common/src/test/java/com/redhat/thermostat/web/common/WebPreparedStatementSerializerTest.java Wed Oct 02 15:07:46 2013 +0200 @@ -37,9 +37,7 @@ package com.redhat.thermostat.web.common; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Test; @@ -83,22 +81,18 @@ PreparedParameter[] parameters = newParams.getParams(); assertEquals(5, parameters.length); assertEquals(2, parameters[0].getValue()); - assertEquals(Integer.class, parameters[0].getType()); + assertEquals(int.class, parameters[0].getType()); assertEquals("testing", parameters[1].getValue()); assertEquals(String.class, parameters[1].getType()); - assertFalse(parameters[1].isArrayType()); assertEquals(222L, parameters[2].getValue()); - assertEquals(Long.class, parameters[2].getType()); - assertFalse(parameters[2].isArrayType()); + assertEquals(long.class, parameters[2].getType()); String[] list = (String[])parameters[3].getValue(); assertEquals(2, list.length); assertEquals("one", list[0]); assertEquals("two", list[1]); - assertEquals(String.class, parameters[3].getType()); - assertTrue(parameters[3].isArrayType()); + assertEquals(String[].class, parameters[3].getType()); assertEquals(true, parameters[4].getValue()); - assertEquals(Boolean.class, parameters[4].getType()); - assertFalse(parameters[4].isArrayType()); + assertEquals(boolean.class, parameters[4].getType()); assertEquals(WebPreparedStatementResponse.DESCRIPTOR_PARSE_FAILED, newStmt.getStatementId()); }