Updated Storage Dispatcher to Dispatch "/a/b/.store" to the store rather than an object

Change-Id: Ief943e0375d7130436d33a350c7fc680da910a07
diff --git a/examples/boxes/android/src/boxesp2p/main.go b/examples/boxes/android/src/boxesp2p/main.go
index 23f8a2c..b9938ed 100644
--- a/examples/boxes/android/src/boxesp2p/main.go
+++ b/examples/boxes/android/src/boxesp2p/main.go
@@ -75,13 +75,12 @@
 	"veyron2"
 	"veyron2/ipc"
 	"veyron2/naming"
+	"veyron2/query"
 	"veyron2/rt"
 	"veyron2/security"
-	"veyron2/services/store"
 	"veyron2/services/watch"
 	"veyron2/storage/vstore"
 	"veyron2/storage/vstore/primitives"
-	"veyron2/query"
 	"veyron2/vom"
 )
 
@@ -103,17 +102,17 @@
 }
 
 var (
-	gs            goState
-	nativeJava    jniState
+	gs         goState
+	nativeJava jniState
 )
 
 const (
-	drawServicePort   = ":8509"
-	storeServicePort  = ":8000"
-	syncServicePort   = ":8001"
-	storePath         = "/data/data/com.boxes.android.draganddraw/files/vsync"
-	storeDatabase     = "veyron_store.db"
-	useStoreService   = true
+	drawServicePort  = ":8509"
+	storeServicePort = ":8000"
+	syncServicePort  = ":8001"
+	storePath        = "/data/data/com.boxes.android.draganddraw/files/vsync"
+	storeDatabase    = "veyron_store.db"
+	useStoreService  = true
 )
 
 func (jni *jniState) registerAddBox(env *C.JNIEnv, obj C.jobject) {
@@ -216,7 +215,7 @@
 	}
 	for {
 		box := <-gs.boxList
-  		boxes := vst.Bind("/" + box.BoxId)
+		boxes := vst.Bind("/" + box.BoxId)
 		tr = primitives.NewTransaction(ctx)
 		if _, err := boxes.Put(ctx, tr, box); err != nil {
 			panic(fmt.Errorf("Put for %s failed:%v", boxes, err))
@@ -323,15 +322,9 @@
 	auth := security.NewACLAuthorizer(acl)
 
 	// Register the services
-	if err = gs.ipc.Register(store.StoreSuffix, storage.NewStoreDispatcher(gs.store, auth)); err != nil {
+	if err = gs.ipc.Register("", storage.NewStoreDispatcher(gs.store, auth)); err != nil {
 		panic(fmt.Errorf("s.Register(store) failed:%v", err))
 	}
-	if err := gs.ipc.Register(raw.RawStoreSuffix, storage.NewRawStoreDispatcher(gs.store, auth)); err != nil {
-		panic(fmt.Errorf("s.Register(rawstore) failed:%v", err))
-	}
-	if err := gs.ipc.Register("", storage.NewObjectDispatcher(gs.store, auth)); err != nil {
-		panic(fmt.Errorf("s.Register(object) failed:%v", err))
-	}
 
 	// Create an endpoint and start listening
 	if _, err = gs.ipc.Listen("tcp", gs.myIPAddr+storeServicePort); err != nil {
diff --git a/examples/todos/test/util.go b/examples/todos/test/util.go
index 0bc3930..3d1b24c 100644
--- a/examples/todos/test/util.go
+++ b/examples/todos/test/util.go
@@ -14,7 +14,6 @@
 	"veyron2/naming"
 	"veyron2/rt"
 	"veyron2/security"
-	"veyron2/services/store"
 	"veyron2/storage"
 	"veyron2/storage/vstore"
 )
@@ -56,13 +55,9 @@
 
 	// Register the services.
 	storeDisp := server.NewStoreDispatcher(storeService, nil)
-	objectDisp := server.NewObjectDispatcher(storeService, nil)
-	if err := s.Register(store.StoreSuffix, storeDisp); err != nil {
+	if err := s.Register("", storeDisp); err != nil {
 		log.Fatal("s.Register(storeDisp) failed: ", err)
 	}
-	if err := s.Register("", objectDisp); err != nil {
-		log.Fatal("s.Register(objectDisp) failed: ", err)
-	}
 
 	// Create an endpoint and start listening.
 	ep, err := s.Listen("tcp", "127.0.0.1:0")
diff --git a/services/store/server/server.go b/services/store/server/server.go
index ae6bfd8..9cad680 100644
--- a/services/store/server/server.go
+++ b/services/store/server/server.go
@@ -4,6 +4,7 @@
 import (
 	"errors"
 	"reflect"
+	"strings"
 	"sync"
 	"time"
 
@@ -265,36 +266,29 @@
 	panic("not implemented")
 }
 
-// Store, raw store and object dispatchers.
-// Typically, the store dispatcher handles paths with ".store" prefix, the
-// raw store dispatcher handles paths with ".store.raw" prefix, and the
-// object dispatcher handles paths with "" prefix.
-// TODO(sadovsky): Revisit this scheme. Seems simpler to have one dispatcher?
-
-// NewStoreDispatcher returns a store dispatcher.
-func NewStoreDispatcher(s *Server, auth security.Authorizer) ipc.Dispatcher {
-	return ipc.SoloDispatcher(store.NewServerStore(s), auth)
-}
-
-// NewRawStoreDispatcher returns a raw store dispatcher.
-func NewRawStoreDispatcher(s *Server, auth security.Authorizer) ipc.Dispatcher {
-	return ipc.SoloDispatcher(raw.NewServerStore(s), auth)
-}
-
-type objectDispatcher struct {
+type storeDispatcher struct {
 	s    *Server
 	auth security.Authorizer
 }
 
-// NewObjectDispatcher returns an object dispatcher.
-func NewObjectDispatcher(s *Server, auth security.Authorizer) ipc.Dispatcher {
-	return &objectDispatcher{s: s, auth: auth}
+// NewStoreDispatcher returns an object dispatcher.
+func NewStoreDispatcher(s *Server, auth security.Authorizer) ipc.Dispatcher {
+	return &storeDispatcher{s: s, auth: auth}
 }
 
-func (d *objectDispatcher) Lookup(suffix string) (ipc.Invoker, security.Authorizer, error) {
-	o := d.s.lookupObject(suffix)
-	serverObject := store.NewServerObject(o)
-	return ipc.ReflectInvoker(serverObject), d.auth, nil
+func (d *storeDispatcher) Lookup(suffix string) (ipc.Invoker, security.Authorizer, error) {
+	return ipc.ReflectInvoker(d.lookupServer(suffix)), d.auth, nil
+}
+
+func (d *storeDispatcher) lookupServer(suffix string) interface{} {
+	if strings.HasSuffix(suffix, store.StoreSuffix) {
+		return store.NewServerStore(d.s)
+	} else if strings.HasSuffix(suffix, raw.RawStoreSuffix) {
+		return raw.NewServerStore(d.s)
+	} else {
+		o := d.s.lookupObject(suffix)
+		return store.NewServerObject(o)
+	}
 }
 
 func (s *Server) lookupObject(name string) *object {
diff --git a/services/store/server/server_test.go b/services/store/server/server_test.go
index fa87c83..4f26b36 100644
--- a/services/store/server/server_test.go
+++ b/services/store/server/server_test.go
@@ -6,6 +6,7 @@
 	"log"
 	"net"
 	"os"
+	"reflect"
 	"testing"
 	"time"
 
@@ -654,3 +655,36 @@
 		t.Errorf("Unexpected error: %v", err)
 	}
 }
+
+func TestStoreDispatcher(t *testing.T) {
+	storeType := reflect.PtrTo(reflect.TypeOf(store.ServerStubStore{}))
+	rawType := reflect.PtrTo(reflect.TypeOf(raw.ServerStubStore{}))
+	objectType := reflect.PtrTo(reflect.TypeOf(store.ServerStubObject{}))
+
+	tests := []struct {
+		name string
+		t    reflect.Type
+	}{
+		{store.StoreSuffix, storeType},
+		{"a/b/" + store.StoreSuffix, storeType},
+		{"a/b/c" + store.StoreSuffix, storeType},
+		{raw.RawStoreSuffix, rawType},
+		{"a/b/" + raw.RawStoreSuffix, rawType},
+		{"a/b/c" + raw.RawStoreSuffix, rawType},
+		{"", objectType},
+		{"a/b/", objectType},
+		{"a/b/c", objectType},
+	}
+
+	s, c := newServer()
+	defer c()
+
+	// TODO(bprosnitz) Switch this to use just exported methods (using signature) once signature stabilizes.
+	d := NewStoreDispatcher(s, nil).(*storeDispatcher)
+	for _, test := range tests {
+		srvr := d.lookupServer(test.name)
+		if reflect.TypeOf(srvr) != test.t {
+			t.Errorf("error looking up %s. got %T, expected %v", test.name, srvr, test.t)
+		}
+	}
+}
diff --git a/services/store/stored/main.go b/services/store/stored/main.go
index 750d278..674fdf3 100644
--- a/services/store/stored/main.go
+++ b/services/store/stored/main.go
@@ -19,11 +19,9 @@
 	"os/user"
 
 	vflag "veyron/security/flag"
-	"veyron/services/store/raw"
 	"veyron/services/store/server"
 
 	"veyron2/rt"
-	"veyron2/services/store"
 
 	_ "veyron/services/store/typeregistryhack"
 )
@@ -71,17 +69,9 @@
 
 	// Register the services.
 	storeDisp := server.NewStoreDispatcher(storeService, auth)
-	rawStoreDisp := server.NewRawStoreDispatcher(storeService, auth)
-	objectDisp := server.NewObjectDispatcher(storeService, auth)
-	if err := s.Register(store.StoreSuffix, storeDisp); err != nil {
+	if err := s.Register("", storeDisp); err != nil {
 		log.Fatal("s.Register(storeDisp) failed: ", err)
 	}
-	if err := s.Register(raw.RawStoreSuffix, rawStoreDisp); err != nil {
-		log.Fatal("s.Register(rawStoreDisp) failed: ", err)
-	}
-	if err := s.Register("", objectDisp); err != nil {
-		log.Fatal("s.Register(objectDisp) failed: ", err)
-	}
 
 	// Create an endpoint and start listening.
 	ep, err := s.Listen("tcp", *address)
diff --git a/services/store/testutil/store.go b/services/store/testutil/store.go
index 560cbdd..4b8df30 100644
--- a/services/store/testutil/store.go
+++ b/services/store/testutil/store.go
@@ -12,7 +12,6 @@
 	"veyron2/ipc"
 	"veyron2/naming"
 	"veyron2/security"
-	"veyron2/services/store"
 )
 
 // NewStore creates a new testing instance of the store server and returns
@@ -43,13 +42,9 @@
 
 	// Register the services.
 	storeDispatcher := istore.NewStoreDispatcher(storeService, nil)
-	objectDispatcher := istore.NewObjectDispatcher(storeService, nil)
-	if err := server.Register(naming.JoinAddressName(name, store.StoreSuffix), storeDispatcher); err != nil {
+	if err := server.Register(name, storeDispatcher); err != nil {
 		t.Fatalf("Register(%v) failed: %v", storeDispatcher, err)
 	}
-	if err := server.Register(name, objectDispatcher); err != nil {
-		t.Fatalf("Register(%v) failed: %v", objectDispatcher, err)
-	}
 
 	// Create an endpoint and start listening.
 	protocol, hostname := "tcp", "127.0.0.1:0"