Mercurial > hg > release > thermostat-0.4
changeset 631:9eed9fa986ad
Implement findAll() in web storage.
Reviewed-by: omajid
http://icedtea.classpath.org/pipermail/thermostat/2012-September/003308.html
line wrap: on
line diff
--- a/common/core/src/main/java/com/redhat/thermostat/common/dao/AgentInfoDAOImpl.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/AgentInfoDAOImpl.java Thu Sep 20 00:28:12 2012 +0200 @@ -64,7 +64,8 @@ @Override public List<AgentInformation> getAllAgentInformation() { - Cursor<AgentInformation> agentCursor = storage.findAllPojosFromCategory(CATEGORY, AgentInformation.class); + Query query = storage.createQuery().from(CATEGORY); + Cursor<AgentInformation> agentCursor = storage.findAllPojos(query, AgentInformation.class); List<AgentInformation> results = new ArrayList<>();
--- a/common/core/src/main/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetter.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetter.java Thu Sep 20 00:28:12 2012 +0200 @@ -42,7 +42,6 @@ import com.redhat.thermostat.common.model.TimeStampedPojo; import com.redhat.thermostat.common.storage.Category; import com.redhat.thermostat.common.storage.Cursor; -import com.redhat.thermostat.common.storage.Cursor.SortDirection; import com.redhat.thermostat.common.storage.Key; import com.redhat.thermostat.common.storage.Query; import com.redhat.thermostat.common.storage.Query.Criteria; @@ -70,7 +69,6 @@ private List<T> getLatest(Query query) { Cursor<T> cursor = storage.findAllPojos(query, resultClass); - cursor = cursor.sort(Key.TIMESTAMP, SortDirection.DESCENDING); List<T> result = new ArrayList<>(); while (cursor.hasNext()) { T pojo = cursor.next(); @@ -82,8 +80,10 @@ protected Query buildQuery(long since) { Query query = storage.createQuery() .from(cat) - .where(Key.AGENT_ID, Criteria.EQUALS, ref.getAgentId()); - query.where(Key.TIMESTAMP, Criteria.GREATER_THAN, since); + .where(Key.AGENT_ID, Criteria.EQUALS, ref.getAgentId()) + .where(Key.TIMESTAMP, Criteria.GREATER_THAN, since) + .sort(Key.TIMESTAMP, Query.SortDirection.DESCENDING); + return query; } }
--- a/common/core/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOImpl.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOImpl.java Thu Sep 20 00:28:12 2012 +0200 @@ -62,8 +62,10 @@ Query query = storage.createQuery() .from(vmMemoryStatsCategory) .where(Key.AGENT_ID, Criteria.EQUALS, ref.getAgent().getAgentId()) - .where(Key.VM_ID, Criteria.EQUALS, ref.getId()); - Cursor<VmMemoryStat> cursor = storage.findAllPojos(query, VmMemoryStat.class).sort(Key.TIMESTAMP, Cursor.SortDirection.DESCENDING).limit(1); + .where(Key.VM_ID, Criteria.EQUALS, ref.getId()) + .sort(Key.TIMESTAMP, Query.SortDirection.DESCENDING) + .limit(1);; + Cursor<VmMemoryStat> cursor = storage.findAllPojos(query, VmMemoryStat.class); if (cursor.hasNext()) { return cursor.next(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/AbstractQuery.java Thu Sep 20 00:28:12 2012 +0200 @@ -0,0 +1,137 @@ +/* + * Copyright 2012 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.common.storage; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public abstract class AbstractQuery implements Query { + + public static class Sort { + private Key<?> key; + private SortDirection direction; + public Sort() { + this(null, null); + } + + public Sort(Key<?> key, SortDirection direction) { + this.key = key; + this.direction = direction; + } + public Key<?> getKey() { + return key; + } + public void setKey(Key<?> key) { + this.key = key; + } + public SortDirection getDirection() { + return direction; + } + public void setDirection(SortDirection direction) { + this.direction = direction; + } + + public int hashCode() { + return Objects.hash(key, direction); + } + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + if (!(obj instanceof Sort)) { + return false; + } + Sort other = (Sort) obj; + return Objects.equals(key, other.key) && Objects.equals(direction, other.direction); + } + } + + private Category category; + private List<Sort> sorts; + private int limit = -1; + + public AbstractQuery() { + sorts = new ArrayList<>(); + } + + @Override + public Query from(Category category) { + this.category = category; + return this; + } + + public Category getCategory() { + return category; + } + + public void setCategory(Category category) { + this.category = category; + } + + @Override + public <T> Query sort(Key<T> key, SortDirection direction) { + sorts.add(new Sort(key, direction)); + return this; + } + + public List<Sort> getSorts() { + return sorts; + } + + public void setSorts(List<Sort> sorts) { + this.sorts = sorts; + } + + @Override + public Query limit(int limit) { + this.limit = limit; + return this; + } + + public int getLimit() { + return limit; + } + + public void setLimit(int limit) { + this.limit = limit; + } +}
--- a/common/core/src/main/java/com/redhat/thermostat/common/storage/Categories.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/Categories.java Thu Sep 20 00:28:12 2012 +0200 @@ -54,6 +54,10 @@ namesToCategories.put(category.getName(), category); } + public static synchronized void remove(Category category) { + namesToCategories.remove(category.getName()); + } + public static synchronized Category getByName(String categoryName) { return namesToCategories.get(categoryName); }
--- a/common/core/src/main/java/com/redhat/thermostat/common/storage/Cursor.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/Cursor.java Thu Sep 20 00:28:12 2012 +0200 @@ -40,26 +40,8 @@ public interface Cursor<T extends Pojo> { - public enum SortDirection { - ASCENDING(1), - DESCENDING(-1); - - private int value; - - private SortDirection(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } - boolean hasNext(); T next(); - Cursor<T> sort(Key<?> orderBy, SortDirection direction); - - Cursor<T> limit(int i); }
--- a/common/core/src/main/java/com/redhat/thermostat/common/storage/MongoCursor.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/MongoCursor.java Thu Sep 20 00:28:12 2012 +0200 @@ -74,23 +74,4 @@ return ChunkToPojoConverter.convertChunkToPojo(resultChunk, resultClass, converters); } - @Override - public Cursor<T> sort(Key<?> orderBy, SortDirection direction) { - if (!category.getKeys().contains(orderBy)) { - throw new IllegalArgumentException("Key not present in this Cursor's category."); - } /* TODO: There are other possible error conditions. Once there is API to configure - * indexing/optimization, we may want to prevent or log predictably bad performance - * sorting requests. - */ - DBObject dbOrderBy = new BasicDBObject(orderBy.getName(), direction.getValue()); - DBCursor sorted = cursor.sort(dbOrderBy); - return new MongoCursor<T>(sorted, category, resultClass, converters); - } - - @Override - public Cursor<T> limit(int i) { - DBCursor limited = cursor.limit(i); - return new MongoCursor<T>(limited, category, resultClass, converters); - } - }
--- a/common/core/src/main/java/com/redhat/thermostat/common/storage/MongoQuery.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/MongoQuery.java Thu Sep 20 00:28:12 2012 +0200 @@ -41,14 +41,14 @@ import com.mongodb.BasicDBObject; import com.mongodb.DBObject; -public class MongoQuery implements Query { +public class MongoQuery extends AbstractQuery { - private Category category; private BasicDBObject query = new BasicDBObject(); + private boolean hasClauses = false; @Override public MongoQuery from(Category category) { - this.category = category; + setCategory(category); return this; } @@ -84,22 +84,18 @@ default: throw new IllegalArgumentException("MongoQuery can not handle " + operator); } - + hasClauses = true; return this; } String getCollectionName() { - return category.getName(); + return getCategory().getName(); } DBObject getGeneratedQuery() { return query; } - Category getCategory() { - return category; - } - @Override public boolean equals(Object obj) { if (obj == this) { @@ -112,11 +108,16 @@ return false; } MongoQuery other = (MongoQuery) obj; - return Objects.equals(this.category, other.category) && Objects.equals(this.query, other.query); + return Objects.equals(getCategory(), other.getCategory()) && Objects.equals(this.query, other.query); } @Override public int hashCode() { - return Objects.hash(this.category, this.query); + return Objects.hash(getCategory(), this.query); } + + boolean hasClauses() { + return hasClauses ; + } + }
--- a/common/core/src/main/java/com/redhat/thermostat/common/storage/MongoStorage.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/MongoStorage.java Thu Sep 20 00:28:12 2012 +0200 @@ -38,6 +38,7 @@ import java.io.InputStream; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; @@ -55,6 +56,7 @@ import com.redhat.thermostat.common.dao.VmMemoryStatConverter; import com.redhat.thermostat.common.model.Pojo; import com.redhat.thermostat.common.model.VmMemoryStat; +import com.redhat.thermostat.common.storage.AbstractQuery.Sort; import com.redhat.thermostat.common.storage.Connection.ConnectionListener; import com.redhat.thermostat.common.storage.Connection.ConnectionStatus; @@ -347,10 +349,30 @@ public <T extends Pojo> Cursor<T> findAllPojos(Query query, Class<T> resultClass) { MongoQuery mongoQuery = checkAndCastQuery(query); DBCollection coll = getCachedCollection(mongoQuery.getCollectionName()); - DBCursor dbCursor = coll.find(mongoQuery.getGeneratedQuery()); + DBCursor dbCursor; + if (mongoQuery.hasClauses()) { + dbCursor = coll.find(mongoQuery.getGeneratedQuery()); + } else { + dbCursor = coll.find(); + } + dbCursor = applySortAndLimit(mongoQuery, dbCursor); return new MongoCursor<T>(dbCursor, mongoQuery.getCategory(), resultClass, converters); } + private DBCursor applySortAndLimit(MongoQuery query, DBCursor dbCursor) { + BasicDBObject orderBy = new BasicDBObject(); + List<Sort> sorts = query.getSorts(); + for (Sort sort : sorts) { + orderBy.append(sort.getKey().getName(), sort.getDirection().getValue()); + } + dbCursor.sort(orderBy); + int limit = query.getLimit(); + if (limit > 0) { + dbCursor.limit(limit); + } + return dbCursor; + } + @Override public <T extends Pojo> T findPojo(Query query, Class<T> resultClass) { Chunk resultChunk = find(query); @@ -379,13 +401,6 @@ } @Override - public <T extends Pojo> Cursor<T> findAllPojosFromCategory(Category category, Class<T> resultClass) { - DBCollection coll = getCachedCollection(category.getName()); - DBCursor dbCursor = coll.find(); - return new MongoCursor<T>(dbCursor, category, resultClass, converters); - } - - @Override public long getCount(Category category) { DBCollection coll = getCachedCollection(category.getName()); if (coll != null) {
--- a/common/core/src/main/java/com/redhat/thermostat/common/storage/Query.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/Query.java Thu Sep 20 00:28:12 2012 +0200 @@ -47,8 +47,26 @@ LESS_THAN_OR_EQUAL_TO, } + enum SortDirection { + ASCENDING(1), + DESCENDING(-1); + + private int value; + + private SortDirection(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + Query from(Category category); <T> Query where(Key<T> key, Criteria criteria, T value); + <T> Query sort(Key<T> key, SortDirection direction); + + Query limit(int n); }
--- a/common/core/src/main/java/com/redhat/thermostat/common/storage/Storage.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/Storage.java Thu Sep 20 00:28:12 2012 +0200 @@ -74,8 +74,6 @@ public abstract <T extends Pojo> T findPojo(Query query, Class<T> resultClass); - public abstract <T extends Pojo> Cursor<T> findAllPojosFromCategory(Category category, Class<T> resultClass); - public abstract long getCount(Category category); public abstract void saveFile(String filename, InputStream data);
--- a/common/core/src/main/java/com/redhat/thermostat/test/MockQuery.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/test/MockQuery.java Thu Sep 20 00:28:12 2012 +0200 @@ -40,11 +40,11 @@ import java.util.List; import java.util.Objects; +import com.redhat.thermostat.common.storage.AbstractQuery; import com.redhat.thermostat.common.storage.Category; import com.redhat.thermostat.common.storage.Key; -import com.redhat.thermostat.common.storage.Query; -public class MockQuery implements Query { +public class MockQuery extends AbstractQuery { public static class WhereClause <T> { public final Key<T> key; @@ -79,11 +79,10 @@ } private final List<WhereClause<?>> whereClauses = new ArrayList<>(); - private Category category; @Override public MockQuery from(Category category) { - this.category = category; + setCategory(category); return this; } @@ -93,10 +92,6 @@ return this; } - public Category getCategory() { - return category; - } - public List<WhereClause<?>> getWhereClauses() { return whereClauses; } @@ -135,12 +130,17 @@ return false; } MockQuery other = (MockQuery) obj; - return Objects.equals(category, other.category) && Objects.equals(whereClauses, other.whereClauses); + return Objects.equals(getCategory(), other.getCategory()) && Objects.equals(whereClauses, other.whereClauses); } @Override public int hashCode() { - return Objects.hash(category, whereClauses); + return Objects.hash(getCategory(), whereClauses); + } + + public boolean hasSort(Key<?> key, SortDirection direction) { + + return getSorts().contains(new Sort(key, direction)); } }
--- a/common/core/src/test/java/com/redhat/thermostat/common/dao/AgentInfoDAOTest.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/AgentInfoDAOTest.java Thu Sep 20 00:28:12 2012 +0200 @@ -39,6 +39,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -49,15 +51,14 @@ import org.junit.Before; import org.junit.Test; -import org.mockito.ArgumentCaptor; import com.redhat.thermostat.common.model.AgentInformation; import com.redhat.thermostat.common.storage.Category; -import com.redhat.thermostat.common.storage.Chunk; import com.redhat.thermostat.common.storage.Cursor; import com.redhat.thermostat.common.storage.Key; +import com.redhat.thermostat.common.storage.Query; +import com.redhat.thermostat.common.storage.Query.Criteria; import com.redhat.thermostat.common.storage.QueryTestHelper; -import com.redhat.thermostat.common.storage.Query.Criteria; import com.redhat.thermostat.common.storage.Remove; import com.redhat.thermostat.common.storage.Storage; import com.redhat.thermostat.common.storage.Update; @@ -119,8 +120,9 @@ when(agentCursor.next()).thenReturn(agent1).thenReturn(null); Storage storage = mock(Storage.class); - when(storage.findAllPojosFromCategory(AgentInfoDAO.CATEGORY, AgentInformation.class)).thenReturn(agentCursor); - + when(storage.findAllPojos(any(Query.class), same(AgentInformation.class))).thenReturn(agentCursor); + MockQuery query = new MockQuery(); + when(storage.createQuery()).thenReturn(query); AgentInfoDAOImpl dao = new AgentInfoDAOImpl(storage); List<AgentInformation> allAgentInfo = dao.getAllAgentInformation();
--- a/common/core/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java Thu Sep 20 00:28:12 2012 +0200 @@ -38,7 +38,6 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.same; @@ -56,7 +55,6 @@ import com.redhat.thermostat.common.model.CpuStat; import com.redhat.thermostat.common.storage.Category; import com.redhat.thermostat.common.storage.Cursor; -import com.redhat.thermostat.common.storage.Cursor.SortDirection; import com.redhat.thermostat.common.storage.Key; import com.redhat.thermostat.common.storage.Query; import com.redhat.thermostat.common.storage.Query.Criteria; @@ -93,7 +91,6 @@ when(cursor.hasNext()).thenReturn(true).thenReturn(false); when(cursor.next()).thenReturn(cpuStat); - when(cursor.sort(any(Key.class), any(SortDirection.class))).thenReturn(cursor); when(storage.createQuery()).thenReturn(query); when(storage.findAllPojos(query, CpuStat.class)).thenReturn(cursor); @@ -125,7 +122,6 @@ when(cursor.hasNext()).thenReturn(true).thenReturn(false); when(cursor.next()).thenReturn(cpuStat); - when(cursor.sort(any(Key.class), any(SortDirection.class))).thenReturn(cursor); when(storage.createQuery()).thenReturn(query); when(storage.findAllPojos(any(Query.class), same(CpuStat.class))).thenReturn(cursor);
--- a/common/core/src/test/java/com/redhat/thermostat/common/dao/HostInfoDAOTest.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/HostInfoDAOTest.java Thu Sep 20 00:28:12 2012 +0200 @@ -147,7 +147,6 @@ return new MockQuery(); } }); - when(storage.findAllPojosFromCategory(HostInfoDAO.hostInfoCategory, HostInfo.class)).thenReturn(cursor); when(storage.findAllPojos(any(Query.class), same(HostInfo.class))).thenReturn(cursor); return storage; @@ -190,7 +189,6 @@ return new MockQuery(); } }); - when(storage.findAllPojosFromCategory(HostInfoDAO.hostInfoCategory, HostInfo.class)).thenReturn(cursor); when(storage.findAllPojos(any(Query.class), same(HostInfo.class))).thenReturn(cursor); return storage;
--- a/common/core/src/test/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetterTest.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetterTest.java Thu Sep 20 00:28:12 2012 +0200 @@ -38,14 +38,9 @@ import static org.junit.Assert.assertArrayEquals; 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 static org.mockito.Matchers.any; -import static org.mockito.Matchers.same; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.Arrays; @@ -59,8 +54,6 @@ import com.redhat.thermostat.common.storage.Category; import com.redhat.thermostat.common.storage.Cursor; import com.redhat.thermostat.common.storage.Key; -import com.redhat.thermostat.common.storage.Query; -import com.redhat.thermostat.common.storage.Cursor.SortDirection; import com.redhat.thermostat.common.storage.Query.Criteria; import com.redhat.thermostat.common.storage.Storage; import com.redhat.thermostat.common.utils.ArrayUtils; @@ -142,7 +135,6 @@ Cursor<CpuStat> cursor = mock(Cursor.class); when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false); when(cursor.next()).thenReturn(result1).thenReturn(result2).thenReturn(null); - when(cursor.sort(any(Key.class), any(SortDirection.class))).thenReturn(cursor); Storage storage = mock(Storage.class); MockQuery query = new MockQuery();
--- a/common/core/src/test/java/com/redhat/thermostat/common/dao/MemoryStatDAOTest.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/MemoryStatDAOTest.java Thu Sep 20 00:28:12 2012 +0200 @@ -55,7 +55,6 @@ import com.redhat.thermostat.common.model.MemoryStat; import com.redhat.thermostat.common.storage.Category; import com.redhat.thermostat.common.storage.Cursor; -import com.redhat.thermostat.common.storage.Cursor.SortDirection; import com.redhat.thermostat.common.storage.Key; import com.redhat.thermostat.common.storage.Query; import com.redhat.thermostat.common.storage.Query.Criteria; @@ -98,7 +97,6 @@ Cursor<MemoryStat> cursor = mock(Cursor.class); when(cursor.hasNext()).thenReturn(true).thenReturn(false); when(cursor.next()).thenReturn(memStat1); - when(cursor.sort(any(Key.class), any(SortDirection.class))).thenReturn(cursor); Storage storage = mock(Storage.class); when(storage.createQuery()).then(new Answer<Query>() {
--- a/common/core/src/test/java/com/redhat/thermostat/common/dao/VmClassStatDAOTest.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmClassStatDAOTest.java Thu Sep 20 00:28:12 2012 +0200 @@ -56,7 +56,6 @@ import com.redhat.thermostat.common.storage.Cursor; import com.redhat.thermostat.common.storage.Key; import com.redhat.thermostat.common.storage.Query; -import com.redhat.thermostat.common.storage.Cursor.SortDirection; import com.redhat.thermostat.common.storage.Query.Criteria; import com.redhat.thermostat.common.storage.Storage; import com.redhat.thermostat.test.MockQuery; @@ -87,7 +86,6 @@ Cursor<VmClassStat> cursor = mock(Cursor.class); when(cursor.hasNext()).thenReturn(true).thenReturn(false); when(cursor.next()).thenReturn(vmClassStat); - when(cursor.sort(any(Key.class), any(SortDirection.class))).thenReturn(cursor); Storage storage = mock(Storage.class); when(storage.createQuery()).then(new Answer<Query>() {
--- a/common/core/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatDAOTest.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatDAOTest.java Thu Sep 20 00:28:12 2012 +0200 @@ -55,7 +55,6 @@ import com.redhat.thermostat.common.model.VmCpuStat; import com.redhat.thermostat.common.storage.Cursor; -import com.redhat.thermostat.common.storage.Cursor.SortDirection; import com.redhat.thermostat.common.storage.Key; import com.redhat.thermostat.common.storage.Query; import com.redhat.thermostat.common.storage.Query.Criteria; @@ -93,7 +92,6 @@ Cursor<VmCpuStat> cursor = mock(Cursor.class); when(cursor.hasNext()).thenReturn(true).thenReturn(false); when(cursor.next()).thenReturn(cpuStat); - when(cursor.sort(any(Key.class), any(SortDirection.class))).thenReturn(cursor); Storage storage = mock(Storage.class); when(storage.createQuery()).then(new Answer<Query>() {
--- a/common/core/src/test/java/com/redhat/thermostat/common/dao/VmGcStatDAOTest.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmGcStatDAOTest.java Thu Sep 20 00:28:12 2012 +0200 @@ -37,12 +37,10 @@ package com.redhat.thermostat.common.dao; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.same; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -51,12 +49,9 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import com.redhat.thermostat.common.model.VmGcStat; import com.redhat.thermostat.common.storage.Cursor; -import com.redhat.thermostat.common.storage.Cursor.SortDirection; import com.redhat.thermostat.common.storage.Key; import com.redhat.thermostat.common.storage.Query; import com.redhat.thermostat.common.storage.Query.Criteria; @@ -93,7 +88,6 @@ Cursor<VmGcStat> cursor = mock(Cursor.class); when(cursor.hasNext()).thenReturn(true).thenReturn(false); when(cursor.next()).thenReturn(vmGcStat); - when(cursor.sort(any(Key.class), any(SortDirection.class))).thenReturn(cursor); Storage storage = mock(Storage.class); when(storage.createQuery()).thenReturn(new MockQuery());
--- a/common/core/src/test/java/com/redhat/thermostat/common/dao/VmLatestPojoListGetterTest.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmLatestPojoListGetterTest.java Thu Sep 20 00:28:12 2012 +0200 @@ -42,7 +42,6 @@ import static org.mockito.Matchers.any; import static org.mockito.Matchers.same; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -54,7 +53,6 @@ import com.redhat.thermostat.common.model.VmClassStat; import com.redhat.thermostat.common.storage.Category; import com.redhat.thermostat.common.storage.Cursor; -import com.redhat.thermostat.common.storage.Cursor.SortDirection; import com.redhat.thermostat.common.storage.Key; import com.redhat.thermostat.common.storage.Query; import com.redhat.thermostat.common.storage.Query.Criteria; @@ -134,7 +132,6 @@ Cursor<VmClassStat> cursor = mock(Cursor.class); when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false); when(cursor.next()).thenReturn(result1).thenReturn(result2).thenReturn(null); - when(cursor.sort(any(Key.class), any(SortDirection.class))).thenReturn(cursor); Storage storage = mock(Storage.class); MockQuery query = new MockQuery();
--- a/common/core/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOTest.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOTest.java Thu Sep 20 00:28:12 2012 +0200 @@ -51,13 +51,11 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.mockito.ArgumentCaptor; import com.redhat.thermostat.common.model.VmMemoryStat; import com.redhat.thermostat.common.model.VmMemoryStat.Generation; import com.redhat.thermostat.common.model.VmMemoryStat.Space; import com.redhat.thermostat.common.storage.Cursor; -import com.redhat.thermostat.common.storage.Cursor.SortDirection; import com.redhat.thermostat.common.storage.Key; import com.redhat.thermostat.common.storage.Query; import com.redhat.thermostat.common.storage.Query.Criteria; @@ -94,8 +92,6 @@ cursor = mock(Cursor.class); when(storage.findAllPojos(any(Query.class), same(VmMemoryStat.class))).thenReturn(cursor); - when(cursor.sort(any(Key.class), any(SortDirection.class))).thenReturn(cursor); - when(cursor.limit(any(Integer.class))).thenReturn(cursor); when(cursor.hasNext()).thenReturn(false); } @@ -164,16 +160,10 @@ } private void verifyQuery() { - @SuppressWarnings("rawtypes") - ArgumentCaptor<Key> sortKey = ArgumentCaptor.forClass(Key.class); - ArgumentCaptor<SortDirection> sortDirection = ArgumentCaptor.forClass(SortDirection.class); - verify(cursor).sort(sortKey.capture(), sortDirection.capture()); assertTrue(query.hasWhereClause(Key.AGENT_ID, Criteria.EQUALS, AGENT_ID)); assertTrue(query.hasWhereClause(Key.VM_ID, Criteria.EQUALS, VM_ID)); - - assertTrue(sortKey.getValue().equals(Key.TIMESTAMP)); - assertTrue(sortDirection.getValue().equals(SortDirection.DESCENDING)); + assertTrue(query.hasSort(Key.TIMESTAMP, Query.SortDirection.DESCENDING)); } @Test
--- a/common/core/src/test/java/com/redhat/thermostat/common/storage/MongoCursorTest.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/test/java/com/redhat/thermostat/common/storage/MongoCursorTest.java Thu Sep 20 00:28:12 2012 +0200 @@ -150,34 +150,4 @@ assertNull(cursor.next()); } - @Test - public void verifyCursorSort() { - ArgumentCaptor<DBObject> arg = ArgumentCaptor.forClass(DBObject.class); - Cursor<TestClass> sorted = cursor.sort(key1, Cursor.SortDirection.ASCENDING); - - verify(dbCursor).sort(arg.capture()); - DBObject orderByDBObject = arg.getValue(); - assertEquals(1, orderByDBObject.keySet().size()); - assertEquals((Integer) Cursor.SortDirection.ASCENDING.getValue(), orderByDBObject.get(key1.getName())); - // Verify that the sorted cursor is still return the same number of items. We leave the actual - // sorting to Mongo and won't check it here. - assertTrue(sorted.hasNext()); - sorted.next(); - assertTrue(sorted.hasNext()); - sorted.next(); - assertFalse(sorted.hasNext()); - } - - @Test - public void verifyCursorLimit() { - - Cursor<TestClass> sorted = cursor.limit(1); - - verify(dbCursor).limit(1); - - // We cannot really test if the cursor really got limited, this is up to the mongo implementation. - // In any case, we can verify that the returned cursor actually is 'active'. - assertTrue(sorted.hasNext()); - sorted.next(); - } }
--- a/common/core/src/test/java/com/redhat/thermostat/common/storage/MongoStorageTest.java Tue Sep 18 22:52:53 2012 +0200 +++ b/common/core/src/test/java/com/redhat/thermostat/common/storage/MongoStorageTest.java Thu Sep 20 00:28:12 2012 +0200 @@ -144,6 +144,7 @@ private Mongo m; private DB db; private DBCollection testCollection, emptyTestCollection, mockedCollection; + private DBCursor cursor; private MongoStorage makeStorage() { MongoStorage storage = new MongoStorage(conf); @@ -177,7 +178,7 @@ multiKeyQuery.put(key2, "test4"); multiKeyQuery.put(key1, "test5"); - DBCursor cursor = mock(DBCursor.class); + cursor = mock(DBCursor.class); when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false); when(cursor.next()).thenReturn(value1).thenReturn(value2).thenReturn(null); @@ -200,6 +201,7 @@ testCollection = null; emptyTestCollection = null; multiKeyQuery = null; + cursor = null; } @Test @@ -248,7 +250,7 @@ public void verifyFindAllCallsDBCollectionFind() throws Exception { PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m); MongoStorage storage = makeStorage(); - Query query = storage.createQuery().from(testCategory); + Query query = storage.createQuery().from(testCategory).where(key1, Criteria.EQUALS, "fluff"); storage.findAllPojos(query, TestClass.class); verify(testCollection).find(any(DBObject.class)); } @@ -268,6 +270,7 @@ MongoStorage storage = makeStorage(); MongoQuery query = mock(MongoQuery.class); + when(query.hasClauses()).thenReturn(true); DBObject generatedQuery = mock(DBObject.class); when(query.getGeneratedQuery()).thenReturn(generatedQuery); when(query.getCollectionName()).thenReturn(testCategory.getName()); @@ -329,10 +332,29 @@ } @Test + public void verifyFindAllWithSortAndLimit() throws Exception { + PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m); + MongoStorage storage = makeStorage(); + // TODO find a way to test this that isn't just testing MongoCursor + // Because we mock the DBCollection, the contents of this query don't actually determine the result. + MongoQuery query = (MongoQuery) new MongoQuery().from(testCategory).sort(key1, Query.SortDirection.ASCENDING).limit(3); + + Cursor<TestClass> cursor = storage.findAllPojos(query, TestClass.class); + + verifyDefaultCursor(cursor); + ArgumentCaptor<DBObject> orderBy = ArgumentCaptor.forClass(DBObject.class); + verify(this.cursor).sort(orderBy.capture()); + assertTrue(orderBy.getValue().containsField("key1")); + assertEquals(1, orderBy.getValue().get("key1")); + verify(this.cursor).limit(3); + } + + @Test public void verifyFindAllFromCategoryCallsDBCollectionFindAll() throws Exception { PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m); MongoStorage storage = makeStorage(); - storage.findAllPojosFromCategory(testCategory, TestClass.class); + Query query = storage.createQuery().from(testCategory); + storage.findAllPojos(query, TestClass.class); verify(testCollection).find(); } @@ -340,7 +362,8 @@ public void verifyFindAllFromCategoryReturnsCorrectCursor() throws Exception { PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m); MongoStorage storage = makeStorage(); - Cursor<TestClass> cursor = storage.findAllPojosFromCategory(testCategory, TestClass.class); + Query query = storage.createQuery().from(testCategory); + Cursor<TestClass> cursor = storage.findAllPojos(query, TestClass.class); verifyDefaultCursor(cursor); }
--- a/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImpl.java Tue Sep 18 22:52:53 2012 +0200 +++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImpl.java Thu Sep 20 00:28:12 2012 +0200 @@ -92,8 +92,8 @@ public ThreadSummary loadLastestSummary(VmRef ref) { ThreadSummary summary = null; - Query query = prepareQuery(THREAD_SUMMARY, ref); - Cursor<ThreadSummary> cursor = storage.findAllPojos(query, ThreadSummary.class).sort(Key.TIMESTAMP, Cursor.SortDirection.DESCENDING).limit(1); + Query query = prepareQuery(THREAD_SUMMARY, ref).sort(Key.TIMESTAMP, Query.SortDirection.DESCENDING).limit(1); + Cursor<ThreadSummary> cursor = storage.findAllPojos(query, ThreadSummary.class); if (cursor.hasNext()) { summary = cursor.next(); } @@ -106,10 +106,10 @@ List<ThreadSummary> result = new ArrayList<>(); - Query query = prepareQuery(THREAD_SUMMARY, ref); + Query query = prepareQuery(THREAD_SUMMARY, ref).sort(Key.TIMESTAMP, Query.SortDirection.DESCENDING); query.where(Key.TIMESTAMP, Criteria.GREATER_THAN, since); - Cursor<ThreadSummary> cursor = storage.findAllPojos(query, ThreadSummary.class).sort(Key.TIMESTAMP, Cursor.SortDirection.DESCENDING); + Cursor<ThreadSummary> cursor = storage.findAllPojos(query, ThreadSummary.class); while (cursor.hasNext()) { ThreadSummary summary = cursor.next(); result.add(summary); @@ -128,9 +128,10 @@ List<ThreadInfoData> result = new ArrayList<>(); Query query = prepareQuery(THREAD_INFO, ref) - .where(Key.TIMESTAMP, Criteria.GREATER_THAN, since); + .where(Key.TIMESTAMP, Criteria.GREATER_THAN, since) + .sort(Key.TIMESTAMP, Query.SortDirection.DESCENDING); - Cursor<ThreadInfoData> cursor = storage.findAllPojos(query, ThreadInfoData.class).sort(Key.TIMESTAMP, Cursor.SortDirection.DESCENDING); + Cursor<ThreadInfoData> cursor = storage.findAllPojos(query, ThreadInfoData.class); while (cursor.hasNext()) { ThreadInfoData info = cursor.next(); result.add(info);
--- a/web/client/src/main/java/com/redhat/thermostat/web/client/RESTStorage.java Tue Sep 18 22:52:53 2012 +0200 +++ b/web/client/src/main/java/com/redhat/thermostat/web/client/RESTStorage.java Thu Sep 20 00:28:12 2012 +0200 @@ -42,6 +42,7 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; +import java.lang.reflect.Array; import java.net.HttpURLConnection; import java.net.URL; import java.util.UUID; @@ -85,16 +86,26 @@ } @Override - public <T extends Pojo> Cursor<T> findAllPojos(Query arg0, Class<T> arg1) { - // TODO Auto-generated method stub - return null; - } + public <T extends Pojo> Cursor<T> findAllPojos(Query query, Class<T> resultClass) { + try { + URL url = new URL(endpoint + "/find-all"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoInput(true); + conn.setDoOutput(true); + conn.setRequestMethod("POST"); + OutputStream out = conn.getOutputStream(); + Gson gson = new Gson(); + OutputStreamWriter writer = new OutputStreamWriter(out); + ((RESTQuery) query).setResultClassName(resultClass.getName()); + gson.toJson(query, writer); + writer.flush(); - @Override - public <T extends Pojo> Cursor<T> findAllPojosFromCategory(Category arg0, - Class<T> arg1) { - // TODO Auto-generated method stub - return null; + InputStream in = conn.getInputStream(); + T[] result = (T[]) gson.fromJson(new InputStreamReader(in), Array.newInstance(resultClass, 0).getClass()); + return new WebCursor<T>(result); + } catch (IOException ex) { + throw new RuntimeException(ex); + } } @Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/client/src/main/java/com/redhat/thermostat/web/client/WebCursor.java Thu Sep 20 00:28:12 2012 +0200 @@ -0,0 +1,67 @@ +/* + * Copyright 2012 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.web.client; + +import com.redhat.thermostat.common.NotImplementedException; +import com.redhat.thermostat.common.model.Pojo; +import com.redhat.thermostat.common.storage.Cursor; +import com.redhat.thermostat.common.storage.Key; + +class WebCursor<T extends Pojo> implements Cursor<T> { + + private T[] data; + private int index; + + WebCursor(T[] data) { + this.data = data; + index = 0; + } + + @Override + public boolean hasNext() { + return index < data.length; + } + + @Override + public T next() { + T result = data[index]; + index++; + return result; + } + +}
--- a/web/client/src/test/java/com/redhat/thermostat/web/client/RESTStorageTest.java Tue Sep 18 22:52:53 2012 +0200 +++ b/web/client/src/test/java/com/redhat/thermostat/web/client/RESTStorageTest.java Thu Sep 20 00:28:12 2012 +0200 @@ -38,10 +38,12 @@ package com.redhat.thermostat.web.client; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.io.Reader; +import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -53,11 +55,15 @@ import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.junit.After; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import com.google.gson.Gson; +import com.redhat.thermostat.common.storage.Categories; import com.redhat.thermostat.common.storage.Category; +import com.redhat.thermostat.common.storage.Cursor; import com.redhat.thermostat.common.storage.Key; import com.redhat.thermostat.common.storage.Query; import com.redhat.thermostat.common.storage.Query.Criteria; @@ -76,6 +82,22 @@ private String responseBody; + private static Category category; + private static Key<String> key1; + + @BeforeClass + public static void setupCategory() { + key1 = new Key<>("property1", true); + category = new Category("test", key1); + } + + @AfterClass + public static void cleanupCategory() { + Categories.remove(category); + category = null; + key1 = null; + } + @Before public void setUp() throws Exception { port = FreePortFinder.findFreePort(new TryPort() { @@ -134,8 +156,7 @@ Gson gson = new Gson(); responseBody = gson.toJson(obj); - Key<String> key1 = new Key<>("property1", true); - Query query = storage.createQuery().from(new Category("test", key1)).where(key1, Criteria.EQUALS, "fluff"); + Query query = storage.createQuery().from(category).where(key1, Criteria.EQUALS, "fluff"); TestObj result = storage.findPojo(query, TestObj.class); RESTQuery restQuery = gson.fromJson(requestBody, RESTQuery.class); @@ -154,4 +175,42 @@ assertEquals("fluffor", result.getProperty1()); } + + @Test + public void testFindAllPojos() { + RESTStorage storage = new RESTStorage(); + storage.setEndpoint("http://localhost:" + port + "/"); + + TestObj obj1 = new TestObj(); + obj1.setProperty1("fluffor1"); + TestObj obj2 = new TestObj(); + obj2.setProperty1("fluffor2"); + Gson gson = new Gson(); + responseBody = gson.toJson(Arrays.asList(obj1, obj2)); + + Key<String> key1 = new Key<>("property1", true); + Query query = storage.createQuery().from(category).where(key1, Criteria.EQUALS, "fluff"); + + Cursor<TestObj> results = storage.findAllPojos(query, TestObj.class); + RESTQuery restQuery = gson.fromJson(requestBody, RESTQuery.class); + + Category actualCategory = restQuery.getCategory(); + assertEquals("test", actualCategory.getName()); + Collection<Key<?>> keys = actualCategory.getKeys(); + assertEquals(1, keys.size()); + assertTrue(keys.contains(new Key<String>("property1", true))); + List<Qualifier<?>> qualifiers = restQuery.getQualifiers(); + assertEquals(1, qualifiers.size()); + Qualifier<?> qual = qualifiers.get(0); + assertEquals(new Key<String>("property1", true), qual.getKey()); + assertEquals(Criteria.EQUALS, qual.getCriteria()); + assertEquals("fluff", qual.getValue()); + + assertTrue(results.hasNext()); + assertEquals("fluffor1", results.next().getProperty1()); + assertTrue(results.hasNext()); + assertEquals("fluffor2", results.next().getProperty1()); + assertFalse(results.hasNext()); + } + }
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/RESTQuery.java Tue Sep 18 22:52:53 2012 +0200 +++ b/web/common/src/main/java/com/redhat/thermostat/web/common/RESTQuery.java Thu Sep 20 00:28:12 2012 +0200 @@ -40,13 +40,12 @@ import java.util.ArrayList; import java.util.List; -import com.redhat.thermostat.common.storage.Category; +import com.redhat.thermostat.common.storage.AbstractQuery; import com.redhat.thermostat.common.storage.Key; import com.redhat.thermostat.common.storage.Query; -public class RESTQuery implements Query { +public class RESTQuery extends AbstractQuery { - private Category category; private List<Qualifier<?>> qualifiers; private String resultClassName; @@ -55,25 +54,11 @@ } @Override - public Query from(Category category) { - this.category = category; - return this; - } - - @Override public <T> Query where(Key<T> key, Criteria criteria, T value) { qualifiers.add(new Qualifier<>(key, criteria, value)); return this; } - public Category getCategory() { - return category; - } - - public void setCategory(Category category) { - this.category = category; - } - public List<Qualifier<?>> getQualifiers() { return qualifiers; } @@ -89,4 +74,5 @@ public void setResultClassName(String resultClassName) { this.resultClassName = resultClassName; } + }
--- a/web/server/src/main/java/com/redhat/thermostat/web/server/RESTStorageEndPoint.java Tue Sep 18 22:52:53 2012 +0200 +++ b/web/server/src/main/java/com/redhat/thermostat/web/server/RESTStorageEndPoint.java Thu Sep 20 00:28:12 2012 +0200 @@ -2,6 +2,7 @@ import java.io.IOException; import java.io.Reader; +import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServlet; @@ -9,6 +10,7 @@ import javax.servlet.http.HttpServletResponse; import com.google.gson.Gson; +import com.redhat.thermostat.common.storage.Cursor; import com.redhat.thermostat.common.storage.Query; import com.redhat.thermostat.common.storage.Storage; import com.redhat.thermostat.web.common.Qualifier; @@ -19,9 +21,11 @@ public class RESTStorageEndPoint extends HttpServlet { private Storage storage; + private Gson gson; public void init() { storage = StorageWrapper.getStorage(); + gson = new Gson(); } @Override @@ -32,6 +36,8 @@ String cmd = uri.substring(lastPartIdx + 1); if (cmd.equals("find-pojo")) { findPojo(req, resp); + } else if (cmd.equals("find-all")) { + findAll(req, resp); } } @@ -39,23 +45,49 @@ private void findPojo(HttpServletRequest req, HttpServletResponse resp) throws IOException { try { Reader in = req.getReader(); - Gson gson = new Gson(); RESTQuery query = gson.fromJson(in, RESTQuery.class); Class resultClass = Class.forName(query.getResultClassName()); - Query targetQuery = storage.createQuery(); - targetQuery = targetQuery.from(query.getCategory()); - List<Qualifier<?>> qualifiers = query.getQualifiers(); - for (Qualifier q : qualifiers) { - targetQuery = targetQuery.where(q.getKey(), q.getCriteria(), q.getValue()); - } + Query targetQuery = constructTargetQuery(query); Object result = storage.findPojo(targetQuery, resultClass); - resp.setStatus(HttpServletResponse.SC_OK); - resp.setContentType("application/json"); - gson.toJson(result, resp.getWriter()); - resp.flushBuffer(); + writeResponse(resp, result); } catch (ClassNotFoundException e) { resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "result class not found"); } } + @SuppressWarnings({ "rawtypes", "unchecked" }) + private void findAll(HttpServletRequest req, HttpServletResponse resp) throws IOException { + try { + Reader in = req.getReader(); + RESTQuery query = gson.fromJson(in, RESTQuery.class); + Class resultClass = Class.forName(query.getResultClassName()); + Query targetQuery = constructTargetQuery(query); + ArrayList resultList = new ArrayList(); + Cursor result = storage.findAllPojos(targetQuery, resultClass); + while (result.hasNext()) { + resultList.add(result.next()); + } + writeResponse(resp, resultList.toArray()); + } catch (ClassNotFoundException e) { + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "result class not found"); + } + } + + private Query constructTargetQuery(RESTQuery query) { + Query targetQuery = storage.createQuery(); + targetQuery = targetQuery.from(query.getCategory()); + List<Qualifier<?>> qualifiers = query.getQualifiers(); + for (Qualifier q : qualifiers) { + targetQuery = targetQuery.where(q.getKey(), q.getCriteria(), q.getValue()); + } + return targetQuery; + } + + private void writeResponse(HttpServletResponse resp, Object result) throws IOException { + resp.setStatus(HttpServletResponse.SC_OK); + resp.setContentType("application/json"); + gson.toJson(result, resp.getWriter()); + resp.flushBuffer(); + } + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/server/src/test/java/com/redhat/thermostat/web/server/RESTStorageEndpointTest.java Thu Sep 20 00:28:12 2012 +0200 @@ -0,0 +1,210 @@ +/* + * Copyright 2012 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.web.server; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.net.HttpURLConnection; +import java.net.URL; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.webapp.WebAppContext; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.gson.Gson; +import com.redhat.thermostat.common.model.Pojo; +import com.redhat.thermostat.common.storage.Categories; +import com.redhat.thermostat.common.storage.Category; +import com.redhat.thermostat.common.storage.Cursor; +import com.redhat.thermostat.common.storage.Key; +import com.redhat.thermostat.common.storage.Query; +import com.redhat.thermostat.common.storage.Query.Criteria; +import com.redhat.thermostat.common.storage.Storage; +import com.redhat.thermostat.test.FreePortFinder; +import com.redhat.thermostat.test.FreePortFinder.TryPort; +import com.redhat.thermostat.web.client.RESTStorage; +import com.redhat.thermostat.web.common.RESTQuery; +import com.redhat.thermostat.web.common.StorageWrapper; + +public class RESTStorageEndpointTest { + + public static class TestClass implements Pojo { + private String key1; + private int key2; + public String getKey1() { + return key1; + } + public void setKey1(String key1) { + this.key1 = key1; + } + public int getKey2() { + return key2; + } + public void setKey2(int key2) { + this.key2 = key2; + } + } + + private Server server; + private int port; + private Storage mockStorage; + + private static Key<String> key1; + private static Key<Integer> key2; + private static Category category; + + @BeforeClass + public static void setupCategory() { + key1 = new Key<>("key1", true); + key2 = new Key<>("key2", false); + category = new Category("test", key1, key2); + } + + @AfterClass + public static void cleanupCategory() { + Categories.remove(category); + category = null; + key2 = null; + key1 = null; + } + + @Before + public void setUp() throws Exception { + + mockStorage = mock(Storage.class); + StorageWrapper.setStorage(mockStorage); + + port = FreePortFinder.findFreePort(new TryPort() { + + @Override + public void tryPort(int port) throws Exception { + startServer(port); + } + }); + } + + private void startServer(int port) throws Exception { + server = new Server(port); + server.setHandler(new WebAppContext("src/main/webapp", "/")); + server.start(); + } + + @After + public void tearDown() throws Exception { + server.stop(); + server.join(); + } + + @Test + public void testFind() { + // Configure mock storage. + TestClass expected = new TestClass(); + expected.setKey1("fluff"); + expected.setKey2(42); + when(mockStorage.findPojo(any(Query.class), same(TestClass.class))).thenReturn(expected); + + Query mockQuery = QueryTestHelper.createMockQuery(); + when(mockStorage.createQuery()).thenReturn(mockQuery); + + RESTStorage restStorage = new RESTStorage(); + restStorage.setEndpoint(getEndpoint()); + Query query = restStorage.createQuery(); + query.from(category).where(key1, Criteria.EQUALS, "fluff"); + + TestClass result = restStorage.findPojo(query, TestClass.class); + + assertEquals("fluff", result.getKey1()); + assertEquals(42, result.getKey2()); + verify(mockStorage).createQuery(); + verify(mockStorage).findPojo(any(Query.class), same(TestClass.class)); + } + + @Test + public void testFindAllPojos() throws IOException { + TestClass expected1 = new TestClass(); + expected1.setKey1("fluff1"); + expected1.setKey2(42); + TestClass expected2 = new TestClass(); + expected2.setKey1("fluff2"); + expected2.setKey2(43); + @SuppressWarnings("unchecked") + Cursor<TestClass> cursor = mock(Cursor.class); + when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false); + when(cursor.next()).thenReturn(expected1).thenReturn(expected2); + + when(mockStorage.findAllPojos(any(Query.class), same(TestClass.class))).thenReturn(cursor); + Query mockQuery = QueryTestHelper.createMockQuery(); + when(mockStorage.createQuery()).thenReturn(mockQuery); + + String endpoint = getEndpoint(); + URL url = new URL(endpoint + "/find-all"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoInput(true); + conn.setDoOutput(true); + RESTQuery query = (RESTQuery) new RESTQuery().from(category).where(key1, Criteria.EQUALS, "fluff"); + query.setResultClassName(TestClass.class.getName()); + Gson gson = new Gson(); + OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); + gson.toJson(query, out); + out.flush(); + + Reader in = new InputStreamReader(conn.getInputStream()); + TestClass[] results = gson.fromJson(in, TestClass[].class); + assertEquals(2, results.length); + assertEquals("fluff1", results[0].getKey1()); + assertEquals(42, results[0].getKey2()); + assertEquals("fluff2", results[1].getKey1()); + assertEquals(43, results[1].getKey2()); + } + + private String getEndpoint() { + return "http://localhost:" + port + "/storage"; + } +}
--- a/web/server/src/test/java/com/redhat/thermostat/web/server/RESTStorageTest.java Tue Sep 18 22:52:53 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -/* - * Copyright 2012 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.web.server; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.same; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.webapp.WebAppContext; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import com.redhat.thermostat.common.model.Pojo; -import com.redhat.thermostat.common.storage.Category; -import com.redhat.thermostat.common.storage.Key; -import com.redhat.thermostat.common.storage.Query; -import com.redhat.thermostat.common.storage.Query.Criteria; -import com.redhat.thermostat.common.storage.Storage; -import com.redhat.thermostat.test.FreePortFinder; -import com.redhat.thermostat.test.FreePortFinder.TryPort; -import com.redhat.thermostat.web.client.RESTStorage; -import com.redhat.thermostat.web.common.StorageWrapper; - -public class RESTStorageTest { - - public static class TestClass implements Pojo { - private String key1; - private int key2; - public String getKey1() { - return key1; - } - public void setKey1(String key1) { - this.key1 = key1; - } - public int getKey2() { - return key2; - } - public void setKey2(int key2) { - this.key2 = key2; - } - } - - private Server server; - private int port; - private Storage mockStorage; - - @Before - public void setUp() throws Exception { - mockStorage = mock(Storage.class); - StorageWrapper.setStorage(mockStorage); - - port = FreePortFinder.findFreePort(new TryPort() { - - @Override - public void tryPort(int port) throws Exception { - startServer(port); - } - }); - } - - private void startServer(int port) throws Exception { - server = new Server(port); - server.setHandler(new WebAppContext("src/main/webapp", "/")); - server.start(); - } - - @After - public void tearDown() throws Exception { - server.stop(); - server.join(); - } - - @Test - public void testFind() { - // Configure mock storage. - TestClass expected = new TestClass(); - expected.setKey1("fluff"); - expected.setKey2(42); - when(mockStorage.findPojo(any(Query.class), same(TestClass.class))).thenReturn(expected); - - Query mockQuery = QueryTestHelper.createMockQuery(); - when(mockStorage.createQuery()).thenReturn(mockQuery); - - RESTStorage restStorage = new RESTStorage(); - restStorage.setEndpoint("http://localhost:" + port + "/storage"); - Query query = restStorage.createQuery(); - Key<String> key1 = new Key<>("key1", true); - Key<Integer> key2 = new Key<>("key2", false); - Category category = new Category("test", key1, key2); - query.from(category).where(key1, Criteria.EQUALS, "fluff"); - - TestClass result = restStorage.findPojo(query, TestClass.class); - - assertEquals("fluff", result.getKey1()); - assertEquals(42, result.getKey2()); - verify(mockStorage).createQuery(); - verify(mockStorage).findPojo(any(Query.class), same(TestClass.class)); - } -}