changeset 222:143ca837d3b0

add bullet in board
author tatsuki
date Tue, 15 Sep 2015 02:03:04 +0900
parents 9404bf19da41
children f0cc848b9af6
files build.gradle src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/App.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/BoardMessage.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/BulletinBoard.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/CassandraBulletinBoard.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/CreateBoardMessageServlet.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/CreateBoardServlet.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/EditMessageServlet.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/EditMessageUseGetServlet.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/GetAttributeImp.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/HectorSample.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/IterableConverter.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/JungleBulletinBoard.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/ShowBoardMessageServlet.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/ShowBoardsServlet.java
diffstat 15 files changed, 984 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/build.gradle	Tue Sep 15 00:39:25 2015 +0900
+++ b/build.gradle	Tue Sep 15 02:03:04 2015 +0900
@@ -17,8 +17,18 @@
     compile "com.google.guava:guava:12.0"
     compile fileTree(dir: 'lib', include: '*.jar')
     compile "junit:junit:4.7"
+    compile group: 'org.eclipse.jetty', name: 'jetty-server', version:'9.1.1.v20140108'
+    compile group: 'org.hectorclient', name: 'hector-core', version:'1.1-2'
+    compile(group: 'org.apache.cassandra', name: 'cassandra-all', version:'1.2.1') {
+        exclude(module: 'slf4j-log4j12')
+        exclude(module: 'log4j')
+    }
+    compile group: 'com.eaio.uuid', name: 'uuid', version:'3.3'
 }
 
