Mercurial > hg > release > thermostat-0.9
changeset 766:13eda5b74828
Rename REST* to Web*.
Reviewed-by: jerboaa
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-November/004078.html
line wrap: on
line diff
--- a/web/client/src/main/java/com/redhat/thermostat/web/client/Activator.java Tue Nov 06 11:00:12 2012 -0500 +++ b/web/client/src/main/java/com/redhat/thermostat/web/client/Activator.java Mon Nov 12 15:48:34 2012 +0100 @@ -50,7 +50,7 @@ @Override public void start(BundleContext context) throws Exception { - RESTStorageProvider storage = new RESTStorageProvider(); + WebStorageProvider storage = new WebStorageProvider(); this.reg = context.registerService(StorageProvider.class.getName(), storage, null); }
--- a/web/client/src/main/java/com/redhat/thermostat/web/client/RESTStorage.java Tue Nov 06 11:00:12 2012 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,377 +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.client; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.lang.reflect.Array; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; -import org.apache.http.StatusLine; -import org.apache.http.client.HttpClient; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.mime.MultipartEntity; -import org.apache.http.entity.mime.content.InputStreamBody; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.message.BasicNameValuePair; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.redhat.thermostat.common.model.AgentIdPojo; -import com.redhat.thermostat.common.model.Pojo; -import com.redhat.thermostat.common.storage.Category; -import com.redhat.thermostat.common.storage.Connection; -import com.redhat.thermostat.common.storage.Cursor; -import com.redhat.thermostat.common.storage.Query; -import com.redhat.thermostat.common.storage.Remove; -import com.redhat.thermostat.common.storage.Storage; -import com.redhat.thermostat.common.storage.Update; -import com.redhat.thermostat.web.common.RESTQuery; -import com.redhat.thermostat.web.common.ThermostatGSONConverter; -import com.redhat.thermostat.web.common.WebInsert; -import com.redhat.thermostat.web.common.WebRemove; -import com.redhat.thermostat.web.common.WebUpdate; - -public class RESTStorage extends Storage { - - private final class WebConnection extends Connection { - WebConnection() { - connected = true; - } - @Override - public void disconnect() { - connected = false; - fireChanged(ConnectionStatus.DISCONNECTED); - } - - @Override - public void connect() { - connected = true; - fireChanged(ConnectionStatus.CONNECTED); - } - @Override - public String getUrl() { - return endpoint; - } - } - - private String endpoint; - private UUID agentId; - - private Map<Category, Integer> categoryIds; - private Gson gson; - - public RESTStorage() { - endpoint = "http://localhost:8082"; - categoryIds = new HashMap<>(); - gson = new GsonBuilder().registerTypeHierarchyAdapter(Pojo.class, new ThermostatGSONConverter()).create(); - } - - @Override - public void registerCategory(Category category) { - try { - URL url = new URL(endpoint + "/register-category"); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - String enc = "UTF-8"; - conn.setRequestProperty("Content-Encoding", enc); - conn.setDoOutput(true); - conn.setDoInput(true); - conn.setRequestMethod("POST"); - OutputStream out = conn.getOutputStream(); - OutputStreamWriter writer = new OutputStreamWriter(out); - writer.write("name="); - writer.write(URLEncoder.encode(category.getName(), enc)); - writer.write("&category="); - writer.write(URLEncoder.encode(gson.toJson(category), enc)); - writer.flush(); - - InputStream in = conn.getInputStream(); - Reader reader = new InputStreamReader(in); - Integer id = gson.fromJson(reader, Integer.class); - categoryIds.put(category, id); - } catch (IOException ex) { - throw new RuntimeException(ex); - } - - } - - @Override - public Query createQuery() { - return new RESTQuery(categoryIds); - } - - @Override - public Remove createRemove() { - return new WebRemove(categoryIds); - } - - @Override - public WebUpdate createUpdate() { - return new WebUpdate(categoryIds); - } - - @Override - 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(); - OutputStreamWriter writer = new OutputStreamWriter(out); - ((RESTQuery) query).setResultClassName(resultClass.getName()); - gson.toJson(query, writer); - writer.flush(); - - 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 - public <T extends Pojo> T findPojo(Query query, Class<T> resultClass) { - try { - ((RESTQuery) query).setResultClassName(resultClass.getName()); - URL url = new URL(endpoint + "/find-pojo"); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setDoInput(true); - conn.setDoOutput(true); - conn.setRequestMethod("POST"); - OutputStream out = conn.getOutputStream(); - OutputStreamWriter writer = new OutputStreamWriter(out); - gson.toJson(query, writer); - writer.flush(); - - InputStream in = conn.getInputStream(); - T result = gson.fromJson(new InputStreamReader(in), resultClass); - return result; - } catch (IOException ex) { - throw new RuntimeException(ex); - } - } - - @Override - public String getAgentId() { - return agentId.toString(); - } - - @Override - public Connection getConnection() { - return new WebConnection(); - } - - @Override - public long getCount(Category category) { - try { - URL url = new URL(endpoint + "/get-count"); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setDoInput(true); - conn.setDoOutput(true); - conn.setRequestMethod("POST"); - OutputStream out = conn.getOutputStream(); - OutputStreamWriter writer = new OutputStreamWriter(out); - writer.write("category="); - gson.toJson(categoryIds.get(category), writer); - writer.write("\n"); - writer.flush(); - - InputStream in = conn.getInputStream(); - long result = gson.fromJson(new InputStreamReader(in), Long.class); - return result; - } catch (IOException ex) { - throw new RuntimeException(ex); - } - } - - @Override - public InputStream loadFile(String name) { - try { - HttpClient httpClient = new DefaultHttpClient(); - HttpPost httpPost = new HttpPost(endpoint + "/load-file"); - List<NameValuePair> formparams = new ArrayList<NameValuePair>(); - formparams.add(new BasicNameValuePair("file", name)); - UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, "UTF-8"); - httpPost.setEntity(entity); - HttpResponse response = httpClient.execute(httpPost); - return response.getEntity().getContent(); - } catch (IOException ex) { - throw new RuntimeException(ex); - } - } - - @Override - public void purge() { - try { - HttpClient httpClient = new DefaultHttpClient(); - HttpPost httpPost = new HttpPost(endpoint + "/purge"); - HttpResponse response = httpClient.execute(httpPost); - int status = response.getStatusLine().getStatusCode(); - if (status != 200) { - throw new IOException("Server returned status: " + status); - } - } catch (IOException ex) { - throw new RuntimeException(ex); - } - } - - @Override - public void putPojo(Category category, boolean replace, AgentIdPojo pojo) { - // TODO: This logic should probably be moved elsewhere. I.e. out of the Storage API. - if (pojo.getAgentId() == null) { - pojo.setAgentId(getAgentId()); - } - try { - int categoryId = categoryIds.get(category); - WebInsert insert = new WebInsert(categoryId, replace, pojo.getClass().getName()); - URL url = new URL(endpoint + "/put-pojo"); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setDoOutput(true); - conn.setDoInput(true); - conn.setRequestMethod("POST"); - OutputStream out = conn.getOutputStream(); - OutputStreamWriter writer = new OutputStreamWriter(out); - writer.write("insert="); - writer.write(URLEncoder.encode(gson.toJson(insert), "UTF-8")); - writer.write("&pojo="); - writer.write(URLEncoder.encode(gson.toJson(pojo), "UTF-8")); - writer.flush(); - checkResponseCode(conn); - } catch (IOException ex) { - throw new RuntimeException(ex); - } - } - - private void checkResponseCode(HttpURLConnection conn) throws IOException { - int responseCode = conn.getResponseCode(); - if (responseCode != HttpURLConnection.HTTP_OK) { - throw new RuntimeException("Web server returned HTTP code: " + responseCode); - } - } - - @Override - public void removePojo(Remove remove) { - try { - URL url = new URL(endpoint + "/remove-pojo"); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setDoOutput(true); - conn.setRequestMethod("POST"); - OutputStream out = conn.getOutputStream(); - OutputStreamWriter writer = new OutputStreamWriter(out); - writer.write("remove="); - writer.write(URLEncoder.encode(gson.toJson(remove), "UTF-8")); - writer.flush(); - checkResponseCode(conn); - } catch (IOException ex) { - throw new RuntimeException(ex); - } - } - - @Override - public void saveFile(String name, InputStream in) { - try { - HttpClient httpClient = new DefaultHttpClient(); - HttpPost httpPost = new HttpPost(endpoint + "/save-file"); - InputStreamBody body = new InputStreamBody(in, name); - MultipartEntity entity = new MultipartEntity(); - entity.addPart("file", body); - httpPost.setEntity(entity); - HttpResponse response = httpClient.execute(httpPost); - StatusLine status = response.getStatusLine(); - if (status.getStatusCode() != 200) { - throw new IOException("Server returned status: " + status); - } - } catch (IOException ex) { - throw new RuntimeException(ex); - } - } - - @Override - public void setAgentId(UUID agentId) { - this.agentId = agentId; - } - - @Override - public void updatePojo(Update update) { - WebUpdate webUp = (WebUpdate) update; - try { - URL url = new URL(endpoint + "/update-pojo"); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setDoOutput(true); - conn.setDoInput(true); - conn.setRequestMethod("POST"); - OutputStream out = conn.getOutputStream(); - OutputStreamWriter writer = new OutputStreamWriter(out); - writer.write("update="); - writer.write(URLEncoder.encode(gson.toJson(webUp), "UTF-8")); - List<WebUpdate.UpdateValue> updateValues = webUp.getUpdates(); - List<Object> values = new ArrayList<>(updateValues.size()); - for (WebUpdate.UpdateValue updateValue : updateValues) { - values.add(updateValue.getValue()); - } - writer.write("&values="); - writer.write(URLEncoder.encode(gson.toJson(values), "UTF-8")); - writer.flush(); - checkResponseCode(conn); - } catch (IOException ex) { - throw new RuntimeException(ex); - } - } - - public void setEndpoint(String endpoint) { - this.endpoint = endpoint; - } - -}
--- a/web/client/src/main/java/com/redhat/thermostat/web/client/RESTStorageProvider.java Tue Nov 06 11:00:12 2012 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -package com.redhat.thermostat.web.client; - -import com.redhat.thermostat.common.config.StartupConfiguration; -import com.redhat.thermostat.common.storage.Storage; -import com.redhat.thermostat.common.storage.StorageProvider; - -public class RESTStorageProvider implements StorageProvider { - - private StartupConfiguration config; - - @Override - public Storage createStorage() { - return new RESTStorage(); - } - - @Override - public void setConfig(StartupConfiguration config) { - this.config = config; - } - - @Override - public boolean canHandleProtocol() { - // use http since this might be https at some point - return config.getDBConnectionString().startsWith("http"); - } - -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/client/src/main/java/com/redhat/thermostat/web/client/WebStorage.java Mon Nov 12 15:48:34 2012 +0100 @@ -0,0 +1,377 @@ +/* + * 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 java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.lang.reflect.Array; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.StatusLine; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.mime.MultipartEntity; +import org.apache.http.entity.mime.content.InputStreamBody; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.redhat.thermostat.common.model.AgentIdPojo; +import com.redhat.thermostat.common.model.Pojo; +import com.redhat.thermostat.common.storage.Category; +import com.redhat.thermostat.common.storage.Connection; +import com.redhat.thermostat.common.storage.Cursor; +import com.redhat.thermostat.common.storage.Query; +import com.redhat.thermostat.common.storage.Remove; +import com.redhat.thermostat.common.storage.Storage; +import com.redhat.thermostat.common.storage.Update; +import com.redhat.thermostat.web.common.WebQuery; +import com.redhat.thermostat.web.common.ThermostatGSONConverter; +import com.redhat.thermostat.web.common.WebInsert; +import com.redhat.thermostat.web.common.WebRemove; +import com.redhat.thermostat.web.common.WebUpdate; + +public class WebStorage extends Storage { + + private final class WebConnection extends Connection { + WebConnection() { + connected = true; + } + @Override + public void disconnect() { + connected = false; + fireChanged(ConnectionStatus.DISCONNECTED); + } + + @Override + public void connect() { + connected = true; + fireChanged(ConnectionStatus.CONNECTED); + } + @Override + public String getUrl() { + return endpoint; + } + } + + private String endpoint; + private UUID agentId; + + private Map<Category, Integer> categoryIds; + private Gson gson; + + public WebStorage() { + endpoint = "http://localhost:8082"; + categoryIds = new HashMap<>(); + gson = new GsonBuilder().registerTypeHierarchyAdapter(Pojo.class, new ThermostatGSONConverter()).create(); + } + + @Override + public void registerCategory(Category category) { + try { + URL url = new URL(endpoint + "/register-category"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + String enc = "UTF-8"; + conn.setRequestProperty("Content-Encoding", enc); + conn.setDoOutput(true); + conn.setDoInput(true); + conn.setRequestMethod("POST"); + OutputStream out = conn.getOutputStream(); + OutputStreamWriter writer = new OutputStreamWriter(out); + writer.write("name="); + writer.write(URLEncoder.encode(category.getName(), enc)); + writer.write("&category="); + writer.write(URLEncoder.encode(gson.toJson(category), enc)); + writer.flush(); + + InputStream in = conn.getInputStream(); + Reader reader = new InputStreamReader(in); + Integer id = gson.fromJson(reader, Integer.class); + categoryIds.put(category, id); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + + } + + @Override + public Query createQuery() { + return new WebQuery(categoryIds); + } + + @Override + public Remove createRemove() { + return new WebRemove(categoryIds); + } + + @Override + public WebUpdate createUpdate() { + return new WebUpdate(categoryIds); + } + + @Override + 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(); + OutputStreamWriter writer = new OutputStreamWriter(out); + ((WebQuery) query).setResultClassName(resultClass.getName()); + gson.toJson(query, writer); + writer.flush(); + + 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 + public <T extends Pojo> T findPojo(Query query, Class<T> resultClass) { + try { + ((WebQuery) query).setResultClassName(resultClass.getName()); + URL url = new URL(endpoint + "/find-pojo"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoInput(true); + conn.setDoOutput(true); + conn.setRequestMethod("POST"); + OutputStream out = conn.getOutputStream(); + OutputStreamWriter writer = new OutputStreamWriter(out); + gson.toJson(query, writer); + writer.flush(); + + InputStream in = conn.getInputStream(); + T result = gson.fromJson(new InputStreamReader(in), resultClass); + return result; + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + @Override + public String getAgentId() { + return agentId.toString(); + } + + @Override + public Connection getConnection() { + return new WebConnection(); + } + + @Override + public long getCount(Category category) { + try { + URL url = new URL(endpoint + "/get-count"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoInput(true); + conn.setDoOutput(true); + conn.setRequestMethod("POST"); + OutputStream out = conn.getOutputStream(); + OutputStreamWriter writer = new OutputStreamWriter(out); + writer.write("category="); + gson.toJson(categoryIds.get(category), writer); + writer.write("\n"); + writer.flush(); + + InputStream in = conn.getInputStream(); + long result = gson.fromJson(new InputStreamReader(in), Long.class); + return result; + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + @Override + public InputStream loadFile(String name) { + try { + HttpClient httpClient = new DefaultHttpClient(); + HttpPost httpPost = new HttpPost(endpoint + "/load-file"); + List<NameValuePair> formparams = new ArrayList<NameValuePair>(); + formparams.add(new BasicNameValuePair("file", name)); + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, "UTF-8"); + httpPost.setEntity(entity); + HttpResponse response = httpClient.execute(httpPost); + return response.getEntity().getContent(); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + @Override + public void purge() { + try { + HttpClient httpClient = new DefaultHttpClient(); + HttpPost httpPost = new HttpPost(endpoint + "/purge"); + HttpResponse response = httpClient.execute(httpPost); + int status = response.getStatusLine().getStatusCode(); + if (status != 200) { + throw new IOException("Server returned status: " + status); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + @Override + public void putPojo(Category category, boolean replace, AgentIdPojo pojo) { + // TODO: This logic should probably be moved elsewhere. I.e. out of the Storage API. + if (pojo.getAgentId() == null) { + pojo.setAgentId(getAgentId()); + } + try { + int categoryId = categoryIds.get(category); + WebInsert insert = new WebInsert(categoryId, replace, pojo.getClass().getName()); + URL url = new URL(endpoint + "/put-pojo"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoOutput(true); + conn.setDoInput(true); + conn.setRequestMethod("POST"); + OutputStream out = conn.getOutputStream(); + OutputStreamWriter writer = new OutputStreamWriter(out); + writer.write("insert="); + writer.write(URLEncoder.encode(gson.toJson(insert), "UTF-8")); + writer.write("&pojo="); + writer.write(URLEncoder.encode(gson.toJson(pojo), "UTF-8")); + writer.flush(); + checkResponseCode(conn); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + private void checkResponseCode(HttpURLConnection conn) throws IOException { + int responseCode = conn.getResponseCode(); + if (responseCode != HttpURLConnection.HTTP_OK) { + throw new RuntimeException("Web server returned HTTP code: " + responseCode); + } + } + + @Override + public void removePojo(Remove remove) { + try { + URL url = new URL(endpoint + "/remove-pojo"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoOutput(true); + conn.setRequestMethod("POST"); + OutputStream out = conn.getOutputStream(); + OutputStreamWriter writer = new OutputStreamWriter(out); + writer.write("remove="); + writer.write(URLEncoder.encode(gson.toJson(remove), "UTF-8")); + writer.flush(); + checkResponseCode(conn); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + @Override + public void saveFile(String name, InputStream in) { + try { + HttpClient httpClient = new DefaultHttpClient(); + HttpPost httpPost = new HttpPost(endpoint + "/save-file"); + InputStreamBody body = new InputStreamBody(in, name); + MultipartEntity entity = new MultipartEntity(); + entity.addPart("file", body); + httpPost.setEntity(entity); + HttpResponse response = httpClient.execute(httpPost); + StatusLine status = response.getStatusLine(); + if (status.getStatusCode() != 200) { + throw new IOException("Server returned status: " + status); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + @Override + public void setAgentId(UUID agentId) { + this.agentId = agentId; + } + + @Override + public void updatePojo(Update update) { + WebUpdate webUp = (WebUpdate) update; + try { + URL url = new URL(endpoint + "/update-pojo"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoOutput(true); + conn.setDoInput(true); + conn.setRequestMethod("POST"); + OutputStream out = conn.getOutputStream(); + OutputStreamWriter writer = new OutputStreamWriter(out); + writer.write("update="); + writer.write(URLEncoder.encode(gson.toJson(webUp), "UTF-8")); + List<WebUpdate.UpdateValue> updateValues = webUp.getUpdates(); + List<Object> values = new ArrayList<>(updateValues.size()); + for (WebUpdate.UpdateValue updateValue : updateValues) { + values.add(updateValue.getValue()); + } + writer.write("&values="); + writer.write(URLEncoder.encode(gson.toJson(values), "UTF-8")); + writer.flush(); + checkResponseCode(conn); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/client/src/main/java/com/redhat/thermostat/web/client/WebStorageProvider.java Mon Nov 12 15:48:34 2012 +0100 @@ -0,0 +1,27 @@ +package com.redhat.thermostat.web.client; + +import com.redhat.thermostat.common.config.StartupConfiguration; +import com.redhat.thermostat.common.storage.Storage; +import com.redhat.thermostat.common.storage.StorageProvider; + +public class WebStorageProvider implements StorageProvider { + + private StartupConfiguration config; + + @Override + public Storage createStorage() { + return new WebStorage(); + } + + @Override + public void setConfig(StartupConfiguration config) { + this.config = config; + } + + @Override + public boolean canHandleProtocol() { + // use http since this might be https at some point + return config.getDBConnectionString().startsWith("http"); + } + +}
--- a/web/client/src/test/java/com/redhat/thermostat/web/client/RESTStorageTest.java Tue Nov 06 11:00:12 2012 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,462 +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.client; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.io.StringReader; -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.server.Request; -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.google.gson.JsonArray; -import com.google.gson.JsonParser; -import com.google.gson.JsonSyntaxException; -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.Remove; -import com.redhat.thermostat.test.FreePortFinder; -import com.redhat.thermostat.test.FreePortFinder.TryPort; -import com.redhat.thermostat.web.common.Qualifier; -import com.redhat.thermostat.web.common.RESTQuery; -import com.redhat.thermostat.web.common.WebInsert; -import com.redhat.thermostat.web.common.WebRemove; -import com.redhat.thermostat.web.common.WebUpdate; - -public class RESTStorageTest { - - private Server server; - - private int port; - - private String requestBody; - - private String responseBody; - private Map<String,String> headers; - private String method; - private String requestURI; - - private static Category category; - private static Key<String> key1; - private static Key<Integer> key2; - - private RESTStorage storage; - - @BeforeClass - public static void setupCategory() { - key1 = new Key<>("property1", true); - key2 = new Key<>("property2", 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() { - @Override - public void tryPort(int port) throws Exception { - startServer(port); - } - }); - - storage = new RESTStorage(); - storage.setEndpoint("http://localhost:" + port + "/"); - storage.setAgentId(new UUID(123, 456)); - headers = new HashMap<>(); - requestURI = null; - method = null; - registerCategory(); - } - - private void startServer(int port) throws Exception { - server = new Server(port); - server.setHandler(new AbstractHandler() { - - @Override - public void handle(String target, Request baseRequest, - HttpServletRequest request, HttpServletResponse response) - throws IOException, ServletException { - Enumeration<String> headerNames = request.getHeaderNames(); - while (headerNames.hasMoreElements()) { - String headerName = headerNames.nextElement(); - headers.put(headerName, request.getHeader(headerName)); - } - - method = request.getMethod(); - requestURI = request.getRequestURI(); - - // Read request body. - StringBuilder body = new StringBuilder(); - Reader reader = request.getReader(); - while (true) { - int read = reader.read(); - if (read == -1) { - break; - } - body.append((char) read); - } - requestBody = body.toString(); - // Send response body. - response.setStatus(HttpServletResponse.SC_OK); - if (responseBody != null) { - response.getWriter().write(responseBody); - } - baseRequest.setHandled(true); - } - }); - server.start(); - } - - @After - public void tearDown() throws Exception { - - headers = null; - requestURI = null; - method = null; - storage = null; - - server.stop(); - server.join(); - } - - private void registerCategory() { - - // Return 42 for categoryId. - Gson gson = new Gson(); - responseBody = gson.toJson(42); - - storage.registerCategory(category); - } - - @Test - public void testFindPojo() { - - TestObj obj = new TestObj(); - obj.setProperty1("fluffor"); - Gson gson = new Gson(); - responseBody = gson.toJson(obj); - - 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); - - assertEquals(42, restQuery.getCategoryId()); - 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()); - - assertEquals("fluffor", result.getProperty1()); - } - - @Test - public void testFindAllPojos() { - - 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); - - assertEquals(42, restQuery.getCategoryId()); - 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()); - } - - @Test - public void testPut() throws IOException, JsonSyntaxException, ClassNotFoundException { - - TestObj obj = new TestObj(); - obj.setProperty1("fluff"); - - storage.putPojo(category, true, obj); - - Gson gson = new Gson(); - StringReader reader = new StringReader(requestBody); - BufferedReader bufRead = new BufferedReader(reader); - String line = URLDecoder.decode(bufRead.readLine(), "UTF-8"); - String [] params = line.split("&"); - assertEquals(2, params.length); - String[] parts = params[0].split("="); - assertEquals("insert", parts[0]); - WebInsert insert = gson.fromJson(parts[1], WebInsert.class); - assertEquals(42, insert.getCategoryId()); - assertEquals(true, insert.isReplace()); - assertEquals(TestObj.class.getName(), insert.getPojoClass()); - - parts = params[1].split("="); - assertEquals(2, parts.length); - assertEquals("pojo", parts[0]); - Object resultObj = gson.fromJson(parts[1], Class.forName(insert.getPojoClass())); - assertEquals(obj, resultObj); - } - - @Test - public void testCreateRemove() { - WebRemove remove = (WebRemove) storage.createRemove(); - assertNotNull(remove); - remove = remove.from(category); - assertEquals(42, remove.getCategoryId()); - assertNotNull(remove); - remove = remove.where(key1, "test"); - assertNotNull(remove); - List<Qualifier<?>> qualifiers = remove.getQualifiers(); - assertEquals(1, qualifiers.size()); - Qualifier<?> qualifier = qualifiers.get(0); - assertEquals(key1, qualifier.getKey()); - assertEquals(Criteria.EQUALS, qualifier.getCriteria()); - assertEquals("test", qualifier.getValue()); - } - - @Test - public void testRemovePojo() throws UnsupportedEncodingException, IOException { - Remove remove = storage.createRemove().from(category).where(key1, "test"); - storage.removePojo(remove); - - Gson gson = new Gson(); - StringReader reader = new StringReader(requestBody); - BufferedReader bufRead = new BufferedReader(reader); - String line = URLDecoder.decode(bufRead.readLine(), "UTF-8"); - System.err.println("line: " + line); - String[] parts = line.split("="); - assertEquals("remove", parts[0]); - WebRemove actualRemove = gson.fromJson(parts[1], WebRemove.class); - - assertEquals(42, actualRemove.getCategoryId()); - List<Qualifier<?>> qualifiers = actualRemove.getQualifiers(); - assertEquals(1, qualifiers.size()); - Qualifier<?> qualifier = qualifiers.get(0); - assertEquals(key1, qualifier.getKey()); - assertEquals(Criteria.EQUALS, qualifier.getCriteria()); - assertEquals("test", qualifier.getValue()); - } - - @Test - public void testCreateUpdate() { - WebUpdate update = (WebUpdate) storage.createUpdate(); - assertNotNull(update); - update = update.from(category); - assertEquals(42, update.getCategoryId()); - assertNotNull(update); - update = update.where(key1, "test"); - assertNotNull(update); - List<Qualifier<?>> qualifiers = update.getQualifiers(); - assertEquals(1, qualifiers.size()); - Qualifier<?> qualifier = qualifiers.get(0); - assertEquals(key1, qualifier.getKey()); - assertEquals(Criteria.EQUALS, qualifier.getCriteria()); - assertEquals("test", qualifier.getValue()); - update = update.set(key1, "fluff"); - assertNotNull(update); - List<WebUpdate.UpdateValue> updates = update.getUpdates(); - assertEquals(1, updates.size()); - assertEquals("fluff", updates.get(0).getValue()); - assertEquals(key1, updates.get(0).getKey()); - assertEquals("java.lang.String", updates.get(0).getValueClass()); - } - - @Test - public void testUpdate() throws UnsupportedEncodingException, IOException, JsonSyntaxException, ClassNotFoundException { - - WebUpdate update = storage.createUpdate().from(category).where(key1, "test").set(key1, "fluff").set(key2, 42); - storage.updatePojo(update); - - Gson gson = new Gson(); - StringReader reader = new StringReader(requestBody); - BufferedReader bufRead = new BufferedReader(reader); - String line = URLDecoder.decode(bufRead.readLine(), "UTF-8"); - String [] params = line.split("&"); - assertEquals(2, params.length); - String[] parts = params[0].split("="); - assertEquals("update", parts[0]); - WebUpdate receivedUpdate = gson.fromJson(parts[1], WebUpdate.class); - assertEquals(42, receivedUpdate.getCategoryId()); - - List<WebUpdate.UpdateValue> updates = receivedUpdate.getUpdates(); - assertEquals(2, updates.size()); - - WebUpdate.UpdateValue update1 = updates.get(0); - assertEquals(key1, update1.getKey()); - assertEquals("java.lang.String", update1.getValueClass()); - assertNull(update1.getValue()); - - WebUpdate.UpdateValue update2 = updates.get(1); - assertEquals(key2, update2.getKey()); - assertEquals("java.lang.Integer", update2.getValueClass()); - assertNull(update2.getValue()); - - List<Qualifier<?>> qualifiers = receivedUpdate.getQualifiers(); - assertEquals(1, qualifiers.size()); - Qualifier<?> qualifier = qualifiers.get(0); - assertEquals(key1, qualifier.getKey()); - assertEquals(Criteria.EQUALS, qualifier.getCriteria()); - assertEquals("test", qualifier.getValue()); - - parts = params[1].split("="); - assertEquals(2, parts.length); - assertEquals("values", parts[0]); - JsonParser jsonParser = new JsonParser(); - JsonArray jsonArray = jsonParser.parse(parts[1]).getAsJsonArray(); - String value1 = gson.fromJson(jsonArray.get(0), String.class); - assertEquals("fluff", value1); - int value2 = gson.fromJson(jsonArray.get(1), Integer.class); - assertEquals(42, value2); - } - - @Test - public void testGetCount() throws UnsupportedEncodingException, IOException { - - Gson gson = new Gson(); - responseBody = gson.toJson(12345); - - long result = storage.getCount(category); - - StringReader reader = new StringReader(requestBody); - BufferedReader bufRead = new BufferedReader(reader); - String line = URLDecoder.decode(bufRead.readLine(), "UTF-8"); - String[] parts = line.split("="); - assertEquals("category", parts[0]); - assertEquals("42", parts[1]); - assertEquals(12345, result); - } - - @Test - public void testSaveFile() { - String data = "Hello World"; - ByteArrayInputStream in = new ByteArrayInputStream(data.getBytes()); - storage.saveFile("fluff", in); - assertEquals("chunked", headers.get("Transfer-Encoding")); - String contentType = headers.get("Content-Type"); - assertTrue(contentType.startsWith("multipart/form-data; boundary=")); - String boundary = contentType.split("boundary=")[1]; - String[] lines = requestBody.split("\n"); - assertEquals("--" + boundary, lines[0].trim()); - assertEquals("Content-Disposition: form-data; name=\"file\"; filename=\"fluff\"", lines[1].trim()); - assertEquals("Content-Type: application/octet-stream", lines[2].trim()); - assertEquals("Content-Transfer-Encoding: binary", lines[3].trim()); - assertEquals("", lines[4].trim()); - assertEquals("Hello World", lines[5].trim()); - assertEquals("--" + boundary + "--", lines[6].trim()); - - } - - @Test - public void testLoadFile() throws IOException { - responseBody = "Hello World"; - InputStream in = storage.loadFile("fluff"); - assertEquals("file=fluff", requestBody.trim()); - byte[] data = new byte[11]; - int totalRead = 0; - while (totalRead < 11) { - int read = in.read(data, totalRead, 11 - totalRead); - if (read < 0) { - fail(); - } - totalRead += read; - } - assertEquals("Hello World", new String(data)); - - } - - @Test - public void testPurge() { - storage.purge(); - assertEquals("POST", method); - assertTrue(requestURI.endsWith("/purge")); - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/client/src/test/java/com/redhat/thermostat/web/client/WebStorageTest.java Mon Nov 12 15:48:34 2012 +0100 @@ -0,0 +1,462 @@ +/* + * 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.server.Request; +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.google.gson.JsonArray; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; +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.Remove; +import com.redhat.thermostat.test.FreePortFinder; +import com.redhat.thermostat.test.FreePortFinder.TryPort; +import com.redhat.thermostat.web.common.Qualifier; +import com.redhat.thermostat.web.common.WebQuery; +import com.redhat.thermostat.web.common.WebInsert; +import com.redhat.thermostat.web.common.WebRemove; +import com.redhat.thermostat.web.common.WebUpdate; + +public class WebStorageTest { + + private Server server; + + private int port; + + private String requestBody; + + private String responseBody; + private Map<String,String> headers; + private String method; + private String requestURI; + + private static Category category; + private static Key<String> key1; + private static Key<Integer> key2; + + private WebStorage storage; + + @BeforeClass + public static void setupCategory() { + key1 = new Key<>("property1", true); + key2 = new Key<>("property2", 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() { + @Override + public void tryPort(int port) throws Exception { + startServer(port); + } + }); + + storage = new WebStorage(); + storage.setEndpoint("http://localhost:" + port + "/"); + storage.setAgentId(new UUID(123, 456)); + headers = new HashMap<>(); + requestURI = null; + method = null; + registerCategory(); + } + + private void startServer(int port) throws Exception { + server = new Server(port); + server.setHandler(new AbstractHandler() { + + @Override + public void handle(String target, Request baseRequest, + HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException { + Enumeration<String> headerNames = request.getHeaderNames(); + while (headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + headers.put(headerName, request.getHeader(headerName)); + } + + method = request.getMethod(); + requestURI = request.getRequestURI(); + + // Read request body. + StringBuilder body = new StringBuilder(); + Reader reader = request.getReader(); + while (true) { + int read = reader.read(); + if (read == -1) { + break; + } + body.append((char) read); + } + requestBody = body.toString(); + // Send response body. + response.setStatus(HttpServletResponse.SC_OK); + if (responseBody != null) { + response.getWriter().write(responseBody); + } + baseRequest.setHandled(true); + } + }); + server.start(); + } + + @After + public void tearDown() throws Exception { + + headers = null; + requestURI = null; + method = null; + storage = null; + + server.stop(); + server.join(); + } + + private void registerCategory() { + + // Return 42 for categoryId. + Gson gson = new Gson(); + responseBody = gson.toJson(42); + + storage.registerCategory(category); + } + + @Test + public void testFindPojo() { + + TestObj obj = new TestObj(); + obj.setProperty1("fluffor"); + Gson gson = new Gson(); + responseBody = gson.toJson(obj); + + Query query = storage.createQuery().from(category).where(key1, Criteria.EQUALS, "fluff"); + + TestObj result = storage.findPojo(query, TestObj.class); + WebQuery restQuery = gson.fromJson(requestBody, WebQuery.class); + + assertEquals(42, restQuery.getCategoryId()); + 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()); + + assertEquals("fluffor", result.getProperty1()); + } + + @Test + public void testFindAllPojos() { + + 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); + WebQuery restQuery = gson.fromJson(requestBody, WebQuery.class); + + assertEquals(42, restQuery.getCategoryId()); + 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()); + } + + @Test + public void testPut() throws IOException, JsonSyntaxException, ClassNotFoundException { + + TestObj obj = new TestObj(); + obj.setProperty1("fluff"); + + storage.putPojo(category, true, obj); + + Gson gson = new Gson(); + StringReader reader = new StringReader(requestBody); + BufferedReader bufRead = new BufferedReader(reader); + String line = URLDecoder.decode(bufRead.readLine(), "UTF-8"); + String [] params = line.split("&"); + assertEquals(2, params.length); + String[] parts = params[0].split("="); + assertEquals("insert", parts[0]); + WebInsert insert = gson.fromJson(parts[1], WebInsert.class); + assertEquals(42, insert.getCategoryId()); + assertEquals(true, insert.isReplace()); + assertEquals(TestObj.class.getName(), insert.getPojoClass()); + + parts = params[1].split("="); + assertEquals(2, parts.length); + assertEquals("pojo", parts[0]); + Object resultObj = gson.fromJson(parts[1], Class.forName(insert.getPojoClass())); + assertEquals(obj, resultObj); + } + + @Test + public void testCreateRemove() { + WebRemove remove = (WebRemove) storage.createRemove(); + assertNotNull(remove); + remove = remove.from(category); + assertEquals(42, remove.getCategoryId()); + assertNotNull(remove); + remove = remove.where(key1, "test"); + assertNotNull(remove); + List<Qualifier<?>> qualifiers = remove.getQualifiers(); + assertEquals(1, qualifiers.size()); + Qualifier<?> qualifier = qualifiers.get(0); + assertEquals(key1, qualifier.getKey()); + assertEquals(Criteria.EQUALS, qualifier.getCriteria()); + assertEquals("test", qualifier.getValue()); + } + + @Test + public void testRemovePojo() throws UnsupportedEncodingException, IOException { + Remove remove = storage.createRemove().from(category).where(key1, "test"); + storage.removePojo(remove); + + Gson gson = new Gson(); + StringReader reader = new StringReader(requestBody); + BufferedReader bufRead = new BufferedReader(reader); + String line = URLDecoder.decode(bufRead.readLine(), "UTF-8"); + System.err.println("line: " + line); + String[] parts = line.split("="); + assertEquals("remove", parts[0]); + WebRemove actualRemove = gson.fromJson(parts[1], WebRemove.class); + + assertEquals(42, actualRemove.getCategoryId()); + List<Qualifier<?>> qualifiers = actualRemove.getQualifiers(); + assertEquals(1, qualifiers.size()); + Qualifier<?> qualifier = qualifiers.get(0); + assertEquals(key1, qualifier.getKey()); + assertEquals(Criteria.EQUALS, qualifier.getCriteria()); + assertEquals("test", qualifier.getValue()); + } + + @Test + public void testCreateUpdate() { + WebUpdate update = (WebUpdate) storage.createUpdate(); + assertNotNull(update); + update = update.from(category); + assertEquals(42, update.getCategoryId()); + assertNotNull(update); + update = update.where(key1, "test"); + assertNotNull(update); + List<Qualifier<?>> qualifiers = update.getQualifiers(); + assertEquals(1, qualifiers.size()); + Qualifier<?> qualifier = qualifiers.get(0); + assertEquals(key1, qualifier.getKey()); + assertEquals(Criteria.EQUALS, qualifier.getCriteria()); + assertEquals("test", qualifier.getValue()); + update = update.set(key1, "fluff"); + assertNotNull(update); + List<WebUpdate.UpdateValue> updates = update.getUpdates(); + assertEquals(1, updates.size()); + assertEquals("fluff", updates.get(0).getValue()); + assertEquals(key1, updates.get(0).getKey()); + assertEquals("java.lang.String", updates.get(0).getValueClass()); + } + + @Test + public void testUpdate() throws UnsupportedEncodingException, IOException, JsonSyntaxException, ClassNotFoundException { + + WebUpdate update = storage.createUpdate().from(category).where(key1, "test").set(key1, "fluff").set(key2, 42); + storage.updatePojo(update); + + Gson gson = new Gson(); + StringReader reader = new StringReader(requestBody); + BufferedReader bufRead = new BufferedReader(reader); + String line = URLDecoder.decode(bufRead.readLine(), "UTF-8"); + String [] params = line.split("&"); + assertEquals(2, params.length); + String[] parts = params[0].split("="); + assertEquals("update", parts[0]); + WebUpdate receivedUpdate = gson.fromJson(parts[1], WebUpdate.class); + assertEquals(42, receivedUpdate.getCategoryId()); + + List<WebUpdate.UpdateValue> updates = receivedUpdate.getUpdates(); + assertEquals(2, updates.size()); + + WebUpdate.UpdateValue update1 = updates.get(0); + assertEquals(key1, update1.getKey()); + assertEquals("java.lang.String", update1.getValueClass()); + assertNull(update1.getValue()); + + WebUpdate.UpdateValue update2 = updates.get(1); + assertEquals(key2, update2.getKey()); + assertEquals("java.lang.Integer", update2.getValueClass()); + assertNull(update2.getValue()); + + List<Qualifier<?>> qualifiers = receivedUpdate.getQualifiers(); + assertEquals(1, qualifiers.size()); + Qualifier<?> qualifier = qualifiers.get(0); + assertEquals(key1, qualifier.getKey()); + assertEquals(Criteria.EQUALS, qualifier.getCriteria()); + assertEquals("test", qualifier.getValue()); + + parts = params[1].split("="); + assertEquals(2, parts.length); + assertEquals("values", parts[0]); + JsonParser jsonParser = new JsonParser(); + JsonArray jsonArray = jsonParser.parse(parts[1]).getAsJsonArray(); + String value1 = gson.fromJson(jsonArray.get(0), String.class); + assertEquals("fluff", value1); + int value2 = gson.fromJson(jsonArray.get(1), Integer.class); + assertEquals(42, value2); + } + + @Test + public void testGetCount() throws UnsupportedEncodingException, IOException { + + Gson gson = new Gson(); + responseBody = gson.toJson(12345); + + long result = storage.getCount(category); + + StringReader reader = new StringReader(requestBody); + BufferedReader bufRead = new BufferedReader(reader); + String line = URLDecoder.decode(bufRead.readLine(), "UTF-8"); + String[] parts = line.split("="); + assertEquals("category", parts[0]); + assertEquals("42", parts[1]); + assertEquals(12345, result); + } + + @Test + public void testSaveFile() { + String data = "Hello World"; + ByteArrayInputStream in = new ByteArrayInputStream(data.getBytes()); + storage.saveFile("fluff", in); + assertEquals("chunked", headers.get("Transfer-Encoding")); + String contentType = headers.get("Content-Type"); + assertTrue(contentType.startsWith("multipart/form-data; boundary=")); + String boundary = contentType.split("boundary=")[1]; + String[] lines = requestBody.split("\n"); + assertEquals("--" + boundary, lines[0].trim()); + assertEquals("Content-Disposition: form-data; name=\"file\"; filename=\"fluff\"", lines[1].trim()); + assertEquals("Content-Type: application/octet-stream", lines[2].trim()); + assertEquals("Content-Transfer-Encoding: binary", lines[3].trim()); + assertEquals("", lines[4].trim()); + assertEquals("Hello World", lines[5].trim()); + assertEquals("--" + boundary + "--", lines[6].trim()); + + } + + @Test + public void testLoadFile() throws IOException { + responseBody = "Hello World"; + InputStream in = storage.loadFile("fluff"); + assertEquals("file=fluff", requestBody.trim()); + byte[] data = new byte[11]; + int totalRead = 0; + while (totalRead < 11) { + int read = in.read(data, totalRead, 11 - totalRead); + if (read < 0) { + fail(); + } + totalRead += read; + } + assertEquals("Hello World", new String(data)); + + } + + @Test + public void testPurge() { + storage.purge(); + assertEquals("POST", method); + assertTrue(requestURI.endsWith("/purge")); + } +}
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/RESTQuery.java Tue Nov 06 11:00:12 2012 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +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.common; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -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 RESTQuery extends AbstractQuery { - - private List<Qualifier<?>> qualifiers; - private String resultClassName; - - private transient Map<Category, Integer> categoryIdMap; - - private int categoryId; - - public RESTQuery() { - this(null); - } - - public RESTQuery(Map<Category, Integer> categoryIdMap) { - qualifiers = new ArrayList<>(); - this.categoryIdMap = categoryIdMap; - } - - @Override - public Query from(Category category) { - categoryId = categoryIdMap.get(category); - return this; - } - - public int getCategoryId() { - return categoryId; - } - - public void setCategoryId(int categoryId) { - this.categoryId = categoryId; - } - - @Override - public <T> Query where(Key<T> key, Criteria criteria, T value) { - qualifiers.add(new Qualifier<>(key, criteria, value)); - return this; - } - - public List<Qualifier<?>> getQualifiers() { - return qualifiers; - } - - public void setQualifiers(List<Qualifier<?>> qualifiers) { - this.qualifiers = qualifiers; - } - - public String getResultClassName() { - return resultClassName; - } - - public void setResultClassName(String resultClassName) { - this.resultClassName = resultClassName; - } - -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/common/src/main/java/com/redhat/thermostat/web/common/WebQuery.java Mon Nov 12 15:48:34 2012 +0100 @@ -0,0 +1,103 @@ +/* + * 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.common; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +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 WebQuery extends AbstractQuery { + + private List<Qualifier<?>> qualifiers; + private String resultClassName; + + private transient Map<Category, Integer> categoryIdMap; + + private int categoryId; + + public WebQuery() { + this(null); + } + + public WebQuery(Map<Category, Integer> categoryIdMap) { + qualifiers = new ArrayList<>(); + this.categoryIdMap = categoryIdMap; + } + + @Override + public Query from(Category category) { + categoryId = categoryIdMap.get(category); + return this; + } + + public int getCategoryId() { + return categoryId; + } + + public void setCategoryId(int categoryId) { + this.categoryId = categoryId; + } + + @Override + public <T> Query where(Key<T> key, Criteria criteria, T value) { + qualifiers.add(new Qualifier<>(key, criteria, value)); + return this; + } + + public List<Qualifier<?>> getQualifiers() { + return qualifiers; + } + + public void setQualifiers(List<Qualifier<?>> qualifiers) { + this.qualifiers = qualifiers; + } + + public String getResultClassName() { + return resultClassName; + } + + public void setResultClassName(String resultClassName) { + this.resultClassName = resultClassName; + } + +}
--- a/web/common/src/test/java/RESTQueryTest.java Tue Nov 06 11:00:12 2012 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.junit.Test; - -import com.redhat.thermostat.common.storage.Category; -import com.redhat.thermostat.common.storage.Key; -import com.redhat.thermostat.common.storage.Query.Criteria; -import com.redhat.thermostat.web.common.Qualifier; -import com.redhat.thermostat.web.common.RESTQuery; - -/* - * 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. - */ - -public class RESTQueryTest { - - @Test - public void test() { - Key<String> key1 = new Key<>("testkey", true); - Category category = new Category("test", key1); - Map<Category,Integer> categoryIdMap = new HashMap<>(); - categoryIdMap.put(category, 42); - RESTQuery query = new RESTQuery(categoryIdMap); - query.from(category).where(key1, Criteria.EQUALS, "fluff"); - - List<Qualifier<?>> qualifiers = query.getQualifiers(); - assertEquals(1, qualifiers.size()); - Qualifier<?> qualifier = qualifiers.get(0); - assertEquals(key1, qualifier.getKey()); - assertEquals(Criteria.EQUALS, qualifier.getCriteria()); - assertEquals("fluff", qualifier.getValue()); - - assertEquals(42, query.getCategoryId()); - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/common/src/test/java/com/redhat/thermostat/web/common/WebQueryTest.java Mon Nov 12 15:48:34 2012 +0100 @@ -0,0 +1,73 @@ +package com.redhat.thermostat.web.common; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +import com.redhat.thermostat.common.storage.Category; +import com.redhat.thermostat.common.storage.Key; +import com.redhat.thermostat.common.storage.Query.Criteria; +import com.redhat.thermostat.web.common.Qualifier; +import com.redhat.thermostat.web.common.WebQuery; + +/* + * 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. + */ + +public class WebQueryTest { + + @Test + public void test() { + Key<String> key1 = new Key<>("testkey", true); + Category category = new Category("test", key1); + Map<Category,Integer> categoryIdMap = new HashMap<>(); + categoryIdMap.put(category, 42); + WebQuery query = new WebQuery(categoryIdMap); + query.from(category).where(key1, Criteria.EQUALS, "fluff"); + + List<Qualifier<?>> qualifiers = query.getQualifiers(); + assertEquals(1, qualifiers.size()); + Qualifier<?> qualifier = qualifiers.get(0); + assertEquals(key1, qualifier.getKey()); + assertEquals(Criteria.EQUALS, qualifier.getCriteria()); + assertEquals("fluff", qualifier.getValue()); + + assertEquals(42, query.getCategoryId()); + } +}
--- a/web/server/src/main/java/com/redhat/thermostat/web/server/RESTStorageEndPoint.java Tue Nov 06 11:00:12 2012 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,340 +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 java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileItemFactory; -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.apache.commons.fileupload.servlet.ServletFileUpload; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; -import com.google.gson.JsonParser; -import com.redhat.thermostat.common.model.AgentIdPojo; -import com.redhat.thermostat.common.model.Pojo; -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.Remove; -import com.redhat.thermostat.common.storage.Storage; -import com.redhat.thermostat.common.storage.Update; -import com.redhat.thermostat.web.common.Qualifier; -import com.redhat.thermostat.web.common.RESTQuery; -import com.redhat.thermostat.web.common.StorageWrapper; -import com.redhat.thermostat.web.common.ThermostatGSONConverter; -import com.redhat.thermostat.web.common.WebInsert; -import com.redhat.thermostat.web.common.WebRemove; -import com.redhat.thermostat.web.common.WebUpdate; - -@SuppressWarnings("serial") -public class RESTStorageEndPoint extends HttpServlet { - - private Storage storage; - private Gson gson; - - static final String STORAGE_ENDPOINT = "storageEndpoint"; - - private int currentCategoryId; - - private Map<String, Integer> categoryIds; - private Map<Integer, Category> categories; - - public void init() { - gson = new GsonBuilder().registerTypeHierarchyAdapter(Pojo.class, new ThermostatGSONConverter()).create(); - categoryIds = new HashMap<>(); - categories = new HashMap<>(); - } - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { - if (storage == null) { - storage = StorageWrapper.getStorage(); - } - String uri = req.getRequestURI(); - int lastPartIdx = uri.lastIndexOf("/"); - String cmd = uri.substring(lastPartIdx + 1); - if (cmd.equals("find-pojo")) { - findPojo(req, resp); - } else if (cmd.equals("find-all")) { - findAll(req, resp); - } else if (cmd.equals("put-pojo")) { - putPojo(req, resp); - } else if (cmd.equals("register-category")) { - registerCategory(req, resp); - } else if (cmd.equals("remove-pojo")) { - removePojo(req, resp); - } else if (cmd.equals("update-pojo")) { - updatePojo(req, resp); - } else if (cmd.equals("get-count")) { - getCount(req, resp); - } else if (cmd.equals("save-file")) { - saveFile(req, resp); - } else if (cmd.equals("load-file")) { - loadFile(req, resp); - } else if (cmd.equals("purge")) { - purge(req, resp); - } - } - - private void purge(HttpServletRequest req, HttpServletResponse resp) { - storage.purge(); - resp.setStatus(HttpServletResponse.SC_OK); - } - - private void loadFile(HttpServletRequest req, HttpServletResponse resp) throws IOException { - String name = req.getParameter("file"); - InputStream data = storage.loadFile(name); - OutputStream out = resp.getOutputStream(); - byte[] buffer = new byte[512]; - int read = 0; - while (read >= 0) { - read = data.read(buffer); - if (read > 0) { - out.write(buffer, 0, read); - } - } - } - - private void saveFile(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - boolean isMultipart = ServletFileUpload.isMultipartContent(req); - if (! isMultipart) { - throw new ServletException("expected multipart message"); - } - FileItemFactory factory = new DiskFileItemFactory(); - ServletFileUpload upload = new ServletFileUpload(factory); - try { - @SuppressWarnings("unchecked") - List<FileItem> items = upload.parseRequest(req); - for (FileItem item : items) { - String fieldName = item.getFieldName(); - if (fieldName.equals("file")) { - String name = item.getName(); - InputStream in = item.getInputStream(); - storage.saveFile(name, in); - } - } - } catch (FileUploadException ex) { - throw new ServletException(ex); - } - - } - - private void getCount(HttpServletRequest req, HttpServletResponse resp) { - try { - String categoryParam = req.getParameter("category"); - int categoryId = gson.fromJson(categoryParam, Integer.class); - Category category = categories.get(categoryId); - long result = storage.getCount(category); - resp.setStatus(HttpServletResponse.SC_OK); - resp.setContentType("application/json"); - gson.toJson(result, resp.getWriter()); - resp.flushBuffer(); - } catch (IOException ex) { - ex.printStackTrace(); - resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } - } - - private synchronized void registerCategory(HttpServletRequest req, HttpServletResponse resp) throws IOException { - String categoryName = req.getParameter("name"); - String categoryParam = req.getParameter("category"); - int id; - if (categoryIds.containsKey(categoryName)) { - id = categoryIds.get(categoryName); - } else { - // The following has the side effect of registering the newly deserialized Category in the Categories clas. - Category category = gson.fromJson(categoryParam, Category.class); - storage.registerCategory(category); - - id = currentCategoryId; - categoryIds.put(categoryName, id); - categories.put(id, category); - currentCategoryId++; - } - resp.setStatus(HttpServletResponse.SC_OK); - resp.setContentType("application/json"); - Writer writer = resp.getWriter(); - gson.toJson(id, writer); - writer.flush(); - } - - private void putPojo(HttpServletRequest req, HttpServletResponse resp) { - try { - String insertParam = req.getParameter("insert"); - WebInsert insert = gson.fromJson(insertParam, WebInsert.class); - Class<? extends AgentIdPojo> pojoCls = (Class<? extends AgentIdPojo>) Class.forName(insert.getPojoClass()); - String pojoParam = req.getParameter("pojo"); - AgentIdPojo pojo = gson.fromJson(pojoParam, pojoCls); - int categoryId = insert.getCategoryId(); - Category category = getCategoryFromId(categoryId); - storage.putPojo(category, insert.isReplace(), pojo); - resp.setStatus(HttpServletResponse.SC_OK); - } catch (ClassNotFoundException ex) { - resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private void removePojo(HttpServletRequest req, HttpServletResponse resp) { - String removeParam = req.getParameter("remove"); - WebRemove remove = gson.fromJson(removeParam, WebRemove.class); - Remove targetRemove = storage.createRemove(); - targetRemove = targetRemove.from(getCategoryFromId(remove.getCategoryId())); - List<Qualifier<?>> qualifiers = remove.getQualifiers(); - for (Qualifier qualifier : qualifiers) { - assert (qualifier.getCriteria() == Criteria.EQUALS); - targetRemove = targetRemove.where(qualifier.getKey(), qualifier.getValue()); - } - storage.removePojo(targetRemove); - resp.setStatus(HttpServletResponse.SC_OK); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private void updatePojo(HttpServletRequest req, HttpServletResponse resp) { - try { - String updateParam = req.getParameter("update"); - WebUpdate update = gson.fromJson(updateParam, WebUpdate.class); - Update targetUpdate = storage.createUpdate(); - targetUpdate = targetUpdate.from(getCategoryFromId(update.getCategoryId())); - List<Qualifier<?>> qualifiers = update.getQualifiers(); - for (Qualifier qualifier : qualifiers) { - assert (qualifier.getCriteria() == Criteria.EQUALS); - targetUpdate = targetUpdate.where(qualifier.getKey(), qualifier.getValue()); - } - List<WebUpdate.UpdateValue> updates = update.getUpdates(); - if (updates != null) { - String valuesParam = req.getParameter("values"); - JsonParser parser = new JsonParser(); - JsonArray jsonArray = parser.parse(valuesParam) - .getAsJsonArray(); - int index = 0; - for (WebUpdate.UpdateValue updateValue : updates) { - Class valueClass = Class.forName(updateValue - .getValueClass()); - Object value = gson.fromJson(jsonArray.get(index), - valueClass); - index++; - Key key = updateValue.getKey(); - targetUpdate.set(key, value); - } - } - storage.updatePojo(targetUpdate); - resp.setStatus(HttpServletResponse.SC_OK); - } catch (ClassNotFoundException ex) { - ex.printStackTrace(); - resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private void findPojo(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); - Object result = storage.findPojo(targetQuery, resultClass); - writeResponse(resp, result); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - 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) { - e.printStackTrace(); - resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "result class not found"); - } - } - - private Query constructTargetQuery(RESTQuery query) { - Query targetQuery = storage.createQuery(); - int categoryId = query.getCategoryId(); - Category category = getCategoryFromId(categoryId); - targetQuery = targetQuery.from(category); - List<Qualifier<?>> qualifiers = query.getQualifiers(); - for (Qualifier q : qualifiers) { - targetQuery = targetQuery.where(q.getKey(), q.getCriteria(), q.getValue()); - } - return targetQuery; - } - - private Category getCategoryFromId(int categoryId) { - Category category = categories.get(categoryId); - return category; - } - - 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(); - } - -}
--- a/web/server/src/main/java/com/redhat/thermostat/web/server/WebServiceCommand.java Tue Nov 06 11:00:12 2012 -0500 +++ b/web/server/src/main/java/com/redhat/thermostat/web/server/WebServiceCommand.java Mon Nov 12 15:48:34 2012 +0100 @@ -43,10 +43,6 @@ public class WebServiceCommand extends SimpleCommand { - public WebServiceCommand() { - // TODO Auto-generated constructor stub - } - @Override public void run(CommandContext ctx) throws CommandException { String storageURL = ctx.getArguments().getArgument("storageURL");
--- a/web/server/src/main/java/com/redhat/thermostat/web/server/WebServiceLauncher.java Tue Nov 06 11:00:12 2012 -0500 +++ b/web/server/src/main/java/com/redhat/thermostat/web/server/WebServiceLauncher.java Mon Nov 12 15:48:34 2012 +0100 @@ -51,8 +51,8 @@ void start() throws Exception { server = new Server(port); ServletHandler handler = new ServletHandler(); - ServletHolder servletHolder = new ServletHolder("rest-storage-end-point", new RESTStorageEndPoint()); - servletHolder.setInitParameter(RESTStorageEndPoint.STORAGE_ENDPOINT, storageURL); + ServletHolder servletHolder = new ServletHolder("rest-storage-end-point", new WebStorageEndPoint()); + servletHolder.setInitParameter(WebStorageEndPoint.STORAGE_ENDPOINT, storageURL); handler.setServlets(new ServletHolder[] { servletHolder }); ServletMapping mapping = new ServletMapping(); mapping.setPathSpec("/");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/server/src/main/java/com/redhat/thermostat/web/server/WebStorageEndPoint.java Mon Nov 12 15:48:34 2012 +0100 @@ -0,0 +1,340 @@ +/* + * 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 java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileItemFactory; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonParser; +import com.redhat.thermostat.common.model.AgentIdPojo; +import com.redhat.thermostat.common.model.Pojo; +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.Remove; +import com.redhat.thermostat.common.storage.Storage; +import com.redhat.thermostat.common.storage.Update; +import com.redhat.thermostat.web.common.Qualifier; +import com.redhat.thermostat.web.common.WebQuery; +import com.redhat.thermostat.web.common.StorageWrapper; +import com.redhat.thermostat.web.common.ThermostatGSONConverter; +import com.redhat.thermostat.web.common.WebInsert; +import com.redhat.thermostat.web.common.WebRemove; +import com.redhat.thermostat.web.common.WebUpdate; + +@SuppressWarnings("serial") +public class WebStorageEndPoint extends HttpServlet { + + private Storage storage; + private Gson gson; + + static final String STORAGE_ENDPOINT = "storageEndpoint"; + + private int currentCategoryId; + + private Map<String, Integer> categoryIds; + private Map<Integer, Category> categories; + + public void init() { + gson = new GsonBuilder().registerTypeHierarchyAdapter(Pojo.class, new ThermostatGSONConverter()).create(); + categoryIds = new HashMap<>(); + categories = new HashMap<>(); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + if (storage == null) { + storage = StorageWrapper.getStorage(); + } + String uri = req.getRequestURI(); + int lastPartIdx = uri.lastIndexOf("/"); + String cmd = uri.substring(lastPartIdx + 1); + if (cmd.equals("find-pojo")) { + findPojo(req, resp); + } else if (cmd.equals("find-all")) { + findAll(req, resp); + } else if (cmd.equals("put-pojo")) { + putPojo(req, resp); + } else if (cmd.equals("register-category")) { + registerCategory(req, resp); + } else if (cmd.equals("remove-pojo")) { + removePojo(req, resp); + } else if (cmd.equals("update-pojo")) { + updatePojo(req, resp); + } else if (cmd.equals("get-count")) { + getCount(req, resp); + } else if (cmd.equals("save-file")) { + saveFile(req, resp); + } else if (cmd.equals("load-file")) { + loadFile(req, resp); + } else if (cmd.equals("purge")) { + purge(req, resp); + } + } + + private void purge(HttpServletRequest req, HttpServletResponse resp) { + storage.purge(); + resp.setStatus(HttpServletResponse.SC_OK); + } + + private void loadFile(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String name = req.getParameter("file"); + InputStream data = storage.loadFile(name); + OutputStream out = resp.getOutputStream(); + byte[] buffer = new byte[512]; + int read = 0; + while (read >= 0) { + read = data.read(buffer); + if (read > 0) { + out.write(buffer, 0, read); + } + } + } + + private void saveFile(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + boolean isMultipart = ServletFileUpload.isMultipartContent(req); + if (! isMultipart) { + throw new ServletException("expected multipart message"); + } + FileItemFactory factory = new DiskFileItemFactory(); + ServletFileUpload upload = new ServletFileUpload(factory); + try { + @SuppressWarnings("unchecked") + List<FileItem> items = upload.parseRequest(req); + for (FileItem item : items) { + String fieldName = item.getFieldName(); + if (fieldName.equals("file")) { + String name = item.getName(); + InputStream in = item.getInputStream(); + storage.saveFile(name, in); + } + } + } catch (FileUploadException ex) { + throw new ServletException(ex); + } + + } + + private void getCount(HttpServletRequest req, HttpServletResponse resp) { + try { + String categoryParam = req.getParameter("category"); + int categoryId = gson.fromJson(categoryParam, Integer.class); + Category category = categories.get(categoryId); + long result = storage.getCount(category); + resp.setStatus(HttpServletResponse.SC_OK); + resp.setContentType("application/json"); + gson.toJson(result, resp.getWriter()); + resp.flushBuffer(); + } catch (IOException ex) { + ex.printStackTrace(); + resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + + private synchronized void registerCategory(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String categoryName = req.getParameter("name"); + String categoryParam = req.getParameter("category"); + int id; + if (categoryIds.containsKey(categoryName)) { + id = categoryIds.get(categoryName); + } else { + // The following has the side effect of registering the newly deserialized Category in the Categories clas. + Category category = gson.fromJson(categoryParam, Category.class); + storage.registerCategory(category); + + id = currentCategoryId; + categoryIds.put(categoryName, id); + categories.put(id, category); + currentCategoryId++; + } + resp.setStatus(HttpServletResponse.SC_OK); + resp.setContentType("application/json"); + Writer writer = resp.getWriter(); + gson.toJson(id, writer); + writer.flush(); + } + + private void putPojo(HttpServletRequest req, HttpServletResponse resp) { + try { + String insertParam = req.getParameter("insert"); + WebInsert insert = gson.fromJson(insertParam, WebInsert.class); + Class<? extends AgentIdPojo> pojoCls = (Class<? extends AgentIdPojo>) Class.forName(insert.getPojoClass()); + String pojoParam = req.getParameter("pojo"); + AgentIdPojo pojo = gson.fromJson(pojoParam, pojoCls); + int categoryId = insert.getCategoryId(); + Category category = getCategoryFromId(categoryId); + storage.putPojo(category, insert.isReplace(), pojo); + resp.setStatus(HttpServletResponse.SC_OK); + } catch (ClassNotFoundException ex) { + resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private void removePojo(HttpServletRequest req, HttpServletResponse resp) { + String removeParam = req.getParameter("remove"); + WebRemove remove = gson.fromJson(removeParam, WebRemove.class); + Remove targetRemove = storage.createRemove(); + targetRemove = targetRemove.from(getCategoryFromId(remove.getCategoryId())); + List<Qualifier<?>> qualifiers = remove.getQualifiers(); + for (Qualifier qualifier : qualifiers) { + assert (qualifier.getCriteria() == Criteria.EQUALS); + targetRemove = targetRemove.where(qualifier.getKey(), qualifier.getValue()); + } + storage.removePojo(targetRemove); + resp.setStatus(HttpServletResponse.SC_OK); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private void updatePojo(HttpServletRequest req, HttpServletResponse resp) { + try { + String updateParam = req.getParameter("update"); + WebUpdate update = gson.fromJson(updateParam, WebUpdate.class); + Update targetUpdate = storage.createUpdate(); + targetUpdate = targetUpdate.from(getCategoryFromId(update.getCategoryId())); + List<Qualifier<?>> qualifiers = update.getQualifiers(); + for (Qualifier qualifier : qualifiers) { + assert (qualifier.getCriteria() == Criteria.EQUALS); + targetUpdate = targetUpdate.where(qualifier.getKey(), qualifier.getValue()); + } + List<WebUpdate.UpdateValue> updates = update.getUpdates(); + if (updates != null) { + String valuesParam = req.getParameter("values"); + JsonParser parser = new JsonParser(); + JsonArray jsonArray = parser.parse(valuesParam) + .getAsJsonArray(); + int index = 0; + for (WebUpdate.UpdateValue updateValue : updates) { + Class valueClass = Class.forName(updateValue + .getValueClass()); + Object value = gson.fromJson(jsonArray.get(index), + valueClass); + index++; + Key key = updateValue.getKey(); + targetUpdate.set(key, value); + } + } + storage.updatePojo(targetUpdate); + resp.setStatus(HttpServletResponse.SC_OK); + } catch (ClassNotFoundException ex) { + ex.printStackTrace(); + resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private void findPojo(HttpServletRequest req, HttpServletResponse resp) throws IOException { + try { + Reader in = req.getReader(); + WebQuery query = gson.fromJson(in, WebQuery.class); + Class resultClass = Class.forName(query.getResultClassName()); + Query targetQuery = constructTargetQuery(query); + Object result = storage.findPojo(targetQuery, resultClass); + writeResponse(resp, result); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + 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(); + WebQuery query = gson.fromJson(in, WebQuery.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) { + e.printStackTrace(); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "result class not found"); + } + } + + private Query constructTargetQuery(WebQuery query) { + Query targetQuery = storage.createQuery(); + int categoryId = query.getCategoryId(); + Category category = getCategoryFromId(categoryId); + targetQuery = targetQuery.from(category); + List<Qualifier<?>> qualifiers = query.getQualifiers(); + for (Qualifier q : qualifiers) { + targetQuery = targetQuery.where(q.getKey(), q.getCriteria(), q.getValue()); + } + return targetQuery; + } + + private Category getCategoryFromId(int categoryId) { + Category category = categories.get(categoryId); + return category; + } + + 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(); + } + +}
--- a/web/server/src/main/webapp/WEB-INF/web.xml Tue Nov 06 11:00:12 2012 -0500 +++ b/web/server/src/main/webapp/WEB-INF/web.xml Mon Nov 12 15:48:34 2012 +0100 @@ -7,7 +7,7 @@ <servlet> <servlet-name>reststorage-servlet</servlet-name> - <servlet-class>com.redhat.thermostat.web.server.RESTStorageEndPoint</servlet-class> + <servlet-class>com.redhat.thermostat.web.server.WebStorageEndPoint</servlet-class> </servlet> <servlet-mapping>
--- a/web/server/src/test/java/com/redhat/thermostat/web/server/RESTStorageEndpointTest.java Tue Nov 06 11:00:12 2012 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,469 +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.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -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.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLEncoder; -import java.util.HashMap; -import java.util.Map; - -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 org.mockito.ArgumentCaptor; - -import com.google.gson.Gson; -import com.redhat.thermostat.common.model.BasePojo; -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.Entity; -import com.redhat.thermostat.common.storage.Key; -import com.redhat.thermostat.common.storage.Persist; -import com.redhat.thermostat.common.storage.Query; -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; -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; -import com.redhat.thermostat.web.common.WebInsert; -import com.redhat.thermostat.web.common.WebRemove; -import com.redhat.thermostat.web.common.WebUpdate; - -public class RESTStorageEndpointTest { - - @Entity - public static class TestClass extends BasePojo { - private String key1; - private int key2; - @Persist - public String getKey1() { - return key1; - } - @Persist - public void setKey1(String key1) { - this.key1 = key1; - } - @Persist - public int getKey2() { - return key2; - } - @Persist - public void setKey2(int key2) { - this.key2 = key2; - } - public boolean equals(Object o) { - if (! (o instanceof TestClass)) { - return false; - } - TestClass other = (TestClass) o; - return key1.equals(other.key1) && key2 == other.key2; - } - } - - private Server server; - private int port; - private Storage mockStorage; - private Integer categoryId; - - 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); - } - }); - registerCategory(); - } - - 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()); - restStorage.registerCategory(category); - 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); - Map<Category,Integer> categoryIdMap = new HashMap<>(); - categoryIdMap.put(category, categoryId); - RESTQuery query = (RESTQuery) new RESTQuery(categoryIdMap).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()); - } - - @Test - public void testPutPojo() throws IOException { - - TestClass expected1 = new TestClass(); - expected1.setKey1("fluff1"); - expected1.setKey2(42); - - String endpoint = getEndpoint(); - - URL url = new URL(endpoint + "/put-pojo"); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setDoOutput(true); - conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - WebInsert insert = new WebInsert(categoryId, true, TestClass.class.getName()); - Gson gson = new Gson(); - OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); - out.write("insert="); - gson.toJson(insert, out); - out.flush(); - out.write("&pojo="); - gson.toJson(expected1, out); - out.write("\n"); - out.flush(); - assertEquals(200, conn.getResponseCode()); - verify(mockStorage).putPojo(category, true, expected1); - } - - @Test - public void testRemovePojo() throws IOException { - - Remove mockRemove = mock(Remove.class); - when(mockRemove.from(any(Category.class))).thenReturn(mockRemove); - when(mockRemove.where(any(Key.class), any())).thenReturn(mockRemove); - - when(mockStorage.createRemove()).thenReturn(mockRemove); - - String endpoint = getEndpoint(); - - URL url = new URL(endpoint + "/remove-pojo"); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setDoOutput(true); - conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - Map<Category,Integer> categoryIds = new HashMap<>(); - categoryIds.put(category, categoryId); - WebRemove remove = new WebRemove(categoryIds).from(category).where(key1, "test"); - Gson gson = new Gson(); - OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); - out.write("remove="); - gson.toJson(remove, out); - out.write("\n"); - out.flush(); - - assertEquals(200, conn.getResponseCode()); - verify(mockStorage).createRemove(); - verify(mockRemove).from(category); - verify(mockRemove).where(key1, "test"); - verify(mockStorage).removePojo(mockRemove); - } - - @Test - public void testUpdatePojo() throws IOException { - - Update mockUpdate = mock(Update.class); - when(mockUpdate.from(any(Category.class))).thenReturn(mockUpdate); - when(mockUpdate.where(any(Key.class), any())).thenReturn(mockUpdate); - when(mockUpdate.set(any(Key.class), any())).thenReturn(mockUpdate); - when(mockStorage.createUpdate()).thenReturn(mockUpdate); - - String endpoint = getEndpoint(); - - URL url = new URL(endpoint + "/update-pojo"); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setDoOutput(true); - conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - Map<Category,Integer> categoryIds = new HashMap<>(); - categoryIds.put(category, categoryId); - WebUpdate update = new WebUpdate(categoryIds).from(category).where(key1, "test").set(key1, "fluff").set(key2, 42); - Gson gson = new Gson(); - OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); - out.write("update="); - gson.toJson(update, out); - out.write("&values="); - gson.toJson(new Object[] {"fluff", 42 }, out); - out.write("\n"); - out.flush(); - - assertEquals(200, conn.getResponseCode()); - verify(mockStorage).createUpdate(); - verify(mockUpdate).from(category); - verify(mockUpdate).where(key1, "test"); - verify(mockUpdate).set(key1, "fluff"); - verify(mockUpdate).set(key2, 42); - verify(mockStorage).updatePojo(mockUpdate); - } - - - @Test - public void testGetCount() throws IOException { - - when(mockStorage.getCount(category)).thenReturn(12345L); - String endpoint = getEndpoint(); - - URL url = new URL(endpoint + "/get-count"); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setDoOutput(true); - conn.setDoInput(true); - conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - Gson gson = new Gson(); - OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); - out.write("category=" + categoryId); - out.flush(); - - InputStream in = conn.getInputStream(); - Reader reader = new InputStreamReader(in); - long result = gson.fromJson(reader, Long.class); - assertEquals(200, conn.getResponseCode()); - assertEquals(12345, result); - verify(mockStorage).getCount(category); - - } - - @Test - public void testSaveFile() throws IOException { - String endpoint = getEndpoint(); - - URL url = new URL(endpoint + "/save-file"); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setDoOutput(true); - conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=fluff"); - conn.setRequestProperty("Transfer-Encoding", "chunked"); - OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); - out.write("--fluff\r\n"); - out.write("Content-Disposition: form-data; name=\"file\"; filename=\"fluff\"\r\n"); - out.write("Content-Type: application/octet-stream\r\n"); - out.write("Content-Transfer-Encoding: binary\r\n"); - out.write("\r\n"); - out.write("Hello World\r\n"); - out.write("--fluff--\r\n"); - out.flush(); - int status = conn.getResponseCode(); - System.err.println("status: " + status); - ArgumentCaptor<InputStream> inCaptor = ArgumentCaptor.forClass(InputStream.class); - verify(mockStorage).saveFile(eq("fluff"), inCaptor.capture()); - InputStream in = inCaptor.getValue(); - byte[] data = new byte[11]; - int totalRead = 0; - while (totalRead < 11) { - int read = in.read(data, totalRead, 11 - totalRead); - if (read < 0) { - fail(); - } - totalRead += read; - } - assertEquals("Hello World", new String(data)); - } - - @Test - public void testLoadFile() throws IOException { - - byte[] data = "Hello World".getBytes(); - InputStream in = new ByteArrayInputStream(data); - when(mockStorage.loadFile("fluff")).thenReturn(in); - - String endpoint = getEndpoint(); - URL url = new URL(endpoint + "/load-file"); - - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setDoOutput(true); - conn.setDoInput(true); - OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); - out.write("file=fluff"); - out.flush(); - in = conn.getInputStream(); - data = new byte[11]; - int totalRead = 0; - while (totalRead < 11) { - int read = in.read(data, totalRead, 11 - totalRead); - if (read < 0) { - fail(); - } - totalRead += read; - } - assertEquals("Hello World", new String(data)); - verify(mockStorage).loadFile("fluff"); - } - - @Test - public void testPurge() throws IOException { - String endpoint = getEndpoint(); - URL url = new URL(endpoint + "/purge"); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setDoOutput(true); - conn.setRequestMethod("POST"); - int status = conn.getResponseCode(); - assertEquals(200, status); - verify(mockStorage).purge(); - } - - private void registerCategory() { - try { - String endpoint = getEndpoint(); - URL url = new URL(endpoint + "/register-category"); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - String enc = "UTF-8"; - conn.setRequestProperty("Content-Encoding", enc); - conn.setDoOutput(true); - conn.setDoInput(true); - conn.setRequestMethod("POST"); - OutputStream out = conn.getOutputStream(); - Gson gson = new Gson(); - OutputStreamWriter writer = new OutputStreamWriter(out); - writer.write("name="); - writer.write(URLEncoder.encode(category.getName(), enc)); - writer.write("&category="); - writer.write(URLEncoder.encode(gson.toJson(category), enc)); - writer.flush(); - - InputStream in = conn.getInputStream(); - Reader reader = new InputStreamReader(in); - Integer id = gson.fromJson(reader, Integer.class); - categoryId = id; - } catch (IOException ex) { - throw new RuntimeException(ex); - } - } - - private String getEndpoint() { - return "http://localhost:" + port + "/storage"; - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/server/src/test/java/com/redhat/thermostat/web/server/WebStorageEndpointTest.java Mon Nov 12 15:48:34 2012 +0100 @@ -0,0 +1,469 @@ +/* + * 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.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +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.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Map; + +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 org.mockito.ArgumentCaptor; + +import com.google.gson.Gson; +import com.redhat.thermostat.common.model.BasePojo; +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.Entity; +import com.redhat.thermostat.common.storage.Key; +import com.redhat.thermostat.common.storage.Persist; +import com.redhat.thermostat.common.storage.Query; +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; +import com.redhat.thermostat.test.FreePortFinder; +import com.redhat.thermostat.test.FreePortFinder.TryPort; +import com.redhat.thermostat.web.client.WebStorage; +import com.redhat.thermostat.web.common.WebQuery; +import com.redhat.thermostat.web.common.StorageWrapper; +import com.redhat.thermostat.web.common.WebInsert; +import com.redhat.thermostat.web.common.WebRemove; +import com.redhat.thermostat.web.common.WebUpdate; + +public class WebStorageEndpointTest { + + @Entity + public static class TestClass extends BasePojo { + private String key1; + private int key2; + @Persist + public String getKey1() { + return key1; + } + @Persist + public void setKey1(String key1) { + this.key1 = key1; + } + @Persist + public int getKey2() { + return key2; + } + @Persist + public void setKey2(int key2) { + this.key2 = key2; + } + public boolean equals(Object o) { + if (! (o instanceof TestClass)) { + return false; + } + TestClass other = (TestClass) o; + return key1.equals(other.key1) && key2 == other.key2; + } + } + + private Server server; + private int port; + private Storage mockStorage; + private Integer categoryId; + + 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); + } + }); + registerCategory(); + } + + 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); + + WebStorage restStorage = new WebStorage(); + restStorage.setEndpoint(getEndpoint()); + restStorage.registerCategory(category); + 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); + Map<Category,Integer> categoryIdMap = new HashMap<>(); + categoryIdMap.put(category, categoryId); + WebQuery query = (WebQuery) new WebQuery(categoryIdMap).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()); + } + + @Test + public void testPutPojo() throws IOException { + + TestClass expected1 = new TestClass(); + expected1.setKey1("fluff1"); + expected1.setKey2(42); + + String endpoint = getEndpoint(); + + URL url = new URL(endpoint + "/put-pojo"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoOutput(true); + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + WebInsert insert = new WebInsert(categoryId, true, TestClass.class.getName()); + Gson gson = new Gson(); + OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); + out.write("insert="); + gson.toJson(insert, out); + out.flush(); + out.write("&pojo="); + gson.toJson(expected1, out); + out.write("\n"); + out.flush(); + assertEquals(200, conn.getResponseCode()); + verify(mockStorage).putPojo(category, true, expected1); + } + + @Test + public void testRemovePojo() throws IOException { + + Remove mockRemove = mock(Remove.class); + when(mockRemove.from(any(Category.class))).thenReturn(mockRemove); + when(mockRemove.where(any(Key.class), any())).thenReturn(mockRemove); + + when(mockStorage.createRemove()).thenReturn(mockRemove); + + String endpoint = getEndpoint(); + + URL url = new URL(endpoint + "/remove-pojo"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoOutput(true); + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + Map<Category,Integer> categoryIds = new HashMap<>(); + categoryIds.put(category, categoryId); + WebRemove remove = new WebRemove(categoryIds).from(category).where(key1, "test"); + Gson gson = new Gson(); + OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); + out.write("remove="); + gson.toJson(remove, out); + out.write("\n"); + out.flush(); + + assertEquals(200, conn.getResponseCode()); + verify(mockStorage).createRemove(); + verify(mockRemove).from(category); + verify(mockRemove).where(key1, "test"); + verify(mockStorage).removePojo(mockRemove); + } + + @Test + public void testUpdatePojo() throws IOException { + + Update mockUpdate = mock(Update.class); + when(mockUpdate.from(any(Category.class))).thenReturn(mockUpdate); + when(mockUpdate.where(any(Key.class), any())).thenReturn(mockUpdate); + when(mockUpdate.set(any(Key.class), any())).thenReturn(mockUpdate); + when(mockStorage.createUpdate()).thenReturn(mockUpdate); + + String endpoint = getEndpoint(); + + URL url = new URL(endpoint + "/update-pojo"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoOutput(true); + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + Map<Category,Integer> categoryIds = new HashMap<>(); + categoryIds.put(category, categoryId); + WebUpdate update = new WebUpdate(categoryIds).from(category).where(key1, "test").set(key1, "fluff").set(key2, 42); + Gson gson = new Gson(); + OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); + out.write("update="); + gson.toJson(update, out); + out.write("&values="); + gson.toJson(new Object[] {"fluff", 42 }, out); + out.write("\n"); + out.flush(); + + assertEquals(200, conn.getResponseCode()); + verify(mockStorage).createUpdate(); + verify(mockUpdate).from(category); + verify(mockUpdate).where(key1, "test"); + verify(mockUpdate).set(key1, "fluff"); + verify(mockUpdate).set(key2, 42); + verify(mockStorage).updatePojo(mockUpdate); + } + + + @Test + public void testGetCount() throws IOException { + + when(mockStorage.getCount(category)).thenReturn(12345L); + String endpoint = getEndpoint(); + + URL url = new URL(endpoint + "/get-count"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoOutput(true); + conn.setDoInput(true); + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + Gson gson = new Gson(); + OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); + out.write("category=" + categoryId); + out.flush(); + + InputStream in = conn.getInputStream(); + Reader reader = new InputStreamReader(in); + long result = gson.fromJson(reader, Long.class); + assertEquals(200, conn.getResponseCode()); + assertEquals(12345, result); + verify(mockStorage).getCount(category); + + } + + @Test + public void testSaveFile() throws IOException { + String endpoint = getEndpoint(); + + URL url = new URL(endpoint + "/save-file"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoOutput(true); + conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=fluff"); + conn.setRequestProperty("Transfer-Encoding", "chunked"); + OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); + out.write("--fluff\r\n"); + out.write("Content-Disposition: form-data; name=\"file\"; filename=\"fluff\"\r\n"); + out.write("Content-Type: application/octet-stream\r\n"); + out.write("Content-Transfer-Encoding: binary\r\n"); + out.write("\r\n"); + out.write("Hello World\r\n"); + out.write("--fluff--\r\n"); + out.flush(); + int status = conn.getResponseCode(); + System.err.println("status: " + status); + ArgumentCaptor<InputStream> inCaptor = ArgumentCaptor.forClass(InputStream.class); + verify(mockStorage).saveFile(eq("fluff"), inCaptor.capture()); + InputStream in = inCaptor.getValue(); + byte[] data = new byte[11]; + int totalRead = 0; + while (totalRead < 11) { + int read = in.read(data, totalRead, 11 - totalRead); + if (read < 0) { + fail(); + } + totalRead += read; + } + assertEquals("Hello World", new String(data)); + } + + @Test + public void testLoadFile() throws IOException { + + byte[] data = "Hello World".getBytes(); + InputStream in = new ByteArrayInputStream(data); + when(mockStorage.loadFile("fluff")).thenReturn(in); + + String endpoint = getEndpoint(); + URL url = new URL(endpoint + "/load-file"); + + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoOutput(true); + conn.setDoInput(true); + OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); + out.write("file=fluff"); + out.flush(); + in = conn.getInputStream(); + data = new byte[11]; + int totalRead = 0; + while (totalRead < 11) { + int read = in.read(data, totalRead, 11 - totalRead); + if (read < 0) { + fail(); + } + totalRead += read; + } + assertEquals("Hello World", new String(data)); + verify(mockStorage).loadFile("fluff"); + } + + @Test + public void testPurge() throws IOException { + String endpoint = getEndpoint(); + URL url = new URL(endpoint + "/purge"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoOutput(true); + conn.setRequestMethod("POST"); + int status = conn.getResponseCode(); + assertEquals(200, status); + verify(mockStorage).purge(); + } + + private void registerCategory() { + try { + String endpoint = getEndpoint(); + URL url = new URL(endpoint + "/register-category"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + String enc = "UTF-8"; + conn.setRequestProperty("Content-Encoding", enc); + conn.setDoOutput(true); + conn.setDoInput(true); + conn.setRequestMethod("POST"); + OutputStream out = conn.getOutputStream(); + Gson gson = new Gson(); + OutputStreamWriter writer = new OutputStreamWriter(out); + writer.write("name="); + writer.write(URLEncoder.encode(category.getName(), enc)); + writer.write("&category="); + writer.write(URLEncoder.encode(gson.toJson(category), enc)); + writer.flush(); + + InputStream in = conn.getInputStream(); + Reader reader = new InputStreamReader(in); + Integer id = gson.fromJson(reader, Integer.class); + categoryId = id; + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + private String getEndpoint() { + return "http://localhost:" + port + "/storage"; + } +}