/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.test.clustering.xsite;
import java.io.IOException;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.infinispan.Cache;
/**
* Servlet providing get/put access to Infinispan cache instance.
*
* http://127.0.0.1:8080/cache?operation=get&key=a
* http://127.0.0.1:8080/cache?operation=put&key=a;value=b
*
* where keys are Strings and Values are String representations of int.
*
* NOTE: Caches defined in the infinispan subsystem need to be started on demand.
* On demand in this case means either:
* (i) through deployment of a distributable web app which uses the cache as a session cache
* (ii) by way of @Resource(lookup=) which will cause the corresponding JNDI binding instance to be started
* and so the cache.
*
* Cache instances are started in this test case by way of a res-ref in the web.xml file in order to
* permit parametrization of the JNDI name.
*
* @author Richard Achmatowicz
*/
@WebServlet(urlPatterns = { CacheAccessServlet.SERVLET_PATH })
public class CacheAccessServlet extends HttpServlet {
private static final long serialVersionUID = 9130271954748513391L;
private static final String SERVLET_NAME = "cache";
static final String SERVLET_PATH = "/" + SERVLET_NAME;
private static final String OPERATION = "operation";
private static final String GET = "get";
private static final String PUT = "put";
private static final String KEY = "key";
private static final String VALUE = "value";
public static URI createGetURI(URL baseURL, String key) throws URISyntaxException {
return createURI(baseURL, GET, key, null);
}
public static URI createPutURI(URL baseURL, String key, String value) throws URISyntaxException {
return createURI(baseURL, PUT, key, value);
}
public static URI createURI(URL baseURL, String operation, String key, String value) throws URISyntaxException {
StringBuilder builder = new StringBuilder(SERVLET_NAME);
builder.append('?').append(OPERATION).append('=').append(operation);
builder.append('&').append(KEY).append('=').append(key);
if (value != null) {
builder.append('&').append(VALUE).append('=').append(value);
}
return baseURL.toURI().resolve(builder.toString());
}
@Resource(name="TheTargetCache")
private Cache<String, Custom> cache;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String operation = req.getParameter(OPERATION);
if (operation == null) {
throw new ServletException(String.format("No '%s' parameter specified)", OPERATION));
}
//
if (operation.equals(GET)) {
String key = req.getParameter(KEY);
validateKeyParam(operation, key);
Custom value = cache.get(key);
if (value == null) {
throw new ServletException(String.format("No value is defined for key '%s'",key));
}
resp.setIntHeader("value", value.getValue());
resp.getWriter().write("Success");
} else if (operation.equals(PUT)) {
String key = req.getParameter(KEY);
validateKeyParam(operation, key);
String value = req.getParameter(VALUE);
validateValueParam(operation, value);
int intValue = Integer.parseInt(value);
// put the new instance of Custom here to the cache
// todo: difference between putting new value and modifying existing old value
cache.put(key, new Custom(intValue));
resp.getWriter().write("Success");
} else {
throw new ServletException(String.format("Unknown operation '%s': valid operations are get/put)", operation));
}
}
private void validateKeyParam(String operation, String key) throws ServletException {
if (key == null || key.length() == 0) {
throw new ServletException(String.format("key parameter for operation %s is null or has zero length", operation));
}
}
private void validateValueParam(String operation, String value) throws ServletException {
if (value == null || value.length() == 0) {
throw new ServletException(String.format("key parameter for operation %s is null or has zero length", operation));
}
try {
Integer.parseInt(value) ;
}
catch(NumberFormatException nfe) {
throw new ServletException(String.format("value parameter for operation %s must be int", operation));
}
}
/*
* Serializable object holding an int value
*/
public static class Custom implements Serializable {
private static final long serialVersionUID = -5129400250276547619L;
private transient boolean serialized = false;
private int value;
public Custom(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
public void setValue(int value) {
this.value = value;
}
public boolean wasSerialized() {
return this.serialized;
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
this.serialized = true;
}
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
this.serialized = true;
}
}
}