+
+
+
 jar {
     manifest {
         attributes 'Implementation-Title': 'Gradle Quickstart', 'Implementation-Version': version
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/App.java	Tue Sep 15 02:03:04 2015 +0900
@@ -0,0 +1,83 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.bbs;
+
+import me.prettyprint.hector.api.HConsistencyLevel;
+import org.mortbay.jetty.Connector;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.nio.SelectChannelConnector;
+import org.mortbay.jetty.servlet.ServletHandler;
+import org.mortbay.jetty.servlet.ServletHolder;
+import org.mortbay.thread.QueuedThreadPool;
+
+import javax.servlet.Servlet;
+
+
+/**
+ * Hello world!
+ *
+ */
+public class App 
+{
+    public static void main( String[] args ) throws Exception
+    {
+    	BulletinBoard cassaBBS = null;
+    	if(args.length == 0){
+    		cassaBBS = new JungleBulletinBoard();
+    	}else{
+    		HConsistencyLevel cLevel = HConsistencyLevel.QUORUM;
+    		int rep_factor = 1;
+    		int i=0;
+    		while(i<args.length) {
+    			if(args[i].equals("-all")) {
+    				cLevel = HConsistencyLevel.ALL;
+    			}else if(args[i].equals("-one")){
+    				cLevel = HConsistencyLevel.ONE;
+    			}else if(args[i].equals("-quorum")){
+    				cLevel = HConsistencyLevel.QUORUM;
+    			}else if(args[i].equals("-any")){
+    				cLevel = HConsistencyLevel.ANY;
+    			}else if(args[i].equals("-rep")){
+    				i++;
+    				rep_factor = Integer.parseInt(args[i]);
+    			}
+    			i++;
+    		}
+			System.out.println("ConsistencyLevel "+cLevel.toString());
+			System.out.println("Replication factor "+rep_factor);
+       		cassaBBS = new CassandraBulletinBoard("test-cluster","localhost:9160","cassaBBS2", cLevel, rep_factor);
+   		}
+    	
+    	String createBoardMessagePath = "/createBoardMessage";
+    	String createBoardPath = "/createBoard";
+    	String editMessagePath = "/editMessage";
+    	String showBoardMessagePath = "/showBoardMessage";
+    	
+    	Servlet createBoardMessage = new CreateBoardMessageServlet(cassaBBS);
+    	Servlet createBoard = new CreateBoardServlet(cassaBBS);
+    	Servlet editBoardMessage = new EditMessageServlet(cassaBBS);
+    	Servlet index = new ShowBoardsServlet(cassaBBS,createBoardPath,showBoardMessagePath);
+    	Servlet board = new ShowBoardMessageServlet(cassaBBS,createBoardMessagePath,editMessagePath);
+    	
+//    	Server serv = new Server(8080);
+    	Server serv = new Server();
+    	SelectChannelConnector connector = new SelectChannelConnector();
+    	connector.setPort(8080);
+    	connector.setThreadPool(new QueuedThreadPool(1000));
+    	serv.setConnectors(new Connector[] { connector });
+    	
+    	ServletHandler context = new ServletHandler();
+    	context.addServletWithMapping(new ServletHolder(createBoardMessage),createBoardMessagePath);
+    	context.addServletWithMapping(new ServletHolder(createBoard),createBoardPath);
+    	context.addServletWithMapping(new ServletHolder(editBoardMessage),editMessagePath);
+    	context.addServletWithMapping(new ServletHolder(index),"/");
+    	context.addServletWithMapping(new ServletHolder(board),showBoardMessagePath);
+    	/* 
+    	 * For write benchmark 
+    	 */
+    	String editMessageUseGetPath = "/editMessageUseGet";
+    	Servlet editMessageUseGet = new EditMessageUseGetServlet(cassaBBS);
+    	context.addServletWithMapping(new ServletHolder(editMessageUseGet), editMessageUseGetPath);
+    	
+    	serv.addHandler(context);
+    	serv.start();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/BoardMessage.java	Tue Sep 15 02:03:04 2015 +0900
@@ -0,0 +1,8 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.bbs;
+
+public interface BoardMessage
+{
+	public String getUUID();
+	public String getAuthor();
+	public String getMessage();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/BulletinBoard.java	Tue Sep 15 02:03:04 2015 +0900
@@ -0,0 +1,11 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.bbs;
+
+public interface BulletinBoard
+{
+	public Iterable<String> getBoards();
+	public void createBoards(String _name, String _author, String _initMessage, String _editKey);
+	public void createBoardMessage(String _board, String _author, String _message, String _editKey);
+	public void editMessage(String _board, String _uuid, String _author, String _message, String _editKey);
+	public String sanitize(String str);
+  GetAttributeImp getAttribute(String _bname, String _nodeNum, String revisionStr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/CassandraBulletinBoard.java	Tue Sep 15 02:03:04 2015 +0900
@@ -0,0 +1,219 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.bbs;
+
+import me.prettyprint.cassandra.model.ConfigurableConsistencyLevel;
+import me.prettyprint.cassandra.serializers.StringSerializer;
+import me.prettyprint.cassandra.serializers.UUIDSerializer;
+import me.prettyprint.cassandra.service.template.SuperCfResult;
+import me.prettyprint.cassandra.service.template.SuperCfUpdater;
+import me.prettyprint.cassandra.service.template.ThriftSuperCfTemplate;
+import me.prettyprint.cassandra.utils.TimeUUIDUtils;
+import me.prettyprint.hector.api.Cluster;
+import me.prettyprint.hector.api.HConsistencyLevel;
+import me.prettyprint.hector.api.Keyspace;
+import me.prettyprint.hector.api.beans.HSuperColumn;
+import me.prettyprint.hector.api.beans.OrderedSuperRows;
+import me.prettyprint.hector.api.beans.SuperRow;
+import me.prettyprint.hector.api.beans.SuperSlice;
+import me.prettyprint.hector.api.ddl.ColumnFamilyDefinition;
+import me.prettyprint.hector.api.ddl.ColumnType;
+import me.prettyprint.hector.api.ddl.ComparatorType;
+import me.prettyprint.hector.api.ddl.KeyspaceDefinition;
+import me.prettyprint.hector.api.factory.HFactory;
+import me.prettyprint.hector.api.query.QueryResult;
+import me.prettyprint.hector.api.query.RangeSuperSlicesQuery;
+import me.prettyprint.hector.api.query.SuperSliceQuery;
+import org.apache.cassandra.locator.SimpleStrategy;
+
+import java.util.*;
+
+public class CassandraBulletinBoard implements BulletinBoard
+{
+	private final String address;
+	private final String clusterName;
+	private final Cluster cluster;
+	private final String keyspace;
+	private final ConfigurableConsistencyLevel configurableConsistencyLevel = new ConfigurableConsistencyLevel(); 
+	
+	private static final String COLUMN_FAMILY_BOARD = "boards";
+	private final int REP_FACTOR;
+	
+	public CassandraBulletinBoard(String _clusterName,String _address,String _keyspaceName, HConsistencyLevel cLevel,int rep_factor )
+	{
+		address = _address;
+		clusterName = _clusterName;
+		keyspace = _keyspaceName;
+		cluster = HFactory.getOrCreateCluster(clusterName,address);
+		Map<String, HConsistencyLevel> clmap = new HashMap<String, HConsistencyLevel>();
+		clmap.put(COLUMN_FAMILY_BOARD, cLevel);
+		configurableConsistencyLevel.setReadCfConsistencyLevels(clmap);
+		configurableConsistencyLevel.setWriteCfConsistencyLevels(clmap);
+		REP_FACTOR = rep_factor;
+		initialize();
+	}
+	
+	public CassandraBulletinBoard(String _clusterName,String _address,String _keyspaceName, HConsistencyLevel cLevel)
+	{
+		this(_clusterName, _address, _keyspaceName, cLevel, 1);		
+	}
+	
+	
+	
+	private void initialize()
+	{
+		if(cluster.describeKeyspace(keyspace) == null){
+			KeyspaceDefinition keyspaceDefinition = HFactory.createKeyspaceDefinition(keyspace,
+					SimpleStrategy.class.getName(),REP_FACTOR,Collections.<ColumnFamilyDefinition> emptyList());
+			cluster.addKeyspace(keyspaceDefinition,false);
+			ColumnFamilyDefinition columnFamilyDefinition = HFactory.createColumnFamilyDefinition(keyspace,COLUMN_FAMILY_BOARD,ComparatorType.UUIDTYPE);
+			columnFamilyDefinition.setColumnType(ColumnType.SUPER);
+			cluster.addColumnFamily(columnFamilyDefinition);
+		}
+	}
+	
+	public Iterable<String> getBoards()
+	{
+		Keyspace ksp = HFactory.createKeyspace(keyspace, cluster, configurableConsistencyLevel);
+		RangeSuperSlicesQuery<String,UUID,String,String> query = HFactory.createRangeSuperSlicesQuery(ksp,StringSerializer.get(),
+				UUIDSerializer.get(),StringSerializer.get(),StringSerializer.get());
+		query.setColumnFamily(COLUMN_FAMILY_BOARD).setKeys(null,null).setRange(null,null,false,0);
+		
+		QueryResult<OrderedSuperRows<String,UUID,String,String>> result = query.execute();
+		OrderedSuperRows<String,UUID,String,String> rows = result.get();
+		List<SuperRow<String,UUID,String,String>> list = rows.getList();
+		
+		IterableConverter.Converter<String,SuperRow<String,UUID,String,String>> converter
+			= new IterableConverter.Converter<String, SuperRow<String,UUID,String,String>>(){
+				public String conv(SuperRow<String, UUID, String, String> _b) {
+					return _b.getKey();
+				}
+			};
+		
+		return new IterableConverter<String,SuperRow<String,UUID,String,String>>(list,converter);
+	}
+	
+	private static final String COLUMN_MESSAGE_AUTHOR = "author";
+	private static final String COLUMN_MESSAGE_BODY = "message";
+	private static final String COLUMN_MESSAGE_EDIT_KEY = "edit";
+
+	public void createBoardMessage(UUID _time,String _name,String _author,String _message,String _editKey)
+	{
+		Keyspace ksp = HFactory.createKeyspace(keyspace, cluster, configurableConsistencyLevel);
+		ThriftSuperCfTemplate<String,UUID,String> template = 
+				new ThriftSuperCfTemplate<String,UUID,String>(ksp,COLUMN_FAMILY_BOARD,StringSerializer.get(),
+						UUIDSerializer.get(),StringSerializer.get());
+		
+		SuperCfUpdater<String,UUID,String> updater = template.createUpdater(_name,_time);
+		updater.setString(COLUMN_MESSAGE_AUTHOR,_author);
+		updater.setString(COLUMN_MESSAGE_BODY,_message);
+		updater.setString(COLUMN_MESSAGE_EDIT_KEY,_editKey);
+		
+		template.update(updater);
+	}
+	
+	public void createBoards(String _name,String _author,String _initMessage,String _editKey)
+	{
+		UUID time = TimeUUIDUtils.getTimeUUID(0);
+		createBoardMessage(time,_name,_author,_initMessage,_editKey);
+	}
+
+	public Iterable<BoardMessage> getMessages(String _boardName)
+	{
+		Keyspace ksp = HFactory.createKeyspace(keyspace, cluster, configurableConsistencyLevel);
+		SuperSliceQuery<String, UUID, String, String> query = HFactory.createSuperSliceQuery(ksp, StringSerializer.get(), UUIDSerializer.get(), StringSerializer.get(), StringSerializer.get());
+		
+		UUID start = TimeUUIDUtils.getTimeUUID(0);
+		query.setKey(_boardName).setColumnFamily(COLUMN_FAMILY_BOARD).setRange(start,null,false,100);
+		
+		QueryResult<SuperSlice<UUID, String, String>> result = query.execute();
+		SuperSlice<UUID,String,String> ss = result.get();
+		List<HSuperColumn<UUID,String,String>> list = ss.getSuperColumns();
+		
+		IterableConverter.Converter<BoardMessage,HSuperColumn<UUID,String,String>> converter =
+				new IterableConverter.Converter<BoardMessage,HSuperColumn<UUID,String,String>>(){
+					public BoardMessage conv(HSuperColumn<UUID, String, String> _b){
+						UUID uuid = _b.getName();
+						String author = _b.getSubColumnByName(COLUMN_MESSAGE_AUTHOR).getValue();
+						String message = _b.getSubColumnByName(COLUMN_MESSAGE_BODY).getValue();
+						BoardMessageImpl bm = new BoardMessageImpl(author,message,uuid.toString());
+						return bm;
+					}
+				};
+		
+		
+		return new IterableConverter<BoardMessage,HSuperColumn<UUID,String,String>>(list,converter);
+	}
+	
+	private static class BoardMessageImpl implements BoardMessage
+	{
+		private final String author;
+		private final String message;
+		private final String uuid;
+		
+		public BoardMessageImpl(String _author,String _message,String _uuid)
+		{
+			author = _author;
+			message = _message;
+			uuid = _uuid;
+		}
+
+		public String getAuthor()
+		{
+			return author;
+		}
+
+		public String getMessage()
+		{
+			return message;
+		}
+
+		public String getUUID()
+		{
+			return uuid;
+		}
+	}
+
+	public void createBoardMessage(String _board, String _author, String _message,String _editKey)
+	{
+		UUID time = TimeUUIDUtils.getUniqueTimeUUIDinMillis();
+		createBoardMessage(time,_board,_author,_message,_editKey);
+	}
+
+	public void editMessage(String _board,String _uuid,String _author,String _message,String _editKey)
+	{
+		Keyspace ksp = HFactory.createKeyspace(keyspace, cluster, configurableConsistencyLevel);
+		UUID time = UUID.fromString(_uuid);
+		ThriftSuperCfTemplate<String,UUID,String> template = 
+				new ThriftSuperCfTemplate<String,UUID,String>(ksp,COLUMN_FAMILY_BOARD,StringSerializer.get(),
+						UUIDSerializer.get(),StringSerializer.get());
+		
+		SuperCfResult<String,UUID,String> result = template.querySuperColumn(_board,time);
+		String editKey = result.getString(COLUMN_MESSAGE_EDIT_KEY);
+		if(!editKey.equals(editKey)){
+			return;
+		}
+		
+		SuperCfUpdater<String, UUID, String> updater = template.createUpdater(_board,time);
+		updater.setString(COLUMN_MESSAGE_AUTHOR,_author);
+		updater.setString(COLUMN_MESSAGE_BODY,_message);
+		updater.setString(COLUMN_MESSAGE_EDIT_KEY,_editKey);
+		
+		template.update(updater);
+	}
+	
+	public String sanitize( String str ) {
+	    if(str==null) {
+	        return str;
+	    }
+	    str = str.replaceAll("&" , "&amp;" );
+	    str = str.replaceAll("<" , "&lt;"  );
+	    str = str.replaceAll(">" , "&gt;"  );
+	    str = str.replaceAll("\"", "&quot;");
+	    str = str.replaceAll("'" , "&#39;" );
+	    return str;
+	 }
+
+  public GetAttributeImp getAttribute(String _bname, String _nodeNum, String revisionStr) {
+    return null; // 未実装 使うときに実装する
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/CreateBoardMessageServlet.java	Tue Sep 15 02:03:04 2015 +0900
@@ -0,0 +1,39 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.bbs;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.PrintWriter;
+
+public class CreateBoardMessageServlet extends HttpServlet
+{
+	private final BulletinBoard bbs;
+	private static final String PARAM_BOARD_NAME = "bname";
+	private static final String PARAM_BOARD_AUTHOR = "author";
+	private static final String PARAM_BOARD_MESSAGE= "msg";
+	private static final String PARAM_BOARD_EDITKEY = "key";
+	
+	private static final long serialVersionUID = 1L;
+	
+	public CreateBoardMessageServlet(BulletinBoard _bbs)
+	{
+		bbs = _bbs;
+	}
+	
+	@Override
+	public void doPost(HttpServletRequest _req,HttpServletResponse _res)
+	{
+		String boardName = _req.getParameter(PARAM_BOARD_NAME);
+		String author = _req.getParameter(PARAM_BOARD_AUTHOR);
+		String msg = _req.getParameter(PARAM_BOARD_MESSAGE);
+		String key = _req.getParameter(PARAM_BOARD_EDITKEY);
+		
+		try{
+			bbs.createBoardMessage(boardName,author,msg,key);
+			PrintWriter pw = _res.getWriter();
+			pw.write("successfully written");
+		}catch(Exception _e){
+			_res.setStatus(500);
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/CreateBoardServlet.java	Tue Sep 15 02:03:04 2015 +0900
@@ -0,0 +1,40 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.bbs;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.PrintWriter;
+
+public class CreateBoardServlet extends HttpServlet
+{
+	private final BulletinBoard bbs;
+	private static final String PARAM_BOARD_NAME = "bname";
+	private static final String PARAM_BOARD_AUTHOR = "author";
+	private static final String PARAM_BOARD_INITMESSAGE= "msg";
+	private static final String PARAM_BOARD_EDITKEY = "key";
+	
+	private static final long serialVersionUID = 1L;
+	
+	public CreateBoardServlet(BulletinBoard _bbs)
+	{
+		bbs = _bbs;
+	}
+
+	public void doPost(HttpServletRequest _req,HttpServletResponse _res)
+	{
+		String boardName = StringEscapeUtils.unescapeHtml(_req.getParameter(PARAM_BOARD_NAME));
+		String author = StringEscapeUtils.unescapeHtml(_req.getParameter(PARAM_BOARD_AUTHOR));
+		String msg = StringEscapeUtils.unescapeHtml(_req.getParameter(PARAM_BOARD_INITMESSAGE));
+		String key = StringEscapeUtils.unescapeHtml(_req.getParameter(PARAM_BOARD_EDITKEY));
+		
+		try{
+			bbs.createBoards(boardName,author,msg,key);
+			PrintWriter pw = _res.getWriter();
+			pw.write("successfully written");
+		}catch(Exception _e){
+			_res.setStatus(500);
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/EditMessageServlet.java	Tue Sep 15 02:03:04 2015 +0900
@@ -0,0 +1,63 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.bbs;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.PrintWriter;
+
+public class EditMessageServlet extends HttpServlet
+{
+	private final BulletinBoard bbs;
+	private static final String PARAM_BOARD_NAME = "bname";
+	private static final String PARAM_BOARD_MSGID = "uuid";
+	private static final String PARAM_BOARD_AUTHOR = "author";
+	private static final String PARAM_BOARD_MESSAGE= "msg";
+	private static final String PARAM_BOARD_EDITKEY = "key";
+	
+	private static final long serialVersionUID = 1L;
+	
+	public EditMessageServlet(BulletinBoard _bbs)
+	{
+		bbs = _bbs;
+	}
+	
+	public void doGet(HttpServletRequest _req,HttpServletResponse _res)
+	{
+		String bname = _req.getParameter(PARAM_BOARD_NAME);
+		String uuid = _req.getParameter(PARAM_BOARD_MSGID);
+		System.out.println("write");
+		
+		try{
+			PrintWriter pw = _res.getWriter();
+			pw.write("<html><body><h1>edit message</h1>");
+			pw.write("<form method='POST'\n");
+			pw.write("<p>Author : <input type='text' name='author'/>" +
+					"<input type='hidden' name='key' value='"+uuid+"'/>" +
+					"<input type='hidden' name='bname' value='"+bname+"'</p>\n");
+			pw.write("<p>Message<br/> <input type='textarea' name='msg'/> </p>\n");
+			pw.write("<p><input type='submit' value='submit'/></p>\n");
+			pw.write("</body></html>");
+			pw.flush();
+		}catch(Exception _e){
+			_res.setStatus(500);
+		}
+	}
+
+	public void doPost(HttpServletRequest _req,HttpServletResponse _res)
+	{
+		String boardName = _req.getParameter(PARAM_BOARD_NAME);
+		String author = _req.getParameter(PARAM_BOARD_AUTHOR);
+		String msg = _req.getParameter(PARAM_BOARD_MESSAGE);
+		String key = _req.getParameter(PARAM_BOARD_EDITKEY);
+		String uuid = _req.getParameter(PARAM_BOARD_MSGID);
+		
+		try{
+			bbs.editMessage(boardName, uuid, author, msg, key);
+			PrintWriter pw = _res.getWriter();
+			pw.write("successfully written");
+			pw.flush();
+		}catch(Exception _e){
+			_res.setStatus(500);
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/EditMessageUseGetServlet.java	Tue Sep 15 02:03:04 2015 +0900
@@ -0,0 +1,40 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.bbs;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.PrintWriter;
+
+public class EditMessageUseGetServlet extends HttpServlet{
+		private final BulletinBoard bbs;
+		private static final String PARAM_BOARD_NAME = "bname";
+		private static final String PARAM_BOARD_MSGID = "uuid";
+		private static final String PARAM_BOARD_AUTHOR = "author";
+		private static final String PARAM_BOARD_MESSAGE= "msg";
+		private static final String PARAM_BOARD_EDITKEY = "key";
+		
+		private static final long serialVersionUID = 1L;
+		
+		public EditMessageUseGetServlet(BulletinBoard _bbs)
+		{
+			bbs = _bbs;
+		}
+		
+		public void doGet(HttpServletRequest _req,HttpServletResponse _res)
+		{
+			String boardName = _req.getParameter(PARAM_BOARD_NAME);
+			String author = _req.getParameter(PARAM_BOARD_AUTHOR);
+			String msg = _req.getParameter(PARAM_BOARD_MESSAGE);
+			String key = _req.getParameter(PARAM_BOARD_EDITKEY);
+			String uuid = _req.getParameter(PARAM_BOARD_MSGID);
+			
+			try{
+				bbs.editMessage(boardName, uuid, author, msg, key);
+				PrintWriter pw = _res.getWriter();
+				pw.write("successfully written");
+				pw.flush();
+			}catch(Exception _e){
+				_res.setStatus(500);
+			}
+		}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/GetAttributeImp.java	Tue Sep 15 02:03:04 2015 +0900
@@ -0,0 +1,23 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.bbs;
+
+
+import jp.ac.u_ryukyu.ie.cr.jungle.store.impl.TreeNode;
+
+import java.util.Iterator;
+
+public class GetAttributeImp {
+  private final TreeNode node;
+
+  public GetAttributeImp(TreeNode _node) {
+    node = _node;
+  }
+
+  public String getMessage(String key) {
+    return node.getAttributes().getString(key);
+  }
+  
+  public Iterator<String> getKeys() {
+    return node.getAttributes().getKeys();
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/HectorSample.java	Tue Sep 15 02:03:04 2015 +0900
@@ -0,0 +1,62 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.bbs;
+
+import me.prettyprint.cassandra.serializers.StringSerializer;
+import me.prettyprint.cassandra.serializers.UUIDSerializer;
+import me.prettyprint.cassandra.service.template.SuperCfUpdater;
+import me.prettyprint.cassandra.service.template.ThriftSuperCfTemplate;
+import me.prettyprint.cassandra.utils.TimeUUIDUtils;
+import me.prettyprint.hector.api.*;
+import me.prettyprint.hector.api.beans.*;
+import me.prettyprint.hector.api.factory.HFactory;
+import me.prettyprint.hector.api.query.QueryResult;
+import me.prettyprint.hector.api.query.RangeSuperSlicesQuery;
+import me.prettyprint.hector.api.query.SuperSliceQuery;
+
+import java.util.List;
+import java.util.UUID;
+
+public class HectorSample
+{
+	public static void main(String _args[])
+	{
+		Cluster myCluster = HFactory.getOrCreateCluster("test-cluster","localhost:9160");
+
+		Keyspace ksp = HFactory.createKeyspace("cassaBBS",myCluster);
+
+		ThriftSuperCfTemplate<String,UUID,String> template =
+				new ThriftSuperCfTemplate<String,UUID,String>(ksp,"boards",StringSerializer.get(),
+						UUIDSerializer.get(),StringSerializer.get());
+		UUID time = TimeUUIDUtils.getUniqueTimeUUIDinMillis();
+		SuperCfUpdater<String,UUID,String> updater = template.createUpdater("board1",TimeUUIDUtils.getTimeUUID(0));
+		updater.setString("name","peter");
+		updater.setString("message",time.toString());
+
+		template.update(updater);
+
+		UUID start = TimeUUIDUtils.getTimeUUID(0);
+
+		SuperSliceQuery<String, UUID, String, String> sq = HFactory.createSuperSliceQuery(ksp, StringSerializer.get(), UUIDSerializer.get(), StringSerializer.get(), StringSerializer.get());
+		sq.setKey("board1").setColumnFamily("ccc").setRange(start,null,false,100);
+
+		QueryResult<SuperSlice<UUID,String,String>> results = sq.execute();
+
+		SuperSlice<UUID,String,String> ss = results.get();
+		List<HSuperColumn<UUID,String,String>> list = ss.getSuperColumns();
+		for(HSuperColumn<UUID,String,String> sc : list){
+			HColumn<String,String> sub = sc.getSubColumnByName("name");
+			System.out.println(sub.getValue());
+			sub = sc.getSubColumnByName("message");
+			System.out.println(sub.getValue());
+		}
+
+		RangeSuperSlicesQuery<String,UUID,String,String> rsq = HFactory.createRangeSuperSlicesQuery(ksp,StringSerializer.get(),
+				UUIDSerializer.get(),StringSerializer.get(),StringSerializer.get());
+		rsq.setKeys(null,null).setRange(null,null,false,0).setColumnFamily("ccc");
+
+		QueryResult<OrderedSuperRows<String,UUID,String,String>> rsqResult = rsq.execute();
+		OrderedSuperRows<String, UUID, String, String> rows = rsqResult.get();
+		for(SuperRow<String, UUID, String, String>  row : rows.getList()){
+			System.out.println(row.getKey());
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/IterableConverter.java	Tue Sep 15 02:03:04 2015 +0900
@@ -0,0 +1,52 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.bbs;
+
+import java.util.Iterator;
+
+public class IterableConverter<A,B> implements Iterable<A>
+{
+	private final Iterable<B> iterable;
+	private final Converter<A,B> converter;
+	
+	public IterableConverter(Iterable<B> _iterable,Converter<A,B> _converter)
+	{
+		iterable = _iterable;
+		converter = _converter;
+	}
+	
+	public Iterator<A> iterator()
+	{
+		return new IteratorConverter<A,B>(iterable.iterator(),converter);
+	}
+	
+	private static final class IteratorConverter<A,B> implements Iterator<A>
+	{
+		private final Iterator<B> iterator;
+		private final Converter<A,B> converter;
+		
+		public IteratorConverter(Iterator<B> _iterator,Converter<A,B> _converter)
+		{
+			iterator = _iterator;
+			converter = _converter;
+		}
+		
+		public boolean hasNext()
+		{
+			return iterator.hasNext();
+		}
+
+		public A next()
+		{
+			return converter.conv(iterator.next());
+		}
+
+		public void remove()
+		{
+			iterator.remove();
+		}
+	}
+
+	public static interface Converter<A,B>
+	{
+		public A conv(B _b);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/JungleBulletinBoard.java	Tue Sep 15 02:03:04 2015 +0900
@@ -0,0 +1,224 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.bbs;
+
+
+import jp.ac.u_ryukyu.ie.cr.jungle.DefaultJungle;
+import jp.ac.u_ryukyu.ie.cr.jungle.Jungle;
+import jp.ac.u_ryukyu.ie.cr.jungle.JungleTree;
+import jp.ac.u_ryukyu.ie.cr.jungle.JungleTreeEditor;
+import jp.ac.u_ryukyu.ie.cr.jungle.core.Children;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.impl.DefaultNodePath;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.impl.DefaultTreeEditor;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.impl.TreeNode;
+import jp.ac.u_ryukyu.ie.cr.jungle.traverser.DefaultEvaluator;
+import jp.ac.u_ryukyu.ie.cr.jungle.traverser.DefaultTraverser;
+import jp.ac.u_ryukyu.ie.cr.jungle.traverser.Traversal;
+import jp.ac.u_ryukyu.ie.cr.jungle.util.Either;
+import jp.ac.u_ryukyu.ie.cr.jungle.util.Error;
+import junit.framework.Assert;
+
+import java.nio.ByteBuffer;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class JungleBulletinBoard implements
+		BulletinBoard {
+	private final Jungle jungle;
+
+	public JungleBulletinBoard() {
+		jungle = new DefaultJungle(null, "hoge", new DefaultTreeEditor(
+				new DefaultTraverser()));
+		jungle.createNewTree("boards");
+	}
+
+	public Iterable<String> getBoards() {
+		JungleTree tree = jungle.getTreeByName("boards");
+		TreeNode node = tree.getRootNode();
+		Children chs = node.getChildren();
+
+		IterableConverter.Converter<String, TreeNode> converter = new IterableConverter.Converter<String, TreeNode>() {
+			public String conv(TreeNode _b) {
+				ByteBuffer e = _b.getAttributes().get("name");
+				return new String(e.array());
+			}
+		};
+
+		return new IterableConverter<String, TreeNode>(chs, converter);
+	}
+
+	public void createBoards(final String _name, final String _author,
+			final String _initMessage, final String _editKey) {
+		if (null == jungle.createNewTree(_name)) {
+			throw new IllegalStateException();
+		}
+		JungleTree tree = jungle.getTreeByName("boards");
+		JungleTreeEditor editor = tree.getTreeEditor();
+		DefaultNodePath root = new DefaultNodePath();
+		Either<Error, JungleTreeEditor> either = editor.addNewChildAt(root, 0);
+		if (either.isA()) {
+			throw new IllegalStateException();
+		}
+		editor = either.b();
+
+		either = editor.putAttribute(root.add(0), "name", ByteBuffer.wrap(_name.getBytes()));
+		if (either.isA()) {
+			throw new IllegalStateException();
+		}
+		editor = either.b();
+		Either<Error, JungleTreeEditor> result = editor.success();
+		if (result.isA()) {
+			throw new IllegalStateException();
+		}
+
+		tree = jungle.getTreeByName(_name);
+		editor = tree.getTreeEditor();
+		editor = editor.putAttribute(root,"author", ByteBuffer.wrap(_author.getBytes())).b();
+		editor = editor.putAttribute(root,"key", ByteBuffer.wrap(_editKey.getBytes())).b();
+		either = editor.putAttribute(root,"mes", ByteBuffer.wrap(_initMessage.getBytes()));
+		
+		if (either.isA()) {
+			throw new IllegalStateException();
+		}
+		editor = either.b();
+		editor.success();
+	}
+
+	public void createBoardMessage(final String _board, final String _author,
+			final String _message, final String _editKey) {
+		JungleTree tree = jungle.getTreeByName(_board);
+		if (tree == null) {
+			throw new IllegalStateException();
+		}
+
+		JungleTreeEditor editor;
+		do {
+			TreeNode node = tree.getRootNode();
+			int size = node.getChildren().size();
+			DefaultNodePath path = new DefaultNodePath();
+
+			editor = tree.getTreeEditor();
+			Either<Error, JungleTreeEditor> either = editor.addNewChildAt(path,
+					size);
+			if (either.isA()) {
+				throw new IllegalStateException();
+			}
+			editor = either.b();
+
+
+
+			editor = editor.putAttribute(path.add(size),"author", ByteBuffer.wrap(_author.getBytes())).b();
+			editor = editor.putAttribute(path.add(size),"key", ByteBuffer.wrap(_editKey.getBytes())).b();
+			either = editor.putAttribute(path.add(size),"mes", ByteBuffer.wrap(_message.getBytes()));
+			
+			if (either.isA()) {
+				throw new IllegalStateException();
+			}
+			editor = either.b();
+		}while (editor.success().isA());
+	}
+
+	public void editMessage(String _board, String _uuid, final String _author,
+			final String _message, final String _editKey) {
+		JungleTreeEditor editor = null;
+		do {
+			DefaultNodePath path = new DefaultNodePath();
+			path = path.add(Integer.parseInt(_uuid));
+
+			JungleTree tree = jungle.getTreeByName(_board);
+			editor = tree.getTreeEditor();
+
+			editor = editor.putAttribute(path,"author", ByteBuffer.wrap(_author.getBytes())).b();
+			editor = editor.putAttribute(path,"key", ByteBuffer.wrap(_editKey.getBytes())).b();
+			Either<Error, JungleTreeEditor> either = editor.putAttribute(path,"mes", ByteBuffer.wrap(_message.getBytes()));
+			
+			if (either.isA()) {
+				throw new IllegalStateException();
+			}
+			editor = either.b();
+		}while (editor.success().isA());
+	}
+
+	public Iterable<BoardMessage> getMessages(String _boardName) {
+		JungleTree tree = jungle.getTreeByName(_boardName);
+		TreeNode node = tree.getRootNode();
+		Children chs = node.getChildren();
+
+		final AtomicInteger counter = new AtomicInteger(0);
+		IterableConverter.Converter<BoardMessage, TreeNode> converter = new IterableConverter.Converter<BoardMessage, TreeNode>() {
+			public BoardMessage conv(TreeNode _b) {
+				String uuid = Integer.toString(counter.get());
+				String author = new String(_b.getAttributes().get("author")
+						.array());
+				String message = new String(_b.getAttributes().get("mes")
+						.array());
+				counter.incrementAndGet();
+				return new BoardMessageImpl(author, message, uuid);
+			}
+		};
+
+		return new IterableConverter<BoardMessage, TreeNode>(chs, converter);
+	}
+
+	private static class BoardMessageImpl implements BoardMessage {
+		private final String author;
+		private final String message;
+		private final String uuid;
+
+		public BoardMessageImpl(String _author, String _message, String _uuid) {
+			author = _author;
+			message = _message;
+			uuid = _uuid;
+		}
+
+		public String getAuthor() {
+			return author;
+		}
+
+		public String getMessage() {
+			return message;
+		}
+
+		public String getUUID() {
+			return uuid;
+		}
+	}
+
+	public String sanitize(String str) {
+		if (str == null) {
+			return str;
+		}
+		str = str.replaceAll("&", "&amp;");
+		str = str.replaceAll("<", "&lt;");
+		str = str.replaceAll(">", "&gt;");
+		str = str.replaceAll("\"", "&quot;");
+		str = str.replaceAll("'", "&#39;");
+		return str;
+	}
+
+  public GetAttributeImp getAttribute(String _bname, String _nodeNum, String revisionStr) {
+
+    DefaultNodePath path = new DefaultNodePath();
+    try {
+      for (int count = 0; _nodeNum.substring(count, count + 1) != null; count++) {
+        if (!_nodeNum.substring(count, count + 1).equals("/"))
+          path = path.add(Integer.parseInt(_nodeNum.substring(count, count + 1)));
+      }
+    } catch (Exception _e) {
+    }
+    JungleTree tree = jungle.getTreeByName(_bname);
+    System.out.println(tree.revision());
+    Long revision = Long.parseLong(revisionStr);
+    JungleTree oldTree = tree.getOldTree(revision).b();
+    System.out.println(oldTree.revision());
+    TreeNode node = oldTree.getRootNode();
+
+    DefaultTraverser traverser = new DefaultTraverser();
+    DefaultEvaluator evaluator = new DefaultEvaluator(path);
+    Either<Error, Traversal> ret = traverser.traverse(node, evaluator);
+    if (ret.isA()) {
+      Assert.fail();
+    }
+
+    Traversal traversal = ret.b();
+    TreeNode target = traversal.destination();
+    return new GetAttributeImp(target);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/ShowBoardMessageServlet.java	Tue Sep 15 02:03:04 2015 +0900
@@ -0,0 +1,55 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.bbs;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.PrintWriter;
+import java.util.Iterator;
+
+public class ShowBoardMessageServlet extends HttpServlet {
+    /**
+     *
+     */
+    private static final long serialVersionUID = 1L;
+    private final BulletinBoard bbs;
+    private final String createBoardMessagePath;
+
+    private static final String PARAM_BOARD_NAME = "bname";
+
+    public ShowBoardMessageServlet(BulletinBoard _bbs, String _createBoardMessagePath, String _editMessagePath) {
+        bbs = _bbs;
+        createBoardMessagePath = _createBoardMessagePath;
+    }
+
+    public void doGet(HttpServletRequest _req, HttpServletResponse _res) {
+        String bname = _req.getParameter(PARAM_BOARD_NAME);
+
+        try {
+            printBoard(bname, _res.getWriter());
+        } catch (Exception _e) {
+            _res.setStatus(500);
+        }
+
+    }
+
+    private void printBoard(String _bname, PrintWriter _pw) throws Exception {
+        _pw.write("<html><body>\n");
+        _pw.write("<h1>" + bbs.sanitize(_bname) + "</h1>\n");
+
+        _pw.write("<form action='" + createBoardMessagePath + "' method='POST'\n");
+        _pw.write("<p>Author : <input type='text' name='author'/> <input type='hidden' name='bname' value='" + _bname + "'/> EditKey : <input type='text' name='key'/></p>\n");
+        _pw.write("<p>Message<br/> <input type='textarea' name='msg'/> </p>\n");
+        _pw.write("<p><input type='submit' value='submit'/></p>\n");
+        GetAttributeImp attribute = bbs.getAttribute(_bname, "[-1]", "1");
+        Iterator<String> keys = attribute.getKeys();
+
+        do  {
+            String key = keys.next();
+            String mesage = attribute.getMessage(key);
+            _pw.write("<p>" + key + " = " + mesage + "</p>\n");
+        }while(keys.hasNext());
+
+        _pw.write("</body></html>");
+        _pw.flush();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/bbs/ShowBoardsServlet.java	Tue Sep 15 02:03:04 2015 +0900
@@ -0,0 +1,55 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.bbs;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.PrintWriter;
+
+public class ShowBoardsServlet extends HttpServlet
+{
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	private final BulletinBoard bbs;
+	private final String createBoardPath;
+	private final String showBoardMessagePath;
+
+	public ShowBoardsServlet(BulletinBoard _bbs, String _createBoardPath,String _showBoardMessagePath)
+	{
+		bbs = _bbs;
+		createBoardPath = _createBoardPath;
+		showBoardMessagePath = _showBoardMessagePath;
+	}
+	
+	public void doGet(HttpServletRequest _req,HttpServletResponse _res)
+	{
+		try{
+			_res.setCharacterEncoding("UTF-8");
+			printBoard(_res.getWriter());
+		}catch(Exception _e){
+			_res.setStatus(500);
+		}
+		
+	}
+	
+	private void printBoard(PrintWriter _pw) throws Exception
+	{
+		_pw.write("<html><body>\n");
+		_pw.write("<h1>BBS</h1>\n");
+		_pw.write("<form action='"+createBoardPath+"' method='POST'\n");
+		_pw.write("<p>Create new board.</p>");
+		_pw.write("<p>BoardName : <input type='text' name='bname'/></p>\n");
+		_pw.write("<p>Author : <input type='text' name='author'/> EditKey : <input type='text' name='key'/></p>\n");
+		_pw.write("<p>Message<br/> <input type='textarea' name='msg'/> </p>\n");
+		_pw.write("<p><input type='submit' value='submit'/></p><hr/>\n");
+		
+		_pw.write("<h2>list of boards</h2>");
+		for(String board : bbs.getBoards()){
+			_pw.write("<p><a href='"+showBoardMessagePath+"?bname=" + bbs.sanitize(board) + "'>"+ bbs.sanitize(board) + "</a></p>");
+		}
+		
+		_pw.write("</body></html>");
+		_pw.flush();
+	}
+}