OSDN Git Service

初期インポート master
authoru6k.yu1 <u6k.yu1@gmail.com>
Sat, 30 Oct 2010 12:30:13 +0000 (21:30 +0900)
committeru6k.yu1 <u6k.yu1@gmail.com>
Sat, 30 Oct 2010 12:30:13 +0000 (21:30 +0900)
66 files changed:
doc/\89æ\96Ê\91J\88Ú\90}.odg [new file with mode: 0644]
doc/\8ed\97l\8f\91.odt [new file with mode: 0644]
money-notebook/.classpath [new file with mode: 0644]
money-notebook/.project [new file with mode: 0644]
money-notebook/.settings/com.google.appengine.eclipse.core.prefs [new file with mode: 0644]
money-notebook/.settings/com.google.gwt.eclipse.core.prefs [new file with mode: 0644]
money-notebook/src/META-INF/jdoconfig.xml [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/AccountDao.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/AccountEntity.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/EntityStateEnum.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/MoneyDiaryDao.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/MoneyDiaryEntity.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/PMF.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/TempAccountDao.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/TempAccountEntity.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/UserDao.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/UserEntity.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/gwt/Index.gwt.xml [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/gwt/client/IndexEntryPoint.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/gwt/client/IndexService.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/gwt/client/IndexServiceAsync.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/gwt/server/IndexServiceImpl.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/logic/LoginLogic.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/CollectionUtil.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/DateUtil.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/HashUtil.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/LockUtil.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/MoneyDiaryForm.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/MoneyDiaryItem.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/filter/LoginCheckFilter.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/filter/RequestLogFilter.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/admin/MaintenanceServlet.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/admin/UserDataServlet.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/admin/UserIdListServlet.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mail/CreateMoneyForm.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mail/CreateMoneyServlet.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mail/RegistMailServlet.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/IndexServlet.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/LoginServlet.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/RegistFinishServlet.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/RegistServlet.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/user/DiaryServlet.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/user/TopServlet.java [new file with mode: 0644]
money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/user/TutorialServlet.java [new file with mode: 0644]
money-notebook/src/log4j.properties [new file with mode: 0644]
money-notebook/src_test/jp/gr/java_conf/u6k/money_notebook/test/util/DateUtilTest.java [new file with mode: 0644]
money-notebook/war/WEB-INF/.gitignore [new file with mode: 0644]
money-notebook/war/WEB-INF/appengine-web.xml [new file with mode: 0644]
money-notebook/war/WEB-INF/datastore-indexes.xml [new file with mode: 0644]
money-notebook/war/WEB-INF/lib/.gitignore [new file with mode: 0644]
money-notebook/war/WEB-INF/lib/jsonic-1.2.0.jar [new file with mode: 0644]
money-notebook/war/WEB-INF/lib/urlrewrite-3.2.0.jar [new file with mode: 0644]
money-notebook/war/WEB-INF/logging.properties [new file with mode: 0644]
money-notebook/war/WEB-INF/page/mobile/index.jsp [new file with mode: 0644]
money-notebook/war/WEB-INF/page/mobile/login.jsp [new file with mode: 0644]
money-notebook/war/WEB-INF/page/mobile/regist.jsp [new file with mode: 0644]
money-notebook/war/WEB-INF/page/mobile/regist_finish.jsp [new file with mode: 0644]
money-notebook/war/WEB-INF/page/mobile/user/diary_daily.jsp [new file with mode: 0644]
money-notebook/war/WEB-INF/page/mobile/user/diary_detail.jsp [new file with mode: 0644]
money-notebook/war/WEB-INF/page/mobile/user/diary_monthly.jsp [new file with mode: 0644]
money-notebook/war/WEB-INF/page/mobile/user/diary_weekly.jsp [new file with mode: 0644]
money-notebook/war/WEB-INF/page/mobile/user/top.jsp [new file with mode: 0644]
money-notebook/war/WEB-INF/urlrewrite.xml [new file with mode: 0644]
money-notebook/war/WEB-INF/web.xml [new file with mode: 0644]
money-notebook/war/admin/data/user.jsp [new file with mode: 0644]
money-notebook/war/index.html [new file with mode: 0644]

diff --git a/doc/\89æ\96Ê\91J\88Ú\90}.odg b/doc/\89æ\96Ê\91J\88Ú\90}.odg
new file mode 100644 (file)
index 0000000..6f42036
Binary files /dev/null and b/doc/‰æ–Ê‘JˆÚ}.odg differ
diff --git a/doc/\8ed\97l\8f\91.odt b/doc/\8ed\97l\8f\91.odt
new file mode 100644 (file)
index 0000000..fe05c4d
Binary files /dev/null and b/doc/Žd—l‘.odt differ
diff --git a/money-notebook/.classpath b/money-notebook/.classpath
new file mode 100644 (file)
index 0000000..f271f4b
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="src" path="src"/>\r
+       <classpathentry kind="src" path="src_test"/>\r
+       <classpathentry kind="con" path="com.google.appengine.eclipse.core.GAE_CONTAINER"/>\r
+       <classpathentry kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>\r
+       <classpathentry kind="lib" path="war/WEB-INF/lib/jsonic-1.2.0.jar"/>\r
+       <classpathentry kind="output" path="war/WEB-INF/classes"/>\r
+</classpath>\r
diff --git a/money-notebook/.project b/money-notebook/.project
new file mode 100644 (file)
index 0000000..bc5c40f
--- /dev/null
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>money-notebook</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.eclipse.jdt.core.javabuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>com.google.gwt.eclipse.core.gwtProjectValidator</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>com.google.appengine.eclipse.core.enhancerbuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>com.google.appengine.eclipse.core.projectValidator</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.jdt.core.javanature</nature>\r
+               <nature>com.google.appengine.eclipse.core.gaeNature</nature>\r
+               <nature>com.google.gwt.eclipse.core.gwtNature</nature>\r
+               <nature>com.google.gdt.eclipse.core.webAppNature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/money-notebook/.settings/com.google.appengine.eclipse.core.prefs b/money-notebook/.settings/com.google.appengine.eclipse.core.prefs
new file mode 100644 (file)
index 0000000..6289375
--- /dev/null
@@ -0,0 +1,3 @@
+#Sun Jun 13 22:46:57 JST 2010\r
+eclipse.preferences.version=1\r
+filesCopiedToWebInfLib=appengine-api-1.0-sdk-1.3.0.jar|appengine-api-labs-1.3.0.jar|datanucleus-appengine-1.0.4.1.final.jar|datanucleus-core-1.1.5.jar|datanucleus-jpa-1.1.5.jar|geronimo-jpa_3.0_spec-1.1.1.jar|geronimo-jta_1.1_spec-1.1.1.jar|jdo2-api-2.3-eb.jar\r
diff --git a/money-notebook/.settings/com.google.gwt.eclipse.core.prefs b/money-notebook/.settings/com.google.gwt.eclipse.core.prefs
new file mode 100644 (file)
index 0000000..2093679
--- /dev/null
@@ -0,0 +1,3 @@
+#Sun Jun 13 22:46:56 JST 2010\r
+eclipse.preferences.version=1\r
+filesCopiedToWebInfLib=gwt-servlet.jar\r
diff --git a/money-notebook/src/META-INF/jdoconfig.xml b/money-notebook/src/META-INF/jdoconfig.xml
new file mode 100644 (file)
index 0000000..5f56aa1
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<jdoconfig xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig"
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig">
+
+   <persistence-manager-factory name="transactions-optional">
+       <property name="javax.jdo.PersistenceManagerFactoryClass"
+           value="org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory"/>
+       <property name="javax.jdo.option.ConnectionURL" value="appengine"/>
+       <property name="javax.jdo.option.NontransactionalRead" value="true"/>
+       <property name="javax.jdo.option.NontransactionalWrite" value="true"/>
+       <property name="javax.jdo.option.RetainValues" value="true"/>
+       <property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true"/>
+   </persistence-manager-factory>
+</jdoconfig>
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/AccountDao.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/AccountDao.java
new file mode 100644 (file)
index 0000000..18b3b9d
--- /dev/null
@@ -0,0 +1,71 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.dao;\r
+\r
+import java.io.IOException;\r
+import java.util.List;\r
+\r
+import javax.jdo.PersistenceManager;\r
+import javax.jdo.Query;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.util.CollectionUtil;\r
+import jp.gr.java_conf.u6k.money_notebook.util.HashUtil;\r
+\r
+public class AccountDao {\r
+\r
+    private PersistenceManager pm;\r
+\r
+    public AccountDao(PersistenceManager pm) {\r
+        this.pm = pm;\r
+    }\r
+\r
+    public AccountEntity findByEmail(String email) {\r
+        Query query = this.pm.newQuery(AccountEntity.class);\r
+        query.setFilter("email == emailParam && entityState == entityStateParam");\r
+        query.declareParameters("String emailParam, EntityStateEnum entityStateParam");\r
+\r
+        List<AccountEntity> accountList = CollectionUtil.castToList(query.execute(email, EntityStateEnum.LIVES));\r
+\r
+        if (accountList.size() == 1) {\r
+            return accountList.get(0);\r
+        } else {\r
+            return null;\r
+        }\r
+    }\r
+\r
+    public AccountEntity findByEmailAndPassword(String email, String password) throws IOException {\r
+        Query query = this.pm.newQuery(AccountEntity.class);\r
+        query.setFilter("email == emailParam && entityState == entityStateParam");\r
+        query.declareParameters("String emailParam, EntityStateEnum entityStateParam");\r
+\r
+        List<AccountEntity> accountList = CollectionUtil.castToList(query.execute(email, EntityStateEnum.LIVES));\r
+\r
+        if (accountList.size() == 0) {\r
+            return null;\r
+        }\r
+\r
+        AccountEntity account = accountList.get(0);\r
+\r
+        String passwordHash = HashUtil.digest(account.getPasswordHashAlgorithm(), password);\r
+\r
+        if (!account.getPassword().equals(passwordHash)) {\r
+            return null;\r
+        }\r
+\r
+        return account;\r
+    }\r
+\r
+    public AccountEntity findByUser(UserEntity user) {\r
+        Query query = this.pm.newQuery(AccountEntity.class);\r
+        query.setFilter("user == userParam && entityState == entityStateParam");\r
+        query.declareParameters("UserEntity userParam, EntityStateEnum entityStateParam");\r
+\r
+        List<AccountEntity> accountList = CollectionUtil.castToList(query.execute(user, EntityStateEnum.LIVES));\r
+\r
+        if (accountList.size() == 0) {\r
+            return null;\r
+        } else {\r
+            return accountList.get(0);\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/AccountEntity.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/AccountEntity.java
new file mode 100644 (file)
index 0000000..cfd02b6
--- /dev/null
@@ -0,0 +1,106 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.dao;\r
+\r
+import java.util.Date;\r
+\r
+import javax.jdo.annotations.IdGeneratorStrategy;\r
+import javax.jdo.annotations.IdentityType;\r
+import javax.jdo.annotations.PersistenceCapable;\r
+import javax.jdo.annotations.Persistent;\r
+import javax.jdo.annotations.PrimaryKey;\r
+\r
+import com.google.appengine.api.datastore.Key;\r
+\r
+@PersistenceCapable(identityType = IdentityType.APPLICATION)\r
+public class AccountEntity {\r
+\r
+    @PrimaryKey\r
+    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)\r
+    private Key key;\r
+\r
+    @Persistent(mappedBy = "account")\r
+    private UserEntity user;\r
+\r
+    @Persistent\r
+    private String email;\r
+\r
+    @Persistent\r
+    private String password;\r
+\r
+    @Persistent\r
+    private String passwordHashAlgorithm = "SHA-512";\r
+\r
+    @Persistent\r
+    private Date updateDatetime;\r
+\r
+    @Persistent\r
+    private EntityStateEnum entityState = EntityStateEnum.LIVES;\r
+\r
+    public AccountEntity backup() {\r
+        AccountEntity account = new AccountEntity();\r
+        account.email = this.email;\r
+        account.password = this.password;\r
+        account.passwordHashAlgorithm = this.passwordHashAlgorithm;\r
+        account.updateDatetime = this.updateDatetime;\r
+        account.entityState = this.entityState;\r
+\r
+        return account;\r
+    }\r
+\r
+    public Key getKey() {\r
+        return this.key;\r
+    }\r
+\r
+    public void setKey(Key key) {\r
+        this.key = key;\r
+    }\r
+\r
+    public UserEntity getUser() {\r
+        return this.user;\r
+    }\r
+\r
+    public void setUser(UserEntity user) {\r
+        this.user = user;\r
+    }\r
+\r
+    public String getEmail() {\r
+        return this.email;\r
+    }\r
+\r
+    public void setEmail(String email) {\r
+        this.email = email;\r
+    }\r
+\r
+    public String getPassword() {\r
+        return this.password;\r
+    }\r
+\r
+    public void setPassword(String password) {\r
+        this.password = password;\r
+    }\r
+\r
+    public String getPasswordHashAlgorithm() {\r
+        return this.passwordHashAlgorithm;\r
+    }\r
+\r
+    public void setPasswordHashAlgorithm(String passwordHashAlgorithm) {\r
+        this.passwordHashAlgorithm = passwordHashAlgorithm;\r
+    }\r
+\r
+    public Date getUpdateDatetime() {\r
+        return this.updateDatetime;\r
+    }\r
+\r
+    public void setUpdateDatetime(Date updateDatetime) {\r
+        this.updateDatetime = updateDatetime;\r
+    }\r
+\r
+    public EntityStateEnum getEntityState() {\r
+        return this.entityState;\r
+    }\r
+\r
+    public void setEntityState(EntityStateEnum entityState) {\r
+        this.entityState = entityState;\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/EntityStateEnum.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/EntityStateEnum.java
new file mode 100644 (file)
index 0000000..ebbb2f4
--- /dev/null
@@ -0,0 +1,8 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.dao;\r
+\r
+public enum EntityStateEnum {\r
+\r
+    LIVES, DELETED,\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/MoneyDiaryDao.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/MoneyDiaryDao.java
new file mode 100644 (file)
index 0000000..db3e605
--- /dev/null
@@ -0,0 +1,51 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.dao;\r
+\r
+import java.util.Collections;\r
+import java.util.Comparator;\r
+import java.util.Date;\r
+import java.util.List;\r
+\r
+import javax.jdo.PersistenceManager;\r
+import javax.jdo.Query;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.util.CollectionUtil;\r
+\r
+public class MoneyDiaryDao {\r
+\r
+    private PersistenceManager pm;\r
+\r
+    public MoneyDiaryDao(PersistenceManager pm) {\r
+        this.pm = pm;\r
+    }\r
+\r
+    public List<MoneyDiaryEntity> findByUser(UserEntity user, EntityStateEnum entityState) {\r
+        Query query = this.pm.newQuery(MoneyDiaryEntity.class);\r
+        query.setFilter("user == userParam && entityState == entityStateParam");\r
+        query.declareParameters("UserEntity userParam, EntityStateEnum entityStateParam");\r
+\r
+        List<MoneyDiaryEntity> moneyDiaryList = CollectionUtil.castToList(query.execute(user, entityState));\r
+\r
+        return moneyDiaryList;\r
+    }\r
+\r
+    public List<MoneyDiaryEntity> findByUserAndDiaryDateBetween(UserEntity user, Date diaryDateBegin, Date diaryDateEnd) {\r
+        Query query = this.pm.newQuery(MoneyDiaryEntity.class);\r
+        query.setFilter("user == userParam && diaryDate >= diaryDateBeginParam && diaryDate < diaryDateEndParam && entityState == entityStateParam");\r
+        query.declareParameters("UserEntity userParam, java.util.Date diaryDateBeginParam, java.util.Date diaryDateEndParam, EntityStateEnum entityStateParam");\r
+\r
+        List<MoneyDiaryEntity> moneyDiaryList = CollectionUtil.castToList(query.executeWithArray(user, diaryDateBegin, diaryDateEnd, EntityStateEnum.LIVES));\r
+\r
+        Collections.sort(moneyDiaryList, new Comparator<MoneyDiaryEntity>() {\r
+\r
+            @Override\r
+            public int compare(MoneyDiaryEntity o1, MoneyDiaryEntity o2) {\r
+                return -1 * o1.getDiaryDate().compareTo(o2.getDiaryDate());\r
+            }\r
+\r
+        });\r
+\r
+        return moneyDiaryList;\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/MoneyDiaryEntity.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/MoneyDiaryEntity.java
new file mode 100644 (file)
index 0000000..f045848
--- /dev/null
@@ -0,0 +1,106 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.dao;\r
+\r
+import java.util.Date;\r
+\r
+import javax.jdo.annotations.IdGeneratorStrategy;\r
+import javax.jdo.annotations.IdentityType;\r
+import javax.jdo.annotations.PersistenceCapable;\r
+import javax.jdo.annotations.Persistent;\r
+import javax.jdo.annotations.PrimaryKey;\r
+\r
+import com.google.appengine.api.datastore.Key;\r
+\r
+@PersistenceCapable(identityType = IdentityType.APPLICATION)\r
+public class MoneyDiaryEntity {\r
+\r
+    @PrimaryKey\r
+    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)\r
+    private Key key;\r
+\r
+    @Persistent\r
+    private UserEntity user;\r
+\r
+    @Persistent\r
+    private Date diaryDate;\r
+\r
+    @Persistent\r
+    private String text;\r
+\r
+    @Persistent\r
+    private long money;\r
+\r
+    @Persistent\r
+    private Date updateDatetime;\r
+\r
+    @Persistent\r
+    private EntityStateEnum entityState = EntityStateEnum.LIVES;\r
+\r
+    public MoneyDiaryEntity backup() {\r
+        MoneyDiaryEntity moneyDiary = new MoneyDiaryEntity();\r
+        moneyDiary.diaryDate = (Date) this.diaryDate.clone();\r
+        moneyDiary.text = this.text;\r
+        moneyDiary.money = this.money;\r
+        moneyDiary.updateDatetime = this.updateDatetime;\r
+        moneyDiary.entityState = this.entityState;\r
+\r
+        return moneyDiary;\r
+    }\r
+\r
+    public Key getKey() {\r
+        return this.key;\r
+    }\r
+\r
+    public void setKey(Key key) {\r
+        this.key = key;\r
+    }\r
+\r
+    public UserEntity getUser() {\r
+        return this.user;\r
+    }\r
+\r
+    public void setUser(UserEntity user) {\r
+        this.user = user;\r
+    }\r
+\r
+    public Date getDiaryDate() {\r
+        return this.diaryDate;\r
+    }\r
+\r
+    public void setDiaryDate(Date diaryDate) {\r
+        this.diaryDate = diaryDate;\r
+    }\r
+\r
+    public String getText() {\r
+        return this.text;\r
+    }\r
+\r
+    public void setText(String text) {\r
+        this.text = text;\r
+    }\r
+\r
+    public long getMoney() {\r
+        return this.money;\r
+    }\r
+\r
+    public void setMoney(long money) {\r
+        this.money = money;\r
+    }\r
+\r
+    public Date getUpdateDatetime() {\r
+        return this.updateDatetime;\r
+    }\r
+\r
+    public void setUpdateDatetime(Date updateDatetime) {\r
+        this.updateDatetime = updateDatetime;\r
+    }\r
+\r
+    public EntityStateEnum getEntityState() {\r
+        return this.entityState;\r
+    }\r
+\r
+    public void setEntityState(EntityStateEnum entityState) {\r
+        this.entityState = entityState;\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/PMF.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/PMF.java
new file mode 100644 (file)
index 0000000..88c77b8
--- /dev/null
@@ -0,0 +1,18 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.dao;\r
+\r
+import javax.jdo.JDOHelper;\r
+import javax.jdo.PersistenceManagerFactory;\r
+\r
+public class PMF {\r
+\r
+    private static final PersistenceManagerFactory PMF_INSTANCE = JDOHelper.getPersistenceManagerFactory("transactions-optional");\r
+\r
+    private PMF() {\r
+    }\r
+\r
+    public static PersistenceManagerFactory get() {\r
+        return PMF.PMF_INSTANCE;\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/TempAccountDao.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/TempAccountDao.java
new file mode 100644 (file)
index 0000000..c2df9c5
--- /dev/null
@@ -0,0 +1,32 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.dao;\r
+\r
+import java.util.List;\r
+\r
+import javax.jdo.PersistenceManager;\r
+import javax.jdo.Query;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.util.CollectionUtil;\r
+\r
+public class TempAccountDao {\r
+\r
+    private PersistenceManager pm;\r
+\r
+    public TempAccountDao(PersistenceManager pm) {\r
+        this.pm = pm;\r
+    }\r
+\r
+    public TempAccountEntity findByUser(UserEntity user) {\r
+        Query query = this.pm.newQuery(TempAccountEntity.class);\r
+        query.setFilter("user == userParam && entityState == entityStateParam");\r
+        query.declareParameters("UserEntity userParam, EntityStateEnum entityStateParam");\r
+        List<TempAccountEntity> tempAccountList = CollectionUtil.castToList(query.execute(user, EntityStateEnum.LIVES));\r
+\r
+        if (tempAccountList.size() > 0) {\r
+            return tempAccountList.get(0);\r
+        } else {\r
+            return null;\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/TempAccountEntity.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/TempAccountEntity.java
new file mode 100644 (file)
index 0000000..6882b0f
--- /dev/null
@@ -0,0 +1,82 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.dao;\r
+\r
+import java.util.Date;\r
+\r
+import javax.jdo.annotations.IdGeneratorStrategy;\r
+import javax.jdo.annotations.IdentityType;\r
+import javax.jdo.annotations.PersistenceCapable;\r
+import javax.jdo.annotations.Persistent;\r
+import javax.jdo.annotations.PrimaryKey;\r
+\r
+import com.google.appengine.api.datastore.Key;\r
+\r
+@PersistenceCapable(identityType = IdentityType.APPLICATION)\r
+public class TempAccountEntity {\r
+\r
+    @PrimaryKey\r
+    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)\r
+    private Key key;\r
+\r
+    @Persistent(mappedBy = "tempAccount")\r
+    private UserEntity user;\r
+\r
+    @Persistent\r
+    private String email;\r
+\r
+    @Persistent\r
+    private Date updateDatetime;\r
+\r
+    @Persistent\r
+    private EntityStateEnum entityState = EntityStateEnum.LIVES;\r
+\r
+    public TempAccountEntity backup() {\r
+        TempAccountEntity tempAccount = new TempAccountEntity();\r
+        tempAccount.email = this.email;\r
+        tempAccount.updateDatetime = this.updateDatetime;\r
+        tempAccount.entityState = this.entityState;\r
+\r
+        return tempAccount;\r
+    }\r
+\r
+    public Key getKey() {\r
+        return this.key;\r
+    }\r
+\r
+    public void setKey(Key key) {\r
+        this.key = key;\r
+    }\r
+\r
+    public UserEntity getUser() {\r
+        return this.user;\r
+    }\r
+\r
+    public void setUser(UserEntity user) {\r
+        this.user = user;\r
+    }\r
+\r
+    public String getEmail() {\r
+        return this.email;\r
+    }\r
+\r
+    public void setEmail(String email) {\r
+        this.email = email;\r
+    }\r
+\r
+    public Date getUpdateDatetime() {\r
+        return this.updateDatetime;\r
+    }\r
+\r
+    public void setUpdateDatetime(Date updateDatetime) {\r
+        this.updateDatetime = updateDatetime;\r
+    }\r
+\r
+    public EntityStateEnum getEntityState() {\r
+        return this.entityState;\r
+    }\r
+\r
+    public void setEntityState(EntityStateEnum entityState) {\r
+        this.entityState = entityState;\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/UserDao.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/UserDao.java
new file mode 100644 (file)
index 0000000..256853b
--- /dev/null
@@ -0,0 +1,54 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.dao;\r
+\r
+import java.util.List;\r
+\r
+import javax.jdo.PersistenceManager;\r
+import javax.jdo.Query;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.util.CollectionUtil;\r
+\r
+public class UserDao {\r
+\r
+    private PersistenceManager pm;\r
+\r
+    public UserDao(PersistenceManager pm) {\r
+        this.pm = pm;\r
+    }\r
+\r
+    public List<UserEntity> findAll() {\r
+        Query query = this.pm.newQuery(UserEntity.class);\r
+        query.setFilter("entityState == entityStateParam");\r
+        query.declareParameters("EntityStateEnum entityStateParam");\r
+        List<UserEntity> userList = CollectionUtil.castToList(query.execute(EntityStateEnum.LIVES));\r
+\r
+        return userList;\r
+    }\r
+\r
+    public UserEntity findById(long id) {\r
+        Query query = this.pm.newQuery(UserEntity.class);\r
+        query.setFilter("key == keyParam && entityState == entityStateParam");\r
+        query.declareParameters("long keyParam, EntityStateEnum entityStateParam");\r
+        List<UserEntity> userList = CollectionUtil.castToList(query.execute(id, EntityStateEnum.LIVES));\r
+\r
+        if (userList.size() > 0) {\r
+            return userList.get(0);\r
+        } else {\r
+            return null;\r
+        }\r
+    }\r
+\r
+    public UserEntity findByAccount(AccountEntity account) {\r
+        Query query = this.pm.newQuery(UserEntity.class);\r
+        query.setFilter("account == accountParam && entityState == entityStateParam");\r
+        query.declareParameters("AccountEntity accountParam, EntityStateEnum entityStateParam");\r
+        List<UserEntity> userList = CollectionUtil.castToList(query.execute(account, EntityStateEnum.LIVES));\r
+\r
+        if (userList.size() > 0) {\r
+            return userList.get(0);\r
+        } else {\r
+            return null;\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/UserEntity.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/dao/UserEntity.java
new file mode 100644 (file)
index 0000000..65e1a9f
--- /dev/null
@@ -0,0 +1,111 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.dao;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Date;\r
+import java.util.List;\r
+\r
+import javax.jdo.annotations.IdGeneratorStrategy;\r
+import javax.jdo.annotations.IdentityType;\r
+import javax.jdo.annotations.PersistenceCapable;\r
+import javax.jdo.annotations.Persistent;\r
+import javax.jdo.annotations.PrimaryKey;\r
+\r
+import com.google.appengine.api.datastore.Key;\r
+\r
+@PersistenceCapable(identityType = IdentityType.APPLICATION)\r
+public class UserEntity {\r
+\r
+    @PrimaryKey\r
+    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)\r
+    private Key key;\r
+\r
+    @Persistent\r
+    private AccountEntity account;\r
+\r
+    @Persistent\r
+    private TempAccountEntity tempAccount;\r
+\r
+    @Persistent(mappedBy = "user")\r
+    private List<MoneyDiaryEntity> moneyDiaryList = new ArrayList<MoneyDiaryEntity>();\r
+\r
+    @Persistent\r
+    private Date updateDatetime;\r
+\r
+    @Persistent\r
+    private EntityStateEnum entityState = EntityStateEnum.LIVES;\r
+\r
+    public UserEntity backup() {\r
+        UserEntity user = new UserEntity();\r
+        if (this.account != null) {\r
+            user.account = this.account.backup();\r
+        } else {\r
+            user.account = null;\r
+        }\r
+        if (this.tempAccount != null) {\r
+            user.tempAccount = this.tempAccount.backup();\r
+        } else {\r
+            user.tempAccount = null;\r
+        }\r
+        if (this.moneyDiaryList != null) {\r
+            for (MoneyDiaryEntity moneyDiary : this.moneyDiaryList) {\r
+                user.moneyDiaryList.add(moneyDiary.backup());\r
+            }\r
+        } else {\r
+            user.moneyDiaryList = null;\r
+        }\r
+        user.updateDatetime = this.updateDatetime;\r
+        user.entityState = this.entityState;\r
+\r
+        return user;\r
+    }\r
+\r
+    public Key getKey() {\r
+        return this.key;\r
+    }\r
+\r
+    public void setKey(Key key) {\r
+        this.key = key;\r
+    }\r
+\r
+    public AccountEntity getAccount() {\r
+        return this.account;\r
+    }\r
+\r
+    public void setAccount(AccountEntity account) {\r
+        this.account = account;\r
+    }\r
+\r
+    public TempAccountEntity getTempAccount() {\r
+        return this.tempAccount;\r
+    }\r
+\r
+    public void setTempAccount(TempAccountEntity tempAccount) {\r
+        this.tempAccount = tempAccount;\r
+    }\r
+\r
+    public List<MoneyDiaryEntity> getMoneyDiaryList() {\r
+        return this.moneyDiaryList;\r
+    }\r
+\r
+    public void setMoneyDiaryList(List<MoneyDiaryEntity> moneyDiaryList) {\r
+        this.moneyDiaryList = moneyDiaryList;\r
+    }\r
+\r
+    public Date getUpdateDatetime() {\r
+        return this.updateDatetime;\r
+    }\r
+\r
+    public void setUpdateDatetime(Date updateDatetime) {\r
+        this.updateDatetime = updateDatetime;\r
+    }\r
+\r
+    public EntityStateEnum getEntityState() {\r
+        return this.entityState;\r
+    }\r
+\r
+    public void setEntityState(EntityStateEnum entityState) {\r
+        this.entityState = entityState;\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/gwt/Index.gwt.xml b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/gwt/Index.gwt.xml
new file mode 100644 (file)
index 0000000..bc68a0e
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<module\r
+    rename-to="index">\r
+\r
+    <inherits\r
+        name='com.google.gwt.user.User' />\r
+    <inherits\r
+        name="com.google.gwt.user.theme.standard.Standard" />\r
+    <entry-point\r
+        class="jp.gr.java_conf.u6k.money_notebook.gwt.client.IndexEntryPoint" />\r
+    <source\r
+        path="client" />\r
+\r
+</module>\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/gwt/client/IndexEntryPoint.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/gwt/client/IndexEntryPoint.java
new file mode 100644 (file)
index 0000000..035c468
--- /dev/null
@@ -0,0 +1,44 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.gwt.client;\r
+\r
+import com.google.gwt.core.client.EntryPoint;\r
+import com.google.gwt.core.client.GWT;\r
+import com.google.gwt.event.dom.client.ClickEvent;\r
+import com.google.gwt.event.dom.client.ClickHandler;\r
+import com.google.gwt.user.client.Window;\r
+import com.google.gwt.user.client.rpc.AsyncCallback;\r
+import com.google.gwt.user.client.ui.Button;\r
+import com.google.gwt.user.client.ui.RootPanel;\r
+\r
+public class IndexEntryPoint implements EntryPoint {\r
+\r
+    private final IndexServiceAsync indexService = GWT.create(IndexService.class);\r
+\r
+    @Override\r
+    public void onModuleLoad() {\r
+        Button sendButton = new Button("Now time.");\r
+        sendButton.addClickHandler(new ClickHandler() {\r
+\r
+            @Override\r
+            public void onClick(ClickEvent event) {\r
+                IndexEntryPoint.this.indexService.send(new AsyncCallback<String>() {\r
+\r
+                    @Override\r
+                    public void onSuccess(String result) {\r
+                        Window.alert(result);\r
+                    }\r
+\r
+                    @Override\r
+                    public void onFailure(Throwable caught) {\r
+                        Window.alert("error");\r
+                    }\r
+\r
+                });\r
+            }\r
+\r
+        });\r
+\r
+        RootPanel.get("content").add(sendButton);\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/gwt/client/IndexService.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/gwt/client/IndexService.java
new file mode 100644 (file)
index 0000000..294a14d
--- /dev/null
@@ -0,0 +1,12 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.gwt.client;\r
+\r
+import com.google.gwt.user.client.rpc.RemoteService;\r
+import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;\r
+\r
+@RemoteServiceRelativePath("index")\r
+public interface IndexService extends RemoteService {\r
+\r
+    String send();\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/gwt/client/IndexServiceAsync.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/gwt/client/IndexServiceAsync.java
new file mode 100644 (file)
index 0000000..5410172
--- /dev/null
@@ -0,0 +1,10 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.gwt.client;\r
+\r
+import com.google.gwt.user.client.rpc.AsyncCallback;\r
+\r
+public interface IndexServiceAsync {\r
+\r
+    void send(AsyncCallback<String> callback);\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/gwt/server/IndexServiceImpl.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/gwt/server/IndexServiceImpl.java
new file mode 100644 (file)
index 0000000..2410709
--- /dev/null
@@ -0,0 +1,21 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.gwt.server;\r
+\r
+import java.util.Date;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.gwt.client.IndexService;\r
+\r
+import com.google.gwt.user.server.rpc.RemoteServiceServlet;\r
+\r
+@SuppressWarnings("serial")\r
+public class IndexServiceImpl extends RemoteServiceServlet implements IndexService {\r
+\r
+    @Override\r
+    public String send() {\r
+        Date now = new Date();\r
+        String message = now.toString();\r
+\r
+        return message;\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/logic/LoginLogic.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/logic/LoginLogic.java
new file mode 100644 (file)
index 0000000..6501bb5
--- /dev/null
@@ -0,0 +1,149 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.logic;\r
+\r
+import java.io.IOException;\r
+\r
+import javax.jdo.PersistenceManager;\r
+import javax.servlet.http.Cookie;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+import javax.servlet.http.HttpSession;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.dao.AccountDao;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.AccountEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.PMF;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.UserDao;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.UserEntity;\r
+\r
+public class LoginLogic {\r
+\r
+    private HttpServletRequest req;\r
+\r
+    private HttpServletResponse resp;\r
+\r
+    private HttpSession session;\r
+\r
+    public LoginLogic(HttpServletRequest req, HttpServletResponse resp) {\r
+        if (req == null) {\r
+            throw new IllegalArgumentException("req == null");\r
+        }\r
+        if (resp == null) {\r
+            throw new IllegalArgumentException("resp == null");\r
+        }\r
+\r
+        this.req = req;\r
+        this.resp = resp;\r
+        this.session = req.getSession();\r
+    }\r
+\r
+    public boolean isLogined() {\r
+        if (this.session.getAttribute("id") == null) {\r
+            return false;\r
+        }\r
+\r
+        if (!(this.session.getAttribute("id") instanceof Long)) {\r
+            return false;\r
+        }\r
+\r
+        long id = (Long) this.session.getAttribute("id");\r
+\r
+        PersistenceManager pm = PMF.get().getPersistenceManager();\r
+        try {\r
+            UserDao userDao = new UserDao(pm);\r
+            UserEntity user = userDao.findById(id);\r
+\r
+            if (user == null) {\r
+                return false;\r
+            }\r
+        } finally {\r
+            pm.close();\r
+        }\r
+\r
+        return true;\r
+    }\r
+\r
+    public boolean autoLogin() {\r
+        Long id = null;\r
+\r
+        if (this.req.getCookies() != null) {\r
+            for (Cookie cookie : this.req.getCookies()) {\r
+                if ("l".equals(cookie.getName())) {\r
+                    String l = cookie.getValue();\r
+                    try {\r
+                        id = Long.parseLong(l);\r
+                        break;\r
+                    } catch (NumberFormatException e) {\r
+                    }\r
+                }\r
+            }\r
+        }\r
+\r
+        if (id == null) {\r
+            return false;\r
+        }\r
+\r
+        PersistenceManager pm = PMF.get().getPersistenceManager();\r
+        try {\r
+            UserDao userDao = new UserDao(pm);\r
+            UserEntity user = userDao.findById(id);\r
+\r
+            if (user == null) {\r
+                return false;\r
+            }\r
+\r
+            this.session.setAttribute("id", user.getKey().getId());\r
+\r
+            System.err.println("Account is null: " + (user.getAccount() == null)); // TODO\r
+        } finally {\r
+            pm.close();\r
+        }\r
+\r
+        return true;\r
+    }\r
+\r
+    public void updateLoginCookie() {\r
+        if (!this.isLogined()) {\r
+            return;\r
+        }\r
+\r
+        long id = this.getLoginId();\r
+\r
+        Cookie cookie = new Cookie("l", Long.toString(id));\r
+        cookie.setMaxAge(60 * 60 * 24 * 7);\r
+        cookie.setPath("/");\r
+\r
+        this.resp.addCookie(cookie);\r
+    }\r
+\r
+    public boolean login(String email, String password) throws IOException {\r
+        PersistenceManager pm = PMF.get().getPersistenceManager();\r
+        try {\r
+            AccountDao accountDao = new AccountDao(pm);\r
+            AccountEntity account = accountDao.findByEmailAndPassword(email, password);\r
+\r
+            if (account == null) {\r
+                return false;\r
+            }\r
+\r
+            UserDao userDao = new UserDao(pm);\r
+            UserEntity user = userDao.findByAccount(account);\r
+\r
+            if (user == null) {\r
+                return false;\r
+            }\r
+\r
+            this.session.setAttribute("id", user.getKey().getId());\r
+        } finally {\r
+            pm.close();\r
+        }\r
+\r
+        return true;\r
+    }\r
+\r
+    public long getLoginId() {\r
+        long id = (Long) this.session.getAttribute("id");\r
+\r
+        return id;\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/CollectionUtil.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/CollectionUtil.java
new file mode 100644 (file)
index 0000000..a66fd41
--- /dev/null
@@ -0,0 +1,13 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.util;\r
+\r
+import java.util.List;\r
+\r
+public class CollectionUtil {\r
+\r
+    @SuppressWarnings("unchecked")\r
+    public static <T> List<T> castToList(Object obj) {\r
+        return (List<T>) obj;\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/DateUtil.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/DateUtil.java
new file mode 100644 (file)
index 0000000..5807fb1
--- /dev/null
@@ -0,0 +1,70 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.util;\r
+\r
+import java.util.Calendar;\r
+import java.util.Date;\r
+import java.util.TimeZone;\r
+\r
+public final class DateUtil {\r
+\r
+    private DateUtil() {\r
+        throw new UnsupportedOperationException();\r
+    }\r
+\r
+    public static TimeZone getUserTimeZone() {\r
+        return TimeZone.getTimeZone("Asia/Tokyo");\r
+    }\r
+\r
+    public static Date getNow(TimeZone tz) {\r
+        Calendar c = Calendar.getInstance(tz);\r
+\r
+        return c.getTime();\r
+    }\r
+\r
+    public static Date getToday(Date date, TimeZone tz) {\r
+        Calendar c = Calendar.getInstance(tz);\r
+        c.setTime(date);\r
+        c.set(Calendar.HOUR_OF_DAY, 0);\r
+        c.set(Calendar.MINUTE, 0);\r
+        c.set(Calendar.SECOND, 0);\r
+        c.set(Calendar.MILLISECOND, 0);\r
+\r
+        return c.getTime();\r
+    }\r
+\r
+    public static Date getWeekStart(Date date, TimeZone tz) {\r
+        Calendar c = Calendar.getInstance(tz);\r
+        c.setTime(date);\r
+        c.set(Calendar.HOUR_OF_DAY, 0);\r
+        c.set(Calendar.MINUTE, 0);\r
+        c.set(Calendar.SECOND, 0);\r
+        c.set(Calendar.MILLISECOND, 0);\r
+\r
+        while (c.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {\r
+            c.add(Calendar.DAY_OF_MONTH, -1);\r
+        }\r
+\r
+        return c.getTime();\r
+    }\r
+\r
+    public static Date getMonthStart(Date date, TimeZone tz) {\r
+        Calendar c = Calendar.getInstance(tz);\r
+        c.setTime(date);\r
+        c.set(Calendar.HOUR_OF_DAY, 0);\r
+        c.set(Calendar.MINUTE, 0);\r
+        c.set(Calendar.SECOND, 0);\r
+        c.set(Calendar.MILLISECOND, 0);\r
+\r
+        c.set(Calendar.DAY_OF_MONTH, 1);\r
+\r
+        return c.getTime();\r
+    }\r
+\r
+    public static Date addCalendar(Date date, int calendarField, int calendarAmount, TimeZone tz) {\r
+        Calendar c = Calendar.getInstance(tz);\r
+        c.setTime(date);\r
+        c.add(calendarField, calendarAmount);\r
+\r
+        return c.getTime();\r
+    }\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/HashUtil.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/HashUtil.java
new file mode 100644 (file)
index 0000000..ed9ed6e
--- /dev/null
@@ -0,0 +1,61 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.util;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.security.MessageDigest;\r
+import java.security.NoSuchAlgorithmException;\r
+\r
+public final class HashUtil {\r
+\r
+    private static final int BUFFER_LENGTH = 1024;\r
+\r
+    private static final int MASK = 0xff;\r
+\r
+    private HashUtil() {\r
+        throw new UnsupportedOperationException();\r
+    }\r
+\r
+    public static String digest(String algorithm, String src) throws IOException {\r
+        return HashUtil.digest(algorithm, new ByteArrayInputStream(src.getBytes()));\r
+    }\r
+\r
+    public static String digest(String algorithm, InputStream in) throws IOException {\r
+        try {\r
+            if (in == null) {\r
+                throw new NullPointerException("in == null");\r
+            }\r
+\r
+            MessageDigest md = MessageDigest.getInstance(algorithm);\r
+\r
+            byte[] buf = new byte[HashUtil.BUFFER_LENGTH];\r
+            int len;\r
+            while ((len = in.read(buf)) != -1) {\r
+                md.update(buf, 0, len);\r
+            }\r
+\r
+            byte[] hashData = md.digest();\r
+            String hash = HashUtil.toHexString(hashData);\r
+\r
+            return hash;\r
+        } catch (NoSuchAlgorithmException e) {\r
+            throw new IOException(e);\r
+        }\r
+    }\r
+\r
+    private static String toHexString(byte[] data) {\r
+        StringBuilder hex = new StringBuilder();\r
+\r
+        for (int i = 0; i < data.length; i++) {\r
+            String b = Integer.toHexString(data[i] & HashUtil.MASK);\r
+            if (b.length() == 1) {\r
+                hex.append("0");\r
+            }\r
+            hex.append(b);\r
+        }\r
+\r
+        return hex.toString();\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/LockUtil.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/LockUtil.java
new file mode 100644 (file)
index 0000000..ded970e
--- /dev/null
@@ -0,0 +1,18 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.util;\r
+\r
+public class LockUtil {\r
+\r
+    private LockUtil() {\r
+        throw new UnsupportedOperationException();\r
+    }\r
+\r
+    public void acquireLock(String key) {\r
+\r
+    }\r
+\r
+    public void releaseLock(String key) {\r
+\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/MoneyDiaryForm.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/MoneyDiaryForm.java
new file mode 100644 (file)
index 0000000..927dd59
--- /dev/null
@@ -0,0 +1,112 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.util;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.IOException;\r
+import java.io.StringReader;\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.Date;\r
+import java.util.List;\r
+\r
+public class MoneyDiaryForm {\r
+\r
+    private Date diaryDate;\r
+\r
+    private List<MoneyDiaryItem> itemList = new ArrayList<MoneyDiaryItem>();\r
+\r
+    public Date getDiaryDate() {\r
+        return this.diaryDate;\r
+    }\r
+\r
+    public void setDiaryDate(Date diaryDate) {\r
+        this.diaryDate = diaryDate;\r
+    }\r
+\r
+    public List<MoneyDiaryItem> getItemList() {\r
+        return Collections.unmodifiableList(this.itemList);\r
+    }\r
+\r
+    public long getMoney() {\r
+        long money = 0;\r
+\r
+        for (MoneyDiaryItem item : this.itemList) {\r
+            money += item.getMoney();\r
+        }\r
+\r
+        return money;\r
+    }\r
+\r
+    public String getText() {\r
+        StringBuilder text = new StringBuilder();\r
+\r
+        for (MoneyDiaryItem item : this.itemList) {\r
+            if (item.getItem() != null) {\r
+                text.append(item.getItem());\r
+            } else {\r
+                text.append("(なし)");\r
+            }\r
+\r
+            text.append(" ");\r
+            text.append(item.getMoney());\r
+\r
+            if (item.getComment() != null) {\r
+                text.append(" ");\r
+                text.append(item.getComment());\r
+            }\r
+\r
+            text.append("\r\n");\r
+        }\r
+\r
+        return text.toString();\r
+    }\r
+\r
+    public void setText(String text) throws IOException {\r
+        List<MoneyDiaryItem> l = new ArrayList<MoneyDiaryItem>();\r
+\r
+        BufferedReader reader = new BufferedReader(new StringReader(text));\r
+        try {\r
+            String line = null;\r
+            while ((line = reader.readLine()) != null) {\r
+                line = line.trim();\r
+\r
+                String column1 = null;\r
+                String column2 = null;\r
+                String column3 = null;\r
+\r
+                if (line.indexOf(" ") != -1) {\r
+                    int index = line.indexOf(" ");\r
+                    column1 = line.substring(0, index);\r
+                    line = line.substring(index + 1);\r
+                } else {\r
+                    continue;\r
+                }\r
+\r
+                if (line.indexOf(" ") != -1) {\r
+                    int index = line.indexOf(" ");\r
+                    column2 = line.substring(0, index);\r
+                    column3 = line.substring(index + 1);\r
+                } else {\r
+                    column2 = line;\r
+                }\r
+\r
+                MoneyDiaryItem diaryItem = new MoneyDiaryItem();\r
+\r
+                diaryItem.setItem(column1);\r
+                try {\r
+                    diaryItem.setMoney(Long.parseLong(column2));\r
+                } catch (NumberFormatException e) {\r
+                    continue;\r
+                }\r
+                diaryItem.setComment(column3);\r
+\r
+                l.add(diaryItem);\r
+            }\r
+        } finally {\r
+            reader.close();\r
+        }\r
+\r
+        this.itemList = l;\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/MoneyDiaryItem.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/util/MoneyDiaryItem.java
new file mode 100644 (file)
index 0000000..2667fcd
--- /dev/null
@@ -0,0 +1,36 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.util;\r
+\r
+public class MoneyDiaryItem {\r
+\r
+    private String item;\r
+\r
+    private long money;\r
+\r
+    private String comment;\r
+\r
+    public String getItem() {\r
+        return this.item;\r
+    }\r
+\r
+    public void setItem(String item) {\r
+        this.item = item;\r
+    }\r
+\r
+    public long getMoney() {\r
+        return this.money;\r
+    }\r
+\r
+    public void setMoney(long money) {\r
+        this.money = money;\r
+    }\r
+\r
+    public String getComment() {\r
+        return this.comment;\r
+    }\r
+\r
+    public void setComment(String comment) {\r
+        this.comment = comment;\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/filter/LoginCheckFilter.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/filter/LoginCheckFilter.java
new file mode 100644 (file)
index 0000000..098936c
--- /dev/null
@@ -0,0 +1,71 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.web.filter;\r
+\r
+import java.io.IOException;\r
+import java.util.logging.Logger;\r
+\r
+import javax.servlet.Filter;\r
+import javax.servlet.FilterChain;\r
+import javax.servlet.FilterConfig;\r
+import javax.servlet.ServletException;\r
+import javax.servlet.ServletRequest;\r
+import javax.servlet.ServletResponse;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.logic.LoginLogic;\r
+\r
+public class LoginCheckFilter implements Filter {\r
+\r
+    // TODO 共通ログイン処理を考える。\r
+    // ログイン後、2週間ログイン状態を保持。セッション情報とは別に管理している。\r
+    // ページアクセス時、セッション上のログイン情報が存在しないけどログイン状態は保持している場合、自動的にログイン処理を行う。\r
+    // ページアクセス時、ログイン状態の有効期限を常に2週間延ばす。\r
+\r
+    private static final Logger LOG = Logger.getLogger(LoginCheckFilter.class.getName());\r
+\r
+    @Override\r
+    public void destroy() {\r
+    }\r
+\r
+    @Override\r
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {\r
+        LoginCheckFilter.LOG.config("LoginCheckFilter処理開始");\r
+\r
+        // 必要なデータを用意する。\r
+        HttpServletRequest req = null;\r
+        HttpServletResponse resp = null;\r
+\r
+        if (request instanceof HttpServletRequest) {\r
+            req = (HttpServletRequest) request;\r
+        }\r
+        if (response instanceof HttpServletResponse) {\r
+            resp = (HttpServletResponse) response;\r
+        }\r
+\r
+        LoginLogic loginLogic = new LoginLogic(req, resp);\r
+\r
+        // ログイン済みではない場合、自動ログインを試みる。\r
+        if (!loginLogic.isLogined()) {\r
+            loginLogic.autoLogin();\r
+        }\r
+\r
+        if (loginLogic.isLogined()) {\r
+            // ログイン済みの場合、次の処理を行う。\r
+            chain.doFilter(request, response);\r
+\r
+            // ログインCookieを更新する。\r
+            loginLogic.updateLoginCookie();\r
+        } else {\r
+            // 未ログインの場合、ログイン画面にリダイレクトする。\r
+            resp.sendRedirect("/m/login");\r
+        }\r
+\r
+        LoginCheckFilter.LOG.config("LoginCheckFilter処理終了");\r
+    }\r
+\r
+    @Override\r
+    public void init(FilterConfig config) throws ServletException {\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/filter/RequestLogFilter.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/filter/RequestLogFilter.java
new file mode 100644 (file)
index 0000000..ac03d8f
--- /dev/null
@@ -0,0 +1,77 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.web.filter;\r
+\r
+import java.io.IOException;\r
+import java.util.Enumeration;\r
+import java.util.logging.Logger;\r
+\r
+import javax.servlet.Filter;\r
+import javax.servlet.FilterChain;\r
+import javax.servlet.FilterConfig;\r
+import javax.servlet.ServletException;\r
+import javax.servlet.ServletRequest;\r
+import javax.servlet.ServletResponse;\r
+import javax.servlet.http.HttpServletRequest;\r
+\r
+public class RequestLogFilter implements Filter {\r
+\r
+    private static final Logger LOG = Logger.getLogger(RequestLogFilter.class.getName());\r
+\r
+    @Override\r
+    public void destroy() {\r
+    }\r
+\r
+    @Override\r
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {\r
+        if (request instanceof HttpServletRequest) {\r
+            HttpServletRequest req = (HttpServletRequest) request;\r
+\r
+            StringBuilder log = new StringBuilder();\r
+            log.append("[Request]\r\n");\r
+            log.append("AuthType: ").append(req.getAuthType()).append("\r\n");\r
+            log.append("CharacterEncoding: ").append(req.getCharacterEncoding()).append("\r\n");\r
+            log.append("ContentLength: ").append(req.getContentLength()).append("\r\n");\r
+            log.append("ContentType: ").append(req.getContentType()).append("\r\n");\r
+            log.append("ContextPath: ").append(req.getContextPath()).append("\r\n");\r
+            log.append("LocalAddr: ").append(req.getLocalAddr()).append("\r\n");\r
+            log.append("Locale: ").append(req.getLocale()).append("\r\n");\r
+            log.append("LocalName: ").append(req.getLocalName()).append("\r\n");\r
+            log.append("LocalPort: ").append(req.getLocalPort()).append("\r\n");\r
+            log.append("Method: ").append(req.getMethod()).append("\r\n");\r
+            log.append("PathInfo: ").append(req.getPathInfo()).append("\r\n");\r
+            log.append("PathTranslated: ").append(req.getPathTranslated()).append("\r\n");\r
+            log.append("Protocol: ").append(req.getProtocol()).append("\r\n");\r
+            log.append("QueryString: ").append(req.getQueryString()).append("\r\n");\r
+            log.append("RemoteAddr: ").append(req.getRemoteAddr()).append("\r\n");\r
+            log.append("RemoteHost: ").append(req.getRemoteHost()).append("\r\n");\r
+            log.append("RemotePort: ").append(req.getRemotePort()).append("\r\n");\r
+            log.append("RemoteUser: ").append(req.getRemoteUser()).append("\r\n");\r
+            log.append("RequestURI: ").append(req.getRequestURI()).append("\r\n");\r
+            log.append("RequestURL: ").append(req.getRequestURL()).append("\r\n");\r
+            log.append("Scheme: ").append(req.getScheme()).append("\r\n");\r
+            log.append("ServerName: ").append(req.getServerName()).append("\r\n");\r
+            log.append("ServerPort: ").append(req.getServerPort()).append("\r\n");\r
+            log.append("ServletPath: ").append(req.getServletPath()).append("\r\n");\r
+            log.append("\r\n");\r
+\r
+            for (Enumeration<?> headerNameEnu = req.getHeaderNames(); headerNameEnu.hasMoreElements();) {\r
+                String headerName = (String) headerNameEnu.nextElement();\r
+\r
+                for (Enumeration<?> headerValueEnu = req.getHeaders(headerName); headerValueEnu.hasMoreElements();) {\r
+                    Object headerValue = headerValueEnu.nextElement();\r
+\r
+                    log.append("Header: ").append(headerName).append(": ").append(headerValue).append("\r\n");\r
+                }\r
+            }\r
+\r
+            RequestLogFilter.LOG.config(log.toString());\r
+        }\r
+\r
+        chain.doFilter(request, response);\r
+    }\r
+\r
+    @Override\r
+    public void init(FilterConfig config) throws ServletException {\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/admin/MaintenanceServlet.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/admin/MaintenanceServlet.java
new file mode 100644 (file)
index 0000000..49ad5e0
--- /dev/null
@@ -0,0 +1,20 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.web.servlet.admin;\r
+\r
+import java.io.IOException;\r
+\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServlet;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+@SuppressWarnings("serial")\r
+public class MaintenanceServlet extends HttpServlet {\r
+\r
+    @Override\r
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\r
+        resp.setContentType("text/plain");\r
+        resp.getWriter().write("ok");\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/admin/UserDataServlet.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/admin/UserDataServlet.java
new file mode 100644 (file)
index 0000000..f571d64
--- /dev/null
@@ -0,0 +1,122 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.web.servlet.admin;\r
+\r
+import java.io.IOException;\r
+\r
+import javax.jdo.PersistenceManager;\r
+import javax.jdo.Transaction;\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServlet;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.dao.AccountEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.MoneyDiaryEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.PMF;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.TempAccountEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.UserDao;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.UserEntity;\r
+import net.arnx.jsonic.JSON;\r
+\r
+@SuppressWarnings("serial")\r
+public class UserDataServlet extends HttpServlet {\r
+\r
+    // private static final Logger LOG = Logger.getLogger(UserDataServlet.class.getName());\r
+\r
+    @Override\r
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\r
+        resp.setContentType("text/plain");\r
+        resp.setCharacterEncoding("UTF-8");\r
+\r
+        long id = Long.parseLong(req.getParameter("id"));\r
+\r
+        UserEntity userBackup;\r
+\r
+        PersistenceManager pm = PMF.get().getPersistenceManager();\r
+        try {\r
+            Transaction tx = pm.currentTransaction();\r
+            try {\r
+                tx.begin();\r
+\r
+                UserDao userDao = new UserDao(pm);\r
+                UserEntity user = userDao.findById(id);\r
+\r
+                userBackup = user.backup();\r
+            } finally {\r
+                tx.rollback();\r
+            }\r
+        } finally {\r
+            pm.close();\r
+        }\r
+\r
+        JSON.encode(userBackup, resp.getOutputStream(), true);\r
+    }\r
+\r
+    @Override\r
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\r
+        String reqData = req.getParameter("data");\r
+\r
+        UserEntity userUpload = JSON.decode(reqData, UserEntity.class);\r
+\r
+        PersistenceManager pm = PMF.get().getPersistenceManager();\r
+        try {\r
+            Transaction tx = pm.currentTransaction();\r
+            try {\r
+                tx.begin();\r
+\r
+                UserEntity user = new UserEntity();\r
+                user.setEntityState(userUpload.getEntityState());\r
+                user.setUpdateDatetime(userUpload.getUpdateDatetime());\r
+                pm.makePersistent(user);\r
+\r
+                AccountEntity accountUpload = userUpload.getAccount();\r
+                AccountEntity account = new AccountEntity();\r
+                account.setEmail(accountUpload.getEmail());\r
+                account.setEntityState(accountUpload.getEntityState());\r
+                account.setPassword(accountUpload.getPassword());\r
+                account.setPasswordHashAlgorithm(accountUpload.getPasswordHashAlgorithm());\r
+                account.setUpdateDatetime(accountUpload.getUpdateDatetime());\r
+                account.setUser(user);\r
+                pm.makePersistent(account);\r
+\r
+                for (MoneyDiaryEntity moneyDiaryUpload : userUpload.getMoneyDiaryList()) {\r
+                    MoneyDiaryEntity moneyDiary = new MoneyDiaryEntity();\r
+                    moneyDiary.setDiaryDate(moneyDiaryUpload.getDiaryDate());\r
+                    moneyDiary.setEntityState(moneyDiaryUpload.getEntityState());\r
+                    moneyDiary.setMoney(moneyDiaryUpload.getMoney());\r
+                    moneyDiary.setText(moneyDiaryUpload.getText());\r
+                    moneyDiary.setUpdateDatetime(moneyDiaryUpload.getUpdateDatetime());\r
+                    moneyDiary.setUser(user);\r
+                    pm.makePersistent(moneyDiary);\r
+\r
+                    user.getMoneyDiaryList().add(moneyDiary);\r
+                }\r
+\r
+                TempAccountEntity tempAccountUpload = userUpload.getTempAccount();\r
+                TempAccountEntity tempAccount = new TempAccountEntity();\r
+                tempAccount.setEmail(tempAccountUpload.getEmail());\r
+                tempAccount.setEntityState(tempAccountUpload.getEntityState());\r
+                tempAccount.setUpdateDatetime(tempAccountUpload.getUpdateDatetime());\r
+                tempAccount.setUser(user);\r
+                pm.makePersistent(tempAccount);\r
+\r
+                user.setTempAccount(tempAccount);\r
+\r
+                pm.makePersistent(user);\r
+\r
+                tx.commit();\r
+            } finally {\r
+                if (tx.isActive()) {\r
+                    tx.rollback();\r
+                }\r
+            }\r
+        } finally {\r
+            pm.close();\r
+        }\r
+\r
+        resp.setContentType("text/plain");\r
+        resp.setCharacterEncoding("UTF-8");\r
+        resp.getWriter().println("ok");\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/admin/UserIdListServlet.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/admin/UserIdListServlet.java
new file mode 100644 (file)
index 0000000..c2cb152
--- /dev/null
@@ -0,0 +1,48 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.web.servlet.admin;\r
+\r
+import java.io.IOException;\r
+import java.io.PrintWriter;\r
+import java.util.List;\r
+\r
+import javax.jdo.PersistenceManager;\r
+import javax.jdo.Transaction;\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServlet;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.dao.PMF;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.UserEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.util.CollectionUtil;\r
+\r
+@SuppressWarnings("serial")\r
+public class UserIdListServlet extends HttpServlet {\r
+\r
+    @Override\r
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\r
+        resp.setContentType("text/plain");\r
+        resp.setCharacterEncoding("UTF-8");\r
+\r
+        PrintWriter w = resp.getWriter();\r
+\r
+        PersistenceManager pm = PMF.get().getPersistenceManager();\r
+        try {\r
+            Transaction tx = pm.currentTransaction();\r
+            try {\r
+                tx.begin();\r
+\r
+                List<UserEntity> userList = CollectionUtil.castToList(pm.newQuery(UserEntity.class).execute());\r
+\r
+                for (UserEntity user : userList) {\r
+                    w.println(user.getKey().getId());\r
+                }\r
+            } finally {\r
+                tx.rollback();\r
+            }\r
+        } finally {\r
+            pm.close();\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mail/CreateMoneyForm.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mail/CreateMoneyForm.java
new file mode 100644 (file)
index 0000000..8cc1958
--- /dev/null
@@ -0,0 +1,36 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.web.servlet.mail;\r
+\r
+public class CreateMoneyForm {\r
+\r
+    private String toEmail;\r
+\r
+    private String subject;\r
+\r
+    private String body;\r
+\r
+    public String getToEmail() {\r
+        return this.toEmail;\r
+    }\r
+\r
+    public void setToEmail(String toEmail) {\r
+        this.toEmail = toEmail;\r
+    }\r
+\r
+    public String getSubject() {\r
+        return this.subject;\r
+    }\r
+\r
+    public void setSubject(String subject) {\r
+        this.subject = subject;\r
+    }\r
+\r
+    public String getBody() {\r
+        return this.body;\r
+    }\r
+\r
+    public void setBody(String body) {\r
+        this.body = body;\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mail/CreateMoneyServlet.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mail/CreateMoneyServlet.java
new file mode 100644 (file)
index 0000000..eacab53
--- /dev/null
@@ -0,0 +1,199 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.web.servlet.mail;\r
+\r
+import java.io.IOException;\r
+import java.text.ParseException;\r
+import java.text.SimpleDateFormat;\r
+import java.util.Calendar;\r
+import java.util.Date;\r
+import java.util.List;\r
+import java.util.Properties;\r
+import java.util.TimeZone;\r
+import java.util.logging.Logger;\r
+\r
+import javax.jdo.PersistenceManager;\r
+import javax.jdo.Transaction;\r
+import javax.mail.MessagingException;\r
+import javax.mail.Multipart;\r
+import javax.mail.Part;\r
+import javax.mail.Session;\r
+import javax.mail.Message.RecipientType;\r
+import javax.mail.internet.InternetAddress;\r
+import javax.mail.internet.MimeMessage;\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServlet;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.dao.MoneyDiaryDao;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.MoneyDiaryEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.PMF;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.UserDao;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.UserEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.util.DateUtil;\r
+import jp.gr.java_conf.u6k.money_notebook.util.MoneyDiaryForm;\r
+\r
+@SuppressWarnings("serial")\r
+public class CreateMoneyServlet extends HttpServlet {\r
+\r
+    // TODO 記帳したよメールを返信する。記帳した内容、今日の合計支出、今週の合計支出、今月の合計支出、ユーザートップへのリンクを返信する。\r
+\r
+    private static final Logger LOG = Logger.getLogger(CreateMoneyServlet.class.getName());\r
+\r
+    @Override\r
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\r
+        CreateMoneyServlet.LOG.config("メールでお金を登録処理開始");\r
+\r
+        try {\r
+            TimeZone tz = DateUtil.getUserTimeZone();\r
+            Date updateDatetime = DateUtil.getNow(tz);\r
+            Date diaryDate = DateUtil.getToday(updateDatetime, tz);\r
+\r
+            // メールを解析して、記帳する情報を取得する。\r
+            CreateMoneyForm form = this.getForm(req);\r
+\r
+            if (form.getSubject() != null && form.getSubject().length() > 0) {\r
+                SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");\r
+                try {\r
+                    diaryDate = DateUtil.getToday(formatter.parse(form.getSubject()), tz);\r
+                } catch (ParseException e) {\r
+                    throw new ServletException(e);\r
+                }\r
+\r
+            }\r
+\r
+            // 記帳する。\r
+            PersistenceManager pm = PMF.get().getPersistenceManager();\r
+            try {\r
+                Transaction tx = pm.currentTransaction();\r
+                try {\r
+                    tx.begin();\r
+\r
+                    UserEntity user = this.getUser(pm, form);\r
+                    this.createMoney(pm, user, diaryDate, updateDatetime, form);\r
+\r
+                    tx.commit();\r
+                } finally {\r
+                    if (tx.isActive()) {\r
+                        tx.rollback();\r
+                    }\r
+                }\r
+            } finally {\r
+                pm.close();\r
+            }\r
+        } catch (MessagingException e) {\r
+            throw new ServletException(e);\r
+        }\r
+\r
+        CreateMoneyServlet.LOG.config("メールでお金を登録処理終了");\r
+    }\r
+\r
+    private CreateMoneyForm getForm(HttpServletRequest req) throws ServletException, MessagingException, IOException {\r
+        CreateMoneyServlet.LOG.config("メール解析処理開始");\r
+\r
+        Properties props = System.getProperties();\r
+        Session mailSession = Session.getDefaultInstance(props, null);\r
+        MimeMessage msg = new MimeMessage(mailSession, req.getInputStream());\r
+\r
+        if (msg.getRecipients(RecipientType.TO).length != 1) {\r
+            throw new ServletException("メール送信先が1つではありません。");\r
+        }\r
+\r
+        String toEmail = ((InternetAddress) msg.getRecipients(RecipientType.TO)[0]).getAddress();\r
+\r
+        String subject = msg.getSubject();\r
+\r
+        String body = this.getMailBody(msg);\r
+\r
+        CreateMoneyForm form = new CreateMoneyForm();\r
+        form.setToEmail(toEmail);\r
+        form.setSubject(subject);\r
+        form.setBody(body);\r
+\r
+        CreateMoneyServlet.LOG.config("メール解析処理終了");\r
+\r
+        return form;\r
+    }\r
+\r
+    private String getMailBody(Part part) throws MessagingException, IOException {\r
+        CreateMoneyServlet.LOG.config("MimeType: text/plain");\r
+\r
+        if (part.isMimeType("text/plain")) {\r
+\r
+            String body = (String) part.getContent();\r
+            return body;\r
+\r
+        } else if (part.isMimeType("multipart/*")) {\r
+\r
+            Multipart multipart = (Multipart) part.getContent();\r
+            int count = multipart.getCount();\r
+\r
+            for (int i = 0; i < count; i++) {\r
+                String body = this.getMailBody(multipart.getBodyPart(i));\r
+                if (body != null) {\r
+                    return body;\r
+                }\r
+            }\r
+\r
+            return null;\r
+\r
+        } else {\r
+\r
+            return null;\r
+\r
+        }\r
+    }\r
+\r
+    private UserEntity getUser(PersistenceManager pm, CreateMoneyForm form) throws ServletException {\r
+        String idString = form.getToEmail();\r
+        idString = idString.substring(0, idString.indexOf("@"));\r
+        long id = Long.parseLong(idString);\r
+\r
+        UserDao userDao = new UserDao(pm);\r
+        UserEntity user = userDao.findById(id);\r
+\r
+        if (user == null) {\r
+            throw new ServletException("ID: " + id + "のユーザは存在しません。");\r
+        }\r
+\r
+        return user;\r
+    }\r
+\r
+    private void createMoney(PersistenceManager pm, UserEntity user, Date diaryDate, Date updateDatetime, CreateMoneyForm form) throws IOException {\r
+        MoneyDiaryDao moneyDiaryDao = new MoneyDiaryDao(pm);\r
+\r
+        Date diaryDateBegin = diaryDate;\r
+        Date diaryDateEnd = DateUtil.addCalendar(diaryDateBegin, Calendar.DAY_OF_MONTH, 1, DateUtil.getUserTimeZone());\r
+        List<MoneyDiaryEntity> moneyDiaryList = moneyDiaryDao.findByUserAndDiaryDateBetween(user, diaryDateBegin, diaryDateEnd);\r
+\r
+        MoneyDiaryEntity moneyDiary = null;\r
+\r
+        if (moneyDiaryList.size() == 0) {\r
+            MoneyDiaryForm f = new MoneyDiaryForm();\r
+            f.setText(form.getBody());\r
+\r
+            moneyDiary = new MoneyDiaryEntity();\r
+            moneyDiary.setUser(user);\r
+            moneyDiary.setDiaryDate(diaryDate);\r
+            moneyDiary.setText(f.getText());\r
+            moneyDiary.setMoney(f.getMoney());\r
+            moneyDiary.setUpdateDatetime(updateDatetime);\r
+\r
+            user.getMoneyDiaryList().add(moneyDiary);\r
+\r
+            pm.makePersistent(user);\r
+        } else {\r
+            moneyDiary = moneyDiaryList.get(0);\r
+\r
+            MoneyDiaryForm f = new MoneyDiaryForm();\r
+            f.setText(moneyDiary.getText() + form.getBody());\r
+\r
+            moneyDiary.setText(f.getText());\r
+            moneyDiary.setMoney(f.getMoney());\r
+            moneyDiary.setUpdateDatetime(updateDatetime);\r
+\r
+            pm.makePersistent(moneyDiary);\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mail/RegistMailServlet.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mail/RegistMailServlet.java
new file mode 100644 (file)
index 0000000..36516b5
--- /dev/null
@@ -0,0 +1,193 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.web.servlet.mail;\r
+\r
+import java.io.IOException;\r
+import java.io.UnsupportedEncodingException;\r
+import java.util.Date;\r
+import java.util.Properties;\r
+import java.util.TimeZone;\r
+import java.util.logging.Logger;\r
+\r
+import javax.jdo.PersistenceManager;\r
+import javax.jdo.Transaction;\r
+import javax.mail.Message;\r
+import javax.mail.MessagingException;\r
+import javax.mail.Session;\r
+import javax.mail.Transport;\r
+import javax.mail.internet.InternetAddress;\r
+import javax.mail.internet.MimeMessage;\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServlet;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.dao.AccountDao;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.AccountEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.PMF;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.TempAccountEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.UserEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.util.DateUtil;\r
+\r
+@SuppressWarnings("serial")\r
+public class RegistMailServlet extends HttpServlet {\r
+\r
+    private static final Logger LOG = Logger.getLogger(RegistMailServlet.class.getName());\r
+\r
+    @Override\r
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\r
+        RegistMailServlet.LOG.config("会員登録メール受信処理開始");\r
+        try {\r
+            TimeZone tz = DateUtil.getUserTimeZone();\r
+            Date currentDatetime = DateUtil.getNow(tz);\r
+\r
+            // メールを解析して、メール送信元を取得する。\r
+            String email = this.getFromAddressFromRequestMail(req);\r
+\r
+            UserEntity user;\r
+\r
+            PersistenceManager pm = PMF.get().getPersistenceManager();\r
+            try {\r
+                Transaction tx = pm.currentTransaction();\r
+                try {\r
+                    tx.begin();\r
+\r
+                    // 既にメールアドレスが登録されている場合、会員登録はしないで処理を終了する。\r
+                    boolean exist = this.existAccount(pm, email);\r
+\r
+                    if (exist) {\r
+                        // 既に会員登録されているので、ユーザを作成しないでメールを返信する。\r
+                        this.sendReturnAlreadyExistMail(email);\r
+                    } else {\r
+                        // ユーザを作成して、会員仮登録する。\r
+                        user = this.createUserAndTempAccount(email, currentDatetime);\r
+                        pm.makePersistent(user);\r
+\r
+                        // 仮登録したことをユーザにメール送信する。\r
+                        this.sendReturnMail(user);\r
+                    }\r
+\r
+                    tx.commit();\r
+                } finally {\r
+                    if (tx.isActive()) {\r
+                        tx.rollback();\r
+                    }\r
+                }\r
+            } finally {\r
+                pm.close();\r
+            }\r
+\r
+            RegistMailServlet.LOG.config("会員登録メール受信処理終了");\r
+        } catch (MessagingException e) {\r
+            throw new ServletException(e);\r
+        }\r
+    }\r
+\r
+    private String getFromAddressFromRequestMail(HttpServletRequest req) throws MessagingException, IOException, ServletException {\r
+        RegistMailServlet.LOG.config("メール送信元取得処理開始");\r
+\r
+        Properties props = System.getProperties();\r
+        Session mailSession = Session.getDefaultInstance(props, null);\r
+        MimeMessage msg = new MimeMessage(mailSession, req.getInputStream());\r
+\r
+        if (msg.getFrom().length != 1) {\r
+            throw new ServletException("メール送信元が1つではありません。");\r
+        }\r
+        if (!(msg.getFrom()[0] instanceof InternetAddress)) {\r
+            throw new ServletException("メール送信元がInternetAddressではありません。");\r
+        }\r
+\r
+        String email = ((InternetAddress) msg.getFrom()[0]).getAddress();\r
+\r
+        RegistMailServlet.LOG.config("メール送信元: " + email);\r
+        RegistMailServlet.LOG.config("メール送信元取得処理終了");\r
+\r
+        return email;\r
+    }\r
+\r
+    private boolean existAccount(PersistenceManager pm, String email) {\r
+        RegistMailServlet.LOG.config("既存会員判定処理開始");\r
+\r
+        AccountDao accountDao = new AccountDao(pm);\r
+        AccountEntity account = accountDao.findByEmail(email);\r
+\r
+        boolean result = (account != null);\r
+\r
+        RegistMailServlet.LOG.config("既存会員判定処理終了");\r
+\r
+        return result;\r
+    }\r
+\r
+    private UserEntity createUserAndTempAccount(String email, Date currentDatetime) {\r
+        RegistMailServlet.LOG.config("ユーザ、及び一時会員登録処理開始");\r
+\r
+        TempAccountEntity tempAccount = new TempAccountEntity();\r
+        tempAccount.setEmail(email);\r
+        tempAccount.setUpdateDatetime(currentDatetime);\r
+\r
+        UserEntity user = new UserEntity();\r
+        user.setUpdateDatetime(currentDatetime);\r
+        user.setTempAccount(tempAccount);\r
+\r
+        RegistMailServlet.LOG.config("ユーザ、及び一時会員登録処理終了");\r
+\r
+        return user;\r
+    }\r
+\r
+    private void sendReturnMail(UserEntity user) throws MessagingException, UnsupportedEncodingException {\r
+        RegistMailServlet.LOG.config("一時会員登録返信メール送信処理開始");\r
+\r
+        String content = "以下のURLにアクセスして、会員登録を続行してください。\r\n";\r
+        content += "http://money-notebook.appspot.com" + this.getServletContext().getContextPath() + "/m/regist/" + user.getKey().getId() + "/";\r
+\r
+        InternetAddress fromAddress = new InternetAddress("u6k.yu1@gmail.com");\r
+        InternetAddress toAddress = new InternetAddress(user.getTempAccount().getEmail());\r
+\r
+        Properties props = System.getProperties();\r
+        Session mailSession = Session.getDefaultInstance(props, null);\r
+\r
+        MimeMessage mail = new MimeMessage(mailSession);\r
+        mail.setHeader("Content-Type", "text/plain; charset=ISO-2022-JP");\r
+        mail.setHeader("Content-Transfer-Encoding", "7bit");\r
+        mail.setFrom(fromAddress);\r
+        mail.addRecipient(Message.RecipientType.TO, toAddress);\r
+        mail.setSubject("[小遣い帳(仮)]会員登録受付のお知らせ", "ISO-2022-JP");\r
+        mail.setText(content, "ISO-2022-JP");\r
+\r
+        Transport.send(mail);\r
+\r
+        RegistMailServlet.LOG.config("一時会員登録返信メール送信処理終了");\r
+    }\r
+\r
+    private void sendReturnAlreadyExistMail(String email) throws MessagingException {\r
+        RegistMailServlet.LOG.config("既に会員登録されています返信メール送信処理開始");\r
+\r
+        String content = email + "様はすでに会員登録されています。\r\n";\r
+        content += "ログインして小遣い帳(仮)を利用できます。\r\n";\r
+        content += "http://money-notebook.appspot.com" + this.getServletContext().getContextPath() + "/m/login\r\n";\r
+        content += "\r\n";\r
+        content += "パスワードを忘れてしまった場合、一時的なパスワードを発行することができます。\r\n";\r
+        content += "http://money-notebook.appspot.com" + this.getServletContext().getContextPath() + "/m/onetime-password\r\n";\r
+        content += "\r\n";\r
+        content += "そのほかのお問い合わせは、ヘルプをご覧下さい。\r\n";\r
+        content += "http://money-notebook.appspot.com" + this.getServletContext().getContextPath() + "m/help\r\n";\r
+\r
+        InternetAddress fromAddress = new InternetAddress("u6k.yu1@gmail.com");\r
+        InternetAddress toAddress = new InternetAddress(email);\r
+\r
+        Properties props = System.getProperties();\r
+        Session mailSession = Session.getDefaultInstance(props, null);\r
+\r
+        MimeMessage mail = new MimeMessage(mailSession);\r
+        mail.setHeader("Content-Type", "text/plain; charset=ISO-2022-JP");\r
+        mail.setHeader("Content-Transfer-Encoding", "7bit");\r
+        mail.setFrom(fromAddress);\r
+        mail.addRecipient(Message.RecipientType.TO, toAddress);\r
+        mail.setSubject("[小遣い帳(仮)]既に会員登録されています", "ISO-2022-JP");\r
+        mail.setText(content, "ISO-2022-JP");\r
+\r
+        Transport.send(mail);\r
+\r
+        RegistMailServlet.LOG.config("既に会員登録されています返信メール送信処理終了");\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/IndexServlet.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/IndexServlet.java
new file mode 100644 (file)
index 0000000..52f5dae
--- /dev/null
@@ -0,0 +1,19 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.web.servlet.mobile;\r
+\r
+import java.io.IOException;\r
+\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServlet;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+@SuppressWarnings("serial")\r
+public class IndexServlet extends HttpServlet {\r
+\r
+    @Override\r
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\r
+        req.getRequestDispatcher("/WEB-INF/page/mobile/index.jsp").forward(req, resp);\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/LoginServlet.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/LoginServlet.java
new file mode 100644 (file)
index 0000000..181359b
--- /dev/null
@@ -0,0 +1,130 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.web.servlet.mobile;\r
+\r
+import java.io.IOException;\r
+import java.util.logging.Logger;\r
+\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServlet;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.logic.LoginLogic;\r
+\r
+@SuppressWarnings("serial")\r
+public class LoginServlet extends HttpServlet {\r
+\r
+    // TODO 未ログイン状態でユーザーページにアクセスしたとき、ログインページにリダイレクトする。\r
+    // ログイン後、元々アクセスしたかったページにリダイレクトする。元々アクセスしたいページが無い場合、ユーザートップにリダイレクトする。\r
+\r
+    // TODO ログインは同時に1端末からのみ。別端末からログインした場合、ログイン情報が異なることを検知して弾く。\r
+\r
+    private static final Logger LOG = Logger.getLogger(LoginServlet.class.getName());\r
+\r
+    @Override\r
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\r
+        LoginServlet.LOG.config("ログイン初期化処理開始");\r
+\r
+        // 既にログイン済みの場合、ユーザトップ画面にリダイレクトする。\r
+        LoginLogic loginLogic = new LoginLogic(req, resp);\r
+\r
+        if (loginLogic.isLogined()) {\r
+            // ユーザ・トップ画面へリダイレクトする。\r
+            LoginServlet.LOG.config("ユーザ・トップ画面へリダイレクト処理開始");\r
+\r
+            resp.sendRedirect("/m/user/" + loginLogic.getLoginId() + "/top");\r
+\r
+            LoginServlet.LOG.config("ユーザ・トップ画面へリダイレクト処理終了");\r
+\r
+            return;\r
+        }\r
+\r
+        // 画面情報を初期化する。\r
+        LoginServlet.LOG.config("画面情報初期化開始");\r
+\r
+        req.setAttribute("email", "");\r
+        req.setAttribute("message", "");\r
+\r
+        LoginServlet.LOG.config("画面情報初期化終了");\r
+\r
+        // JSPへフォワードする。\r
+        LoginServlet.LOG.config("JSPへフォワード開始");\r
+\r
+        this.getServletContext().getRequestDispatcher("/WEB-INF/page/mobile/login.jsp").forward(req, resp);\r
+\r
+        LoginServlet.LOG.config("JSPへフォワード終了");\r
+\r
+        LoginServlet.LOG.config("ログイン初期化処理終了");\r
+    }\r
+\r
+    @Override\r
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\r
+        LoginServlet.LOG.config("ログイン処理開始");\r
+\r
+        // 入力を取得し、入力チェックを行う。\r
+        LoginServlet.LOG.config("ユーザ入力取得・チェック処理開始");\r
+\r
+        String email = req.getParameter("email");\r
+        String password = req.getParameter("password");\r
+\r
+        LoginServlet.LOG.config("メールアドレス: " + email);\r
+\r
+        String message = null;\r
+\r
+        if (email == null || "".equals(email)) {\r
+            message = "メールアドレスを入力してください。";\r
+            LoginServlet.LOG.config("入力チェック失敗: " + message);\r
+        }\r
+\r
+        if (message == null && (password == null || "".equals(password))) {\r
+            message = "パスワードを入力してください。";\r
+            LoginServlet.LOG.config("入力チェック失敗: " + message);\r
+        }\r
+\r
+        if (message != null) {\r
+            LoginServlet.LOG.config("ユーザ入力チェック失敗開始");\r
+\r
+            req.setAttribute("email", email);\r
+            req.setAttribute("message", message);\r
+\r
+            this.getServletContext().getRequestDispatcher("/WEB-INF/page/mobile/login.jsp").forward(req, resp);\r
+\r
+            LoginServlet.LOG.config("ユーザ入力チェック失敗終了");\r
+\r
+            return;\r
+        }\r
+\r
+        LoginServlet.LOG.config("ユーザ入力取得・チェック処理終了");\r
+\r
+        // ログイン・ビジネス処理を行う。\r
+        LoginServlet.LOG.config("ログイン・ビジネス処理開始");\r
+\r
+        LoginLogic loginLogic = new LoginLogic(req, resp);\r
+        if (!loginLogic.login(email, password)) {\r
+            LoginServlet.LOG.config("ログイン・ビジネス処理失敗");\r
+\r
+            message = "メールアドレス、またはパスワードが間違えています。";\r
+\r
+            req.setAttribute("email", email);\r
+            req.setAttribute("message", message);\r
+\r
+            this.getServletContext().getRequestDispatcher("/WEB-INF/page/mobile/login.jsp").forward(req, resp);\r
+\r
+            LoginServlet.LOG.config("ログイン・ビジネス処理失敗終了");\r
+\r
+            return;\r
+        }\r
+\r
+        LoginServlet.LOG.config("ログイン・ビジネス処理終了");\r
+\r
+        // ユーザ・トップ画面へリダイレクトする。\r
+        LoginServlet.LOG.config("ユーザ・トップ画面へリダイレクト処理開始");\r
+\r
+        resp.sendRedirect("/m/user/" + loginLogic.getLoginId() + "/top");\r
+\r
+        LoginServlet.LOG.config("ユーザ・トップ画面へリダイレクト処理終了");\r
+\r
+        LoginServlet.LOG.config("ログイン処理終了");\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/RegistFinishServlet.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/RegistFinishServlet.java
new file mode 100644 (file)
index 0000000..57d1420
--- /dev/null
@@ -0,0 +1,19 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.web.servlet.mobile;\r
+\r
+import java.io.IOException;\r
+\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServlet;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+@SuppressWarnings("serial")\r
+public class RegistFinishServlet extends HttpServlet {\r
+\r
+    @Override\r
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\r
+        req.getRequestDispatcher("/WEB-INF/page/mobile/regist_finish.jsp").forward(req, resp);\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/RegistServlet.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/RegistServlet.java
new file mode 100644 (file)
index 0000000..5e5cac6
--- /dev/null
@@ -0,0 +1,213 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.web.servlet.mobile;\r
+\r
+import java.io.IOException;\r
+import java.util.Date;\r
+import java.util.TimeZone;\r
+import java.util.logging.Logger;\r
+import java.util.regex.Pattern;\r
+\r
+import javax.jdo.PersistenceManager;\r
+import javax.jdo.Transaction;\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServlet;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+import javax.servlet.http.HttpSession;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.dao.AccountEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.EntityStateEnum;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.PMF;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.TempAccountDao;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.TempAccountEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.UserDao;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.UserEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.util.DateUtil;\r
+import jp.gr.java_conf.u6k.money_notebook.util.HashUtil;\r
+\r
+@SuppressWarnings("serial")\r
+public class RegistServlet extends HttpServlet {\r
+\r
+    private static final Logger LOG = Logger.getLogger(RegistServlet.class.getName());\r
+\r
+    @Override\r
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\r
+        RegistServlet.LOG.config("会員登録初期化処理開始");\r
+\r
+        // パラメータを取得する。\r
+        RegistServlet.LOG.config("パラメータ取得処理開始");\r
+\r
+        long id = Long.parseLong(req.getParameter("id"));\r
+\r
+        RegistServlet.LOG.config("ユーザID: " + id);\r
+\r
+        RegistServlet.LOG.config("パラメータ取得処理終了");\r
+\r
+        // ユーザが存在するかチェック。存在しない場合、エラーとする。\r
+        RegistServlet.LOG.config("ユーザ存在チェック処理開始");\r
+\r
+        TempAccountEntity tempAccount;\r
+\r
+        PersistenceManager pm = PMF.get().getPersistenceManager();\r
+        try {\r
+            UserDao userDao = new UserDao(pm);\r
+            UserEntity user = userDao.findById(id);\r
+\r
+            if (user == null) {\r
+                throw new ServletException("ユーザID: " + id + "のユーザは存在しません。");\r
+            }\r
+\r
+            TempAccountDao tempAccountDao = new TempAccountDao(pm);\r
+            tempAccount = tempAccountDao.findByUser(user);\r
+\r
+            if (tempAccount == null) {\r
+                throw new ServletException("一時アカウントが存在しません。");\r
+            }\r
+        } finally {\r
+            pm.close();\r
+        }\r
+\r
+        RegistServlet.LOG.config("ユーザ存在チェック処理終了");\r
+\r
+        // 登録ページを表示する。\r
+        RegistServlet.LOG.config("フォワード処理開始");\r
+\r
+        HttpSession session = req.getSession();\r
+        session.setAttribute("id", id);\r
+        session.setAttribute("email", tempAccount.getEmail());\r
+\r
+        req.setAttribute("message", "");\r
+\r
+        this.getServletContext().getRequestDispatcher("/WEB-INF/page/mobile/regist.jsp").forward(req, resp);\r
+\r
+        RegistServlet.LOG.config("フォワード処理終了");\r
+\r
+        RegistServlet.LOG.config("会員登録初期化処理終了");\r
+    }\r
+\r
+    @Override\r
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\r
+        RegistServlet.LOG.config("会員登録登録処理開始");\r
+\r
+        TimeZone tz = DateUtil.getUserTimeZone();\r
+        Date updateDatetime = DateUtil.getNow(tz);\r
+\r
+        PersistenceManager pm = PMF.get().getPersistenceManager();\r
+        try {\r
+            Transaction tx = pm.currentTransaction();\r
+            try {\r
+                tx.begin();\r
+\r
+                // パラメータを取得する。\r
+                RegistServlet.LOG.config("パラメータ取得処理開始");\r
+\r
+                HttpSession session = req.getSession();\r
+                long id = (Long) session.getAttribute("id");\r
+\r
+                long reqId = Long.parseLong(req.getParameter("id"));\r
+\r
+                RegistServlet.LOG.config("ユーザID: " + id);\r
+                RegistServlet.LOG.config("ユーザID(パラメータ): " + reqId);\r
+\r
+                RegistServlet.LOG.config("パラメータ取得処理終了");\r
+\r
+                // ユーザ、一時アカウントを取得する。\r
+                RegistServlet.LOG.config("ユーザ取得処理開始");\r
+\r
+                UserDao userDao = new UserDao(pm);\r
+                UserEntity user = userDao.findById(id);\r
+\r
+                if (user == null) {\r
+                    throw new ServletException("ユーザID: " + id + "のユーザは存在しません。");\r
+                }\r
+\r
+                TempAccountDao tempAccountDao = new TempAccountDao(pm);\r
+                TempAccountEntity tempAccount = tempAccountDao.findByUser(user);\r
+\r
+                if (tempAccount == null) {\r
+                    throw new ServletException("一時アカウントが存在しません。");\r
+                }\r
+\r
+                RegistServlet.LOG.config("ユーザ取得処理終了");\r
+\r
+                // パラメータを取得して、入力チェックを行う。\r
+                RegistServlet.LOG.config("入力チェック処理開始");\r
+\r
+                String password1 = req.getParameter("password1");\r
+                String password2 = req.getParameter("password2");\r
+\r
+                String message = null;\r
+\r
+                final String PASSWORD_PATTERN = "^[0-9a-zA-Z]{7,}$";\r
+\r
+                if (password1 == null || "".equals(password1) || password2 == null || "".equals(password2)) {\r
+                    message = "パスワードを入力してください。";\r
+                    RegistServlet.LOG.config("入力チェック失敗: " + message);\r
+                }\r
+\r
+                if (message == null && (!Pattern.matches(PASSWORD_PATTERN, password1) || !Pattern.matches(PASSWORD_PATTERN, password2))) {\r
+                    message = "パスワードは英数字7文字以上を入力してください。";\r
+                    RegistServlet.LOG.config("入力チェック失敗: " + message);\r
+                }\r
+\r
+                if (message == null && !password1.equals(password2)) {\r
+                    message = "2つのパスワードが一致しません。もう一度入力してください。";\r
+                    RegistServlet.LOG.config("入力チェック失敗: " + message);\r
+                }\r
+\r
+                if (message != null) {\r
+                    // 入力チェックに失敗したので、ページを再表示する。\r
+                    RegistServlet.LOG.config("入力チェック処理失敗による再フォワード開始");\r
+\r
+                    req.setAttribute("message", message);\r
+\r
+                    this.getServletContext().getRequestDispatcher("/WEB-INF/page/mobile/regist.jsp").forward(req, resp);\r
+\r
+                    RegistServlet.LOG.config("入力チェック処理失敗による再フォワード終了");\r
+\r
+                    return;\r
+                }\r
+\r
+                RegistServlet.LOG.config("入力チェック処理終了");\r
+\r
+                // 登録する。\r
+                RegistServlet.LOG.config("アカウント登録、一時アカウント論理削除、処理開始");\r
+\r
+                String password = HashUtil.digest("SHA-512", password1);\r
+\r
+                AccountEntity account = new AccountEntity();\r
+                account.setUser(user);\r
+                account.setEmail(tempAccount.getEmail());\r
+                account.setPassword(password);\r
+                account.setUpdateDatetime(updateDatetime);\r
+\r
+                pm.makePersistent(account);\r
+\r
+                tempAccount.setUpdateDatetime(updateDatetime);\r
+                tempAccount.setEntityState(EntityStateEnum.DELETED);\r
+\r
+                pm.makePersistent(tempAccount);\r
+\r
+                RegistServlet.LOG.config("アカウント登録、一時アカウント論理削除、処理終了");\r
+\r
+                // 会員登録完了ページにリダイレクトする。\r
+                RegistServlet.LOG.config("会員登録完了ページにフォワード開始");\r
+\r
+                resp.sendRedirect("/m/regist/" + id + "/finish");\r
+\r
+                RegistServlet.LOG.config("会員登録完了ページにフォワード終了");\r
+\r
+                tx.commit();\r
+            } finally {\r
+                if (tx.isActive()) {\r
+                    tx.rollback();\r
+                }\r
+            }\r
+        } finally {\r
+            pm.close();\r
+        }\r
+\r
+        RegistServlet.LOG.config("会員登録登録処理終了");\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/user/DiaryServlet.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/user/DiaryServlet.java
new file mode 100644 (file)
index 0000000..9679984
--- /dev/null
@@ -0,0 +1,125 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.web.servlet.mobile.user;\r
+\r
+import java.io.IOException;\r
+import java.text.ParseException;\r
+import java.text.SimpleDateFormat;\r
+import java.util.ArrayList;\r
+import java.util.Calendar;\r
+import java.util.Collection;\r
+import java.util.Date;\r
+import java.util.List;\r
+\r
+import javax.jdo.PersistenceManager;\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServlet;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+import javax.servlet.http.HttpSession;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.dao.MoneyDiaryDao;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.MoneyDiaryEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.PMF;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.UserDao;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.UserEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.util.DateUtil;\r
+import jp.gr.java_conf.u6k.money_notebook.util.MoneyDiaryForm;\r
+\r
+@SuppressWarnings("serial")\r
+public class DiaryServlet extends HttpServlet {\r
+\r
+    @Override\r
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\r
+        String mode = req.getParameter("mode");\r
+\r
+        if ("daily".equals(mode)) {\r
+            this.executeDaily(req);\r
+            req.getRequestDispatcher("/WEB-INF/page/mobile/user/diary_daily.jsp").forward(req, resp);\r
+        } else if ("detail".equals(mode)) {\r
+            this.executeDetail(req);\r
+            req.getRequestDispatcher("/WEB-INF/page/mobile/user/diary_detail.jsp").forward(req, resp);\r
+        } else {\r
+            throw new ServletException();\r
+        }\r
+    }\r
+\r
+    private void executeDaily(HttpServletRequest req) throws ServletException {\r
+        HttpSession session = req.getSession();\r
+        long id = (Long) session.getAttribute("id");\r
+\r
+        String reqBegin = req.getParameter("begin");\r
+        String reqEnd = req.getParameter("end");\r
+\r
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");\r
+        formatter.setTimeZone(DateUtil.getUserTimeZone());\r
+\r
+        Date beginDate;\r
+        Date endDate;\r
+        try {\r
+            beginDate = formatter.parse(reqBegin);\r
+            endDate = formatter.parse(reqEnd);\r
+        } catch (ParseException e) {\r
+            throw new ServletException(e);\r
+        }\r
+        endDate = DateUtil.addCalendar(endDate, Calendar.DATE, 1, DateUtil.getUserTimeZone());\r
+\r
+        PersistenceManager pm = PMF.get().getPersistenceManager();\r
+        try {\r
+            UserDao userDao = new UserDao(pm);\r
+            UserEntity user = userDao.findById(id);\r
+\r
+            MoneyDiaryDao moneyDiaryDao = new MoneyDiaryDao(pm);\r
+            List<MoneyDiaryEntity> moneyDiaryList = moneyDiaryDao.findByUserAndDiaryDateBetween(user, beginDate, endDate);\r
+            Collection<MoneyDiaryEntity> moneyDiaryCol = pm.detachCopyAll(moneyDiaryList);\r
+\r
+            req.setAttribute("moneyDiaryList", moneyDiaryCol);\r
+        } finally {\r
+            pm.close();\r
+        }\r
+    }\r
+\r
+    private void executeDetail(HttpServletRequest req) throws ServletException, IOException {\r
+        HttpSession session = req.getSession();\r
+        long id = (Long) session.getAttribute("id");\r
+\r
+        String reqBegin = req.getParameter("begin");\r
+        String reqEnd = req.getParameter("end");\r
+\r
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");\r
+        formatter.setTimeZone(DateUtil.getUserTimeZone());\r
+\r
+        Date beginDate;\r
+        Date endDate;\r
+        try {\r
+            beginDate = formatter.parse(reqBegin);\r
+            endDate = formatter.parse(reqEnd);\r
+        } catch (ParseException e) {\r
+            throw new ServletException(e);\r
+        }\r
+        endDate = DateUtil.addCalendar(endDate, Calendar.DATE, 1, DateUtil.getUserTimeZone());\r
+\r
+        List<MoneyDiaryForm> moneyDiaryFormList = new ArrayList<MoneyDiaryForm>();\r
+\r
+        PersistenceManager pm = PMF.get().getPersistenceManager();\r
+        try {\r
+            UserDao userDao = new UserDao(pm);\r
+            UserEntity user = userDao.findById(id);\r
+\r
+            MoneyDiaryDao moneyDiaryDao = new MoneyDiaryDao(pm);\r
+            List<MoneyDiaryEntity> moneyDiaryList = moneyDiaryDao.findByUserAndDiaryDateBetween(user, beginDate, endDate);\r
+\r
+            for (MoneyDiaryEntity moneyDiary : moneyDiaryList) {\r
+                MoneyDiaryForm moneyDiaryForm = new MoneyDiaryForm();\r
+                moneyDiaryForm.setDiaryDate(moneyDiary.getDiaryDate());\r
+                moneyDiaryForm.setText(moneyDiary.getText());\r
+\r
+                moneyDiaryFormList.add(moneyDiaryForm);\r
+            }\r
+\r
+            req.setAttribute("moneyDiaryFormList", moneyDiaryFormList);\r
+        } finally {\r
+            pm.close();\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/user/TopServlet.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/user/TopServlet.java
new file mode 100644 (file)
index 0000000..9e008b6
--- /dev/null
@@ -0,0 +1,122 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.web.servlet.mobile.user;\r
+\r
+import java.io.IOException;\r
+import java.util.Calendar;\r
+import java.util.Date;\r
+import java.util.List;\r
+import java.util.TimeZone;\r
+import java.util.logging.Logger;\r
+\r
+import javax.jdo.PersistenceManager;\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServlet;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+import javax.servlet.http.HttpSession;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.dao.MoneyDiaryDao;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.MoneyDiaryEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.PMF;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.UserDao;\r
+import jp.gr.java_conf.u6k.money_notebook.dao.UserEntity;\r
+import jp.gr.java_conf.u6k.money_notebook.util.DateUtil;\r
+import jp.gr.java_conf.u6k.money_notebook.util.MoneyDiaryForm;\r
+\r
+@SuppressWarnings("serial")\r
+public class TopServlet extends HttpServlet {\r
+\r
+    // TODO ログインユーザと別のユーザーのトップを表示しようとした場合、「そのユーザーはお小遣い帳を公開していません」エラーとする。\r
+    // TODO 当日の合計支出、先日の合計支出、今週の合計支出、先週の合計支出、今月の合計支出、先月の合計支出を表示する。明細はその先のページで表示する。\r
+    // TODO ログアウトを作る。\r
+\r
+    private static final Logger LOG = Logger.getLogger(TopServlet.class.getName());\r
+\r
+    @Override\r
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\r
+        TopServlet.LOG.config("ユーザ・トップ画面表示処理開始");\r
+\r
+        HttpSession session = req.getSession();\r
+\r
+        long reqId = Long.parseLong(req.getParameter("id"));\r
+        long id = (Long) session.getAttribute("id");\r
+\r
+        if (reqId != id) {\r
+            resp.setContentType("text/plain");\r
+            resp.getWriter().println("reqId != id");\r
+\r
+            TopServlet.LOG.severe("reqId != id");\r
+\r
+            return;\r
+        }\r
+\r
+        PersistenceManager pm = PMF.get().getPersistenceManager();\r
+        try {\r
+            UserDao userDao = new UserDao(pm);\r
+            UserEntity user = userDao.findById(id);\r
+\r
+            TimeZone tz = DateUtil.getUserTimeZone();\r
+\r
+            // 今日の収支明細を取得する。\r
+            Date diaryDateBegin = DateUtil.getToday(DateUtil.getNow(tz), tz);\r
+            Date diaryDateEnd = DateUtil.addCalendar(diaryDateBegin, Calendar.DATE, 1, tz);\r
+\r
+            MoneyDiaryDao moneyDiaryDao = new MoneyDiaryDao(pm);\r
+            List<MoneyDiaryEntity> moneyDiaryList = moneyDiaryDao.findByUserAndDiaryDateBetween(user, diaryDateBegin, diaryDateEnd);\r
+\r
+            MoneyDiaryForm moneyDiaryForm = new MoneyDiaryForm();\r
+\r
+            if (moneyDiaryList.size() == 0) {\r
+                moneyDiaryForm.setDiaryDate(diaryDateBegin);\r
+            } else {\r
+                MoneyDiaryEntity moneyDiary = moneyDiaryList.get(0);\r
+\r
+                moneyDiaryForm.setDiaryDate(moneyDiary.getDiaryDate());\r
+                moneyDiaryForm.setText(moneyDiary.getText());\r
+            }\r
+\r
+            req.setAttribute("moneyDiaryForm", moneyDiaryForm);\r
+\r
+            // 今週の収支合計を算出する。\r
+            Date weekStartDate = DateUtil.getWeekStart(diaryDateBegin, tz);\r
+            Date weekEndDate = DateUtil.addCalendar(weekStartDate, Calendar.DATE, 7, tz);\r
+\r
+            moneyDiaryList = moneyDiaryDao.findByUserAndDiaryDateBetween(user, weekStartDate, weekEndDate);\r
+\r
+            long totalMoneyThisWeek = 0;\r
+            for (MoneyDiaryEntity d : moneyDiaryList) {\r
+                totalMoneyThisWeek += d.getMoney();\r
+            }\r
+\r
+            weekEndDate = DateUtil.addCalendar(weekEndDate, Calendar.DATE, -1, tz);\r
+\r
+            req.setAttribute("weekStartDate", weekStartDate);\r
+            req.setAttribute("weekEndDate", weekEndDate);\r
+            req.setAttribute("totalMoneyThisWeek", totalMoneyThisWeek);\r
+\r
+            // 今月の収支合計を算出する。\r
+            Date monthStartDate = DateUtil.getMonthStart(diaryDateBegin, tz);\r
+            Date monthEndDate = DateUtil.addCalendar(monthStartDate, Calendar.MONTH, 1, tz);\r
+\r
+            moneyDiaryList = moneyDiaryDao.findByUserAndDiaryDateBetween(user, monthStartDate, monthEndDate);\r
+\r
+            long totalMoneyThisMonth = 0;\r
+            for (MoneyDiaryEntity d : moneyDiaryList) {\r
+                totalMoneyThisMonth += d.getMoney();\r
+            }\r
+\r
+            monthEndDate = DateUtil.addCalendar(monthEndDate, Calendar.DATE, -1, tz);\r
+\r
+            req.setAttribute("monthStartDate", monthStartDate);\r
+            req.setAttribute("monthEndDate", monthEndDate);\r
+            req.setAttribute("totalMoneyThisMonth", totalMoneyThisMonth);\r
+        } finally {\r
+            pm.close();\r
+        }\r
+\r
+        req.getRequestDispatcher("/WEB-INF/page/mobile/user/top.jsp").forward(req, resp);\r
+\r
+        TopServlet.LOG.config("ユーザ・トップ画面表示処理終了");\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/user/TutorialServlet.java b/money-notebook/src/jp/gr/java_conf/u6k/money_notebook/web/servlet/mobile/user/TutorialServlet.java
new file mode 100644 (file)
index 0000000..d713f74
--- /dev/null
@@ -0,0 +1,20 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.web.servlet.mobile.user;\r
+\r
+import java.io.IOException;\r
+\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServlet;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+@SuppressWarnings("serial")\r
+public class TutorialServlet extends HttpServlet {\r
+\r
+    @Override\r
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\r
+        resp.setContentType("text/plain");\r
+        resp.getWriter().println("tutorial");\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/src/log4j.properties b/money-notebook/src/log4j.properties
new file mode 100644 (file)
index 0000000..d9c3edc
--- /dev/null
@@ -0,0 +1,24 @@
+# A default log4j configuration for log4j users.
+#
+# To use this configuration, deploy it into your application's WEB-INF/classes
+# directory.  You are also encouraged to edit it as you like.
+
+# Configure the console as our one appender
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c] - %m%n
+
+# tighten logging on the DataNucleus Categories
+log4j.category.DataNucleus.JDO=WARN, A1
+log4j.category.DataNucleus.Persistence=WARN, A1
+log4j.category.DataNucleus.Cache=WARN, A1
+log4j.category.DataNucleus.MetaData=WARN, A1
+log4j.category.DataNucleus.General=WARN, A1
+log4j.category.DataNucleus.Utility=WARN, A1
+log4j.category.DataNucleus.Transaction=WARN, A1
+log4j.category.DataNucleus.Datastore=WARN, A1
+log4j.category.DataNucleus.ClassLoading=WARN, A1
+log4j.category.DataNucleus.Plugin=WARN, A1
+log4j.category.DataNucleus.ValueGeneration=WARN, A1
+log4j.category.DataNucleus.Enhancer=WARN, A1
+log4j.category.DataNucleus.SchemaTool=WARN, A1
diff --git a/money-notebook/src_test/jp/gr/java_conf/u6k/money_notebook/test/util/DateUtilTest.java b/money-notebook/src_test/jp/gr/java_conf/u6k/money_notebook/test/util/DateUtilTest.java
new file mode 100644 (file)
index 0000000..5204c95
--- /dev/null
@@ -0,0 +1,137 @@
+\r
+package jp.gr.java_conf.u6k.money_notebook.test.util;\r
+\r
+import java.util.Calendar;\r
+import java.util.Date;\r
+import java.util.TimeZone;\r
+\r
+import jp.gr.java_conf.u6k.money_notebook.util.DateUtil;\r
+\r
+import org.junit.Assert;\r
+import org.junit.Test;\r
+\r
+public class DateUtilTest {\r
+\r
+    @Test\r
+    public void getUserTimeZone() {\r
+        TimeZone tz = DateUtil.getUserTimeZone();\r
+\r
+        Assert.assertEquals("Asia/Tokyo", tz.getID());\r
+    }\r
+\r
+    @Test\r
+    public void getNow() {\r
+        TimeZone tz = DateUtil.getUserTimeZone();\r
+        Date a = DateUtil.getNow(tz);\r
+        Date b = new Date();\r
+\r
+        Assert.assertTrue(Math.abs(a.getTime() - b.getTime()) < 100);\r
+    }\r
+\r
+    @Test\r
+    public void getToday() {\r
+        TimeZone tz = DateUtil.getUserTimeZone();\r
+\r
+        Calendar c = Calendar.getInstance();\r
+        c.set(Calendar.YEAR, 2010);\r
+        c.set(Calendar.MONTH, 6);\r
+        c.set(Calendar.DAY_OF_MONTH, 20);\r
+\r
+        Date d = DateUtil.getToday(c.getTime(), tz);\r
+        c.setTime(d);\r
+\r
+        Assert.assertEquals(2010, c.get(Calendar.YEAR));\r
+        Assert.assertEquals(6, c.get(Calendar.MONTH));\r
+        Assert.assertEquals(20, c.get(Calendar.DAY_OF_MONTH));\r
+        Assert.assertEquals(0, c.get(Calendar.HOUR_OF_DAY));\r
+        Assert.assertEquals(0, c.get(Calendar.MINUTE));\r
+        Assert.assertEquals(0, c.get(Calendar.SECOND));\r
+        Assert.assertEquals(0, c.get(Calendar.MILLISECOND));\r
+    }\r
+\r
+    @Test\r
+    public void getWeekStart() {\r
+        TimeZone tz = DateUtil.getUserTimeZone();\r
+\r
+        Calendar c = Calendar.getInstance();\r
+        c.set(Calendar.YEAR, 2010);\r
+        c.set(Calendar.MONTH, 6);\r
+        c.set(Calendar.DAY_OF_MONTH, 20);\r
+\r
+        Date d = DateUtil.getWeekStart(c.getTime(), tz);\r
+        c.setTime(d);\r
+\r
+        Assert.assertEquals(2010, c.get(Calendar.YEAR));\r
+        Assert.assertEquals(6, c.get(Calendar.MONTH));\r
+        Assert.assertEquals(18, c.get(Calendar.DAY_OF_MONTH));\r
+        Assert.assertEquals(0, c.get(Calendar.HOUR_OF_DAY));\r
+        Assert.assertEquals(0, c.get(Calendar.MINUTE));\r
+        Assert.assertEquals(0, c.get(Calendar.SECOND));\r
+        Assert.assertEquals(0, c.get(Calendar.MILLISECOND));\r
+    }\r
+\r
+    @Test\r
+    public void getMonthStart() {\r
+        TimeZone tz = DateUtil.getUserTimeZone();\r
+\r
+        Calendar c = Calendar.getInstance();\r
+        c.set(Calendar.YEAR, 2010);\r
+        c.set(Calendar.MONTH, 6);\r
+        c.set(Calendar.DAY_OF_MONTH, 20);\r
+\r
+        Date d = DateUtil.getMonthStart(c.getTime(), tz);\r
+        c.setTime(d);\r
+\r
+        Assert.assertEquals(2010, c.get(Calendar.YEAR));\r
+        Assert.assertEquals(6, c.get(Calendar.MONTH));\r
+        Assert.assertEquals(1, c.get(Calendar.DAY_OF_MONTH));\r
+        Assert.assertEquals(0, c.get(Calendar.HOUR_OF_DAY));\r
+        Assert.assertEquals(0, c.get(Calendar.MINUTE));\r
+        Assert.assertEquals(0, c.get(Calendar.SECOND));\r
+        Assert.assertEquals(0, c.get(Calendar.MILLISECOND));\r
+    }\r
+\r
+    @Test\r
+    public void addCalendar() {\r
+        TimeZone tz = DateUtil.getUserTimeZone();\r
+\r
+        Calendar c = Calendar.getInstance();\r
+        c.set(Calendar.YEAR, 2010);\r
+        c.set(Calendar.MONTH, 6);\r
+        c.set(Calendar.DAY_OF_MONTH, 20);\r
+\r
+        Date d = DateUtil.getToday(c.getTime(), tz);\r
+        c.setTime(d);\r
+\r
+        Assert.assertEquals(2010, c.get(Calendar.YEAR));\r
+        Assert.assertEquals(6, c.get(Calendar.MONTH));\r
+        Assert.assertEquals(20, c.get(Calendar.DAY_OF_MONTH));\r
+        Assert.assertEquals(0, c.get(Calendar.HOUR_OF_DAY));\r
+        Assert.assertEquals(0, c.get(Calendar.MINUTE));\r
+        Assert.assertEquals(0, c.get(Calendar.SECOND));\r
+        Assert.assertEquals(0, c.get(Calendar.MILLISECOND));\r
+\r
+        d = DateUtil.addCalendar(d, Calendar.DAY_OF_YEAR, 7, tz);\r
+        c.setTime(d);\r
+\r
+        Assert.assertEquals(2010, c.get(Calendar.YEAR));\r
+        Assert.assertEquals(6, c.get(Calendar.MONTH));\r
+        Assert.assertEquals(27, c.get(Calendar.DAY_OF_MONTH));\r
+        Assert.assertEquals(0, c.get(Calendar.HOUR_OF_DAY));\r
+        Assert.assertEquals(0, c.get(Calendar.MINUTE));\r
+        Assert.assertEquals(0, c.get(Calendar.SECOND));\r
+        Assert.assertEquals(0, c.get(Calendar.MILLISECOND));\r
+\r
+        d = DateUtil.addCalendar(d, Calendar.DAY_OF_YEAR, 7, tz);\r
+        c.setTime(d);\r
+\r
+        Assert.assertEquals(2010, c.get(Calendar.YEAR));\r
+        Assert.assertEquals(7, c.get(Calendar.MONTH));\r
+        Assert.assertEquals(3, c.get(Calendar.DAY_OF_MONTH));\r
+        Assert.assertEquals(0, c.get(Calendar.HOUR_OF_DAY));\r
+        Assert.assertEquals(0, c.get(Calendar.MINUTE));\r
+        Assert.assertEquals(0, c.get(Calendar.SECOND));\r
+        Assert.assertEquals(0, c.get(Calendar.MILLISECOND));\r
+    }\r
+\r
+}\r
diff --git a/money-notebook/war/WEB-INF/.gitignore b/money-notebook/war/WEB-INF/.gitignore
new file mode 100644 (file)
index 0000000..e3a0a0d
--- /dev/null
@@ -0,0 +1,2 @@
+\r
+classes
\ No newline at end of file
diff --git a/money-notebook/war/WEB-INF/appengine-web.xml b/money-notebook/war/WEB-INF/appengine-web.xml
new file mode 100644 (file)
index 0000000..2a3c4e2
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<appengine-web-app
+    xmlns="http://appengine.google.com/ns/1.0">
+
+    <application>money-notebook</application>
+    <version>1</version>
+
+    <!-- Configure java.util.logging -->
+    <system-properties>
+        <property
+            name="java.util.logging.config.file"
+            value="WEB-INF/logging.properties" />
+    </system-properties>
+    
+    <sessions-enabled>true</sessions-enabled>
+
+    <inbound-services>
+        <service>mail</service>
+    </inbound-services>
+
+</appengine-web-app>
diff --git a/money-notebook/war/WEB-INF/datastore-indexes.xml b/money-notebook/war/WEB-INF/datastore-indexes.xml
new file mode 100644 (file)
index 0000000..bade366
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<datastore-indexes\r
+    autoGenerate="true">\r
+\r
+    <datastore-index\r
+        kind="MoneyDiaryEntity"\r
+        ancestor="true"\r
+        source="manual">\r
+        <property\r
+            name="moneyDiaryList_INTEGER_IDX"\r
+            direction="asc" />\r
+    </datastore-index>\r
+\r
+</datastore-indexes>\r
diff --git a/money-notebook/war/WEB-INF/lib/.gitignore b/money-notebook/war/WEB-INF/lib/.gitignore
new file mode 100644 (file)
index 0000000..057b56e
--- /dev/null
@@ -0,0 +1,10 @@
+\r
+appengine-api-1.0-sdk-1.3.0.jar\r
+appengine-api-labs-1.3.0.jar\r
+datanucleus-appengine-1.0.4.1.final.jar\r
+datanucleus-core-1.1.5.jar\r
+datanucleus-jpa-1.1.5.jar\r
+geronimo-jpa_3.0_spec-1.1.1.jar\r
+geronimo-jta_1.1_spec-1.1.1.jar\r
+gwt-servlet.jar\r
+jdo2-api-2.3-eb.jar
\ No newline at end of file
diff --git a/money-notebook/war/WEB-INF/lib/jsonic-1.2.0.jar b/money-notebook/war/WEB-INF/lib/jsonic-1.2.0.jar
new file mode 100644 (file)
index 0000000..09f9bec
Binary files /dev/null and b/money-notebook/war/WEB-INF/lib/jsonic-1.2.0.jar differ
diff --git a/money-notebook/war/WEB-INF/lib/urlrewrite-3.2.0.jar b/money-notebook/war/WEB-INF/lib/urlrewrite-3.2.0.jar
new file mode 100644 (file)
index 0000000..214518b
Binary files /dev/null and b/money-notebook/war/WEB-INF/lib/urlrewrite-3.2.0.jar differ
diff --git a/money-notebook/war/WEB-INF/logging.properties b/money-notebook/war/WEB-INF/logging.properties
new file mode 100644 (file)
index 0000000..a01c7c1
--- /dev/null
@@ -0,0 +1,28 @@
+# A default java.util.logging configuration.
+# (All App Engine logging is through java.util.logging by default).
+#
+# To use this configuration, copy it into your application's WEB-INF
+# folder and add the following to your appengine-web.xml:
+# 
+# <system-properties>
+#   <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
+# </system-properties>
+#
+
+# Set the default logging level for all loggers to WARNING
+.level = CONFIG
+
+# Set the default logging level for ORM, specifically, to WARNING
+DataNucleus.JDO.level=WARNING
+DataNucleus.Persistence.level=WARNING
+DataNucleus.Cache.level=WARNING
+DataNucleus.MetaData.level=WARNING
+DataNucleus.General.level=WARNING
+DataNucleus.Utility.level=WARNING
+DataNucleus.Transaction.level=WARNING
+DataNucleus.Datastore.level=WARNING
+DataNucleus.ClassLoading.level=WARNING
+DataNucleus.Plugin.level=WARNING
+DataNucleus.ValueGeneration.level=WARNING
+DataNucleus.Enhancer.level=WARNING
+DataNucleus.SchemaTool.level=WARNING
diff --git a/money-notebook/war/WEB-INF/page/mobile/index.jsp b/money-notebook/war/WEB-INF/page/mobile/index.jsp
new file mode 100644 (file)
index 0000000..be759b0
--- /dev/null
@@ -0,0 +1,37 @@
+<%@ page contentType="text/html; charset=UTF-8"\r
+         pageEncoding="UTF-8" %>\r
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>\r
+<%\r
+    response.setDateHeader("Date", System.currentTimeMillis());\r
+    response.setDateHeader("Expires", 0);\r
+    response.setHeader("Pragma", "no-cache");\r
+    response.setHeader("Cache-Control", "no-cache");\r
+    response.addHeader("Cache-Control", "no-store");\r
+    response.addHeader("Cache-Control", "max-age=0");\r
+%>\r
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\r
+<html>\r
+    <head>\r
+        <meta http-equiv="content-type" content="text/html; charset=UTF-8">\r
+        <meta http-equiv="content-language" content="ja">\r
+        <meta http-equiv="content-style-type" content="text/css">\r
+        <meta http-equiv="content-script-type" content="text/javascript">\r
+        <meta http-equiv="pragma" content="no-cache">\r
+        <meta http-equiv="cache-control" content="no-cache">\r
+        <meta http-equiv="expires" content="0">\r
+        <meta name="author" content="u6k.yu1@gmail.com">\r
+        <meta name="copyright" content="Copyright (C) 2010 u6k.yu1@gmail.com All rights reserved.">\r
+        <meta name="keywords" content="小遣い,家計簿" lang="ja">\r
+        <meta name="description" content="小遣い帳サービス。">\r
+        <meta name="robots" content="nofollow">\r
+        <title>小遣い帳(仮)</title>\r
+    </head>\r
+    <body>\r
+        <h1>小遣い帳(仮)</h1>\r
+        \r
+        <ul>\r
+            <li>会員登録するには、<a href="mailto:regist@money-notebook.appspotmail.com">regist@money-notebook.appspotmail.com</a>に空メールを送ってください。</li>\r
+            <li><a href="<c:url value="/m/login" />">ログイン</a></li>\r
+        </ul>\r
+    </body>\r
+</html>\r
diff --git a/money-notebook/war/WEB-INF/page/mobile/login.jsp b/money-notebook/war/WEB-INF/page/mobile/login.jsp
new file mode 100644 (file)
index 0000000..c3da496
--- /dev/null
@@ -0,0 +1,42 @@
+<%@ page contentType="text/html; charset=UTF-8"\r
+         pageEncoding="UTF-8" %>\r
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>\r
+<%\r
+    response.setDateHeader("Date", System.currentTimeMillis());\r
+    response.setDateHeader("Expires", 0);\r
+    response.setHeader("Pragma", "no-cache");\r
+    response.setHeader("Cache-Control", "no-cache");\r
+    response.addHeader("Cache-Control", "no-store");\r
+    response.addHeader("Cache-Control", "max-age=0");\r
+%>\r
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\r
+<html>\r
+    <head>\r
+        <meta http-equiv="content-type" content="text/html; charset=UTF-8">\r
+        <meta http-equiv="content-language" content="ja">\r
+        <meta http-equiv="content-style-type" content="text/css">\r
+        <meta http-equiv="content-script-type" content="text/javascript">\r
+        <meta http-equiv="pragma" content="no-cache">\r
+        <meta http-equiv="cache-control" content="no-cache">\r
+        <meta http-equiv="expires" content="0">\r
+        <meta name="author" content="u6k.yu1@gmail.com">\r
+        <meta name="copyright" content="Copyright (C) 2010 u6k.yu1@gmail.com All rights reserved.">\r
+        <meta name="keywords" content="小遣い,家計簿" lang="ja">\r
+        <meta name="description" content="小遣い帳サービス。">\r
+        <meta name="robots" content="nofollow">\r
+        <title>ログイン - 小遣い帳(仮)</title>\r
+    </head>\r
+    <body>\r
+        <h1>小遣い帳(仮)</h1>\r
+        <h2>ログイン</h2>\r
+        \r
+        <p><c:out value="${requestScope.message}" /></p>\r
+        <form action="<c:url value="/m/login" />" method="post">\r
+            メールアドレス<br>\r
+            <input type="text" id="email" name="email" value="<c:out value="${requestScope.email}" />"><br>\r
+            パスワード<br>\r
+            <input type="password" id="password" name="password" /><br>\r
+            <input type="submit" value="登録">\r
+        </form>\r
+    </body>\r
+</html>\r
diff --git a/money-notebook/war/WEB-INF/page/mobile/regist.jsp b/money-notebook/war/WEB-INF/page/mobile/regist.jsp
new file mode 100644 (file)
index 0000000..c57dae8
--- /dev/null
@@ -0,0 +1,44 @@
+<%@ page contentType="text/html; charset=UTF-8"\r
+         pageEncoding="UTF-8" %>\r
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>\r
+<%\r
+    response.setDateHeader("Date", System.currentTimeMillis());\r
+    response.setDateHeader("Expires", 0);\r
+    response.setHeader("Pragma", "no-cache");\r
+    response.setHeader("Cache-Control", "no-cache");\r
+    response.addHeader("Cache-Control", "no-store");\r
+    response.addHeader("Cache-Control", "max-age=0");\r
+%>\r
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\r
+<html>\r
+    <head>\r
+        <meta http-equiv="content-type" content="text/html; charset=UTF-8">\r
+        <meta http-equiv="content-language" content="ja">\r
+        <meta http-equiv="content-style-type" content="text/css">\r
+        <meta http-equiv="content-script-type" content="text/javascript">\r
+        <meta http-equiv="pragma" content="no-cache">\r
+        <meta http-equiv="cache-control" content="no-cache">\r
+        <meta http-equiv="expires" content="0">\r
+        <meta name="author" content="u6k.yu1@gmail.com">\r
+        <meta name="copyright" content="Copyright (C) 2010 u6k.yu1@gmail.com All rights reserved.">\r
+        <meta name="keywords" content="小遣い,家計簿" lang="ja">\r
+        <meta name="description" content="小遣い帳サービス。">\r
+        <meta name="robots" content="nofollow">\r
+        <title>会員登録 - 小遣い帳(仮)</title>\r
+    </head>\r
+    <body>\r
+        <h1>小遣い帳(仮)</h1>\r
+        <h2>会員登録</h2>\r
+        \r
+        <p><c:out value="${sessionScope.email}" />様の会員登録を続行します。</p>\r
+        <p><c:out value="${requestScope.message}" /></p>\r
+        \r
+        <form action="<c:url value="/m/regist/${sessionScope.id}/" />" method="post">\r
+            パスワード<br>\r
+            <input type="password" id="password1" name="password1" /><br>\r
+            もう一度<br>\r
+            <input type="password" id="password2" name="password2" /><br>\r
+            <input type="submit" value="登録">\r
+        </form>\r
+    </body>\r
+</html>\r
diff --git a/money-notebook/war/WEB-INF/page/mobile/regist_finish.jsp b/money-notebook/war/WEB-INF/page/mobile/regist_finish.jsp
new file mode 100644 (file)
index 0000000..15c49b3
--- /dev/null
@@ -0,0 +1,45 @@
+<%@ page contentType="text/html; charset=UTF-8"\r
+         pageEncoding="UTF-8" %>\r
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>\r
+<%\r
+    response.setDateHeader("Date", System.currentTimeMillis());\r
+    response.setDateHeader("Expires", 0);\r
+    response.setHeader("Pragma", "no-cache");\r
+    response.setHeader("Cache-Control", "no-cache");\r
+    response.addHeader("Cache-Control", "no-store");\r
+    response.addHeader("Cache-Control", "max-age=0");\r
+%>\r
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\r
+<html>\r
+    <head>\r
+        <meta http-equiv="content-type" content="text/html; charset=UTF-8">\r
+        <meta http-equiv="content-language" content="ja">\r
+        <meta http-equiv="content-style-type" content="text/css">\r
+        <meta http-equiv="content-script-type" content="text/javascript">\r
+        <meta http-equiv="pragma" content="no-cache">\r
+        <meta http-equiv="cache-control" content="no-cache">\r
+        <meta http-equiv="expires" content="0">\r
+        <meta name="author" content="u6k.yu1@gmail.com">\r
+        <meta name="copyright" content="Copyright (C) 2010 u6k.yu1@gmail.com All rights reserved.">\r
+        <meta name="keywords" content="小遣い,家計簿" lang="ja">\r
+        <meta name="description" content="小遣い帳サービス。">\r
+        <meta name="robots" content="nofollow">\r
+        <title>会員登録完了 - 小遣い帳(仮)</title>\r
+    </head>\r
+    <body>\r
+        <h1>小遣い帳(仮)</h1>\r
+        <h2>会員登録完了</h2>\r
+        \r
+        <p>\r
+            <c:out value="${sessionScope.email}" />様の会員登録を完了しました。<br>\r
+            ようこそ! お小遣い帳(仮)を有効にご活用ください。<br>\r
+            チュートリアルでお小遣い帳(仮)の使い方を簡単に説明します。<br>\r
+            <br>\r
+            <a href="<c:url value="/m/user/${sessionScope.id}/tutorial" />">[ チュートリアルを開始する ]</a><br>\r
+            <br>\r
+            チュートリアルを飛ばしてお小遣い帳(仮)を使い始めるには、トップを表示します。(チュートリアルは後で開始することもできます)<br>\r
+            <br>\r
+            <a href="<c:url value="/m/user/${sessionScope.id}/top" />">[ トップを表示する ]</a>\r
+        </p>\r
+    </body>\r
+</html>\r
diff --git a/money-notebook/war/WEB-INF/page/mobile/user/diary_daily.jsp b/money-notebook/war/WEB-INF/page/mobile/user/diary_daily.jsp
new file mode 100644 (file)
index 0000000..e1de4ae
--- /dev/null
@@ -0,0 +1,43 @@
+<%@ page contentType="text/html; charset=UTF-8"\r
+         pageEncoding="UTF-8" %>\r
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>\r
+<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>\r
+<%\r
+    response.setDateHeader("Date", System.currentTimeMillis());\r
+    response.setDateHeader("Expires", 0);\r
+    response.setHeader("Pragma", "no-cache");\r
+    response.setHeader("Cache-Control", "no-cache");\r
+    response.addHeader("Cache-Control", "no-store");\r
+    response.addHeader("Cache-Control", "max-age=0");\r
+%>\r
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\r
+<html>\r
+    <head>\r
+        <meta http-equiv="content-type" content="text/html; charset=UTF-8">\r
+        <meta http-equiv="content-language" content="ja">\r
+        <meta http-equiv="content-style-type" content="text/css">\r
+        <meta http-equiv="content-script-type" content="text/javascript">\r
+        <meta http-equiv="pragma" content="no-cache">\r
+        <meta http-equiv="cache-control" content="no-cache">\r
+        <meta http-equiv="expires" content="0">\r
+        <meta name="author" content="u6k.yu1@gmail.com">\r
+        <meta name="copyright" content="Copyright (C) 2010 u6k.yu1@gmail.com All rights reserved.">\r
+        <meta name="keywords" content="小遣い,家計簿" lang="ja">\r
+        <meta name="description" content="小遣い帳サービス。">\r
+        <meta name="robots" content="nofollow">\r
+        <title>トップ - 小遣い帳(仮)</title>\r
+    </head>\r
+    <body>\r
+        <h1>小遣い帳(仮)</h1>\r
+        <h2>一覧(日毎)</h2>\r
+        <hr>\r
+        <table border="0">\r
+            <c:forEach items="${requestScope.moneyDiaryList}" var="moneyDiary">\r
+            <tr>\r
+                <td><fmt:formatDate value="${moneyDiary.diaryDate}" pattern="yyyy/MM/dd" timeZone="JST" /></td>\r
+                <td><c:out value="${moneyDiary.money}" />円</td>\r
+            </tr>\r
+            </c:forEach>\r
+        </table>\r
+    </body>\r
+</html>\r
diff --git a/money-notebook/war/WEB-INF/page/mobile/user/diary_detail.jsp b/money-notebook/war/WEB-INF/page/mobile/user/diary_detail.jsp
new file mode 100644 (file)
index 0000000..eb39054
--- /dev/null
@@ -0,0 +1,46 @@
+<%@ page contentType="text/html; charset=UTF-8"\r
+         pageEncoding="UTF-8" %>\r
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>\r
+<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>\r
+<%\r
+    response.setDateHeader("Date", System.currentTimeMillis());\r
+    response.setDateHeader("Expires", 0);\r
+    response.setHeader("Pragma", "no-cache");\r
+    response.setHeader("Cache-Control", "no-cache");\r
+    response.addHeader("Cache-Control", "no-store");\r
+    response.addHeader("Cache-Control", "max-age=0");\r
+%>\r
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\r
+<html>\r
+    <head>\r
+        <meta http-equiv="content-type" content="text/html; charset=UTF-8">\r
+        <meta http-equiv="content-language" content="ja">\r
+        <meta http-equiv="content-style-type" content="text/css">\r
+        <meta http-equiv="content-script-type" content="text/javascript">\r
+        <meta http-equiv="pragma" content="no-cache">\r
+        <meta http-equiv="cache-control" content="no-cache">\r
+        <meta http-equiv="expires" content="0">\r
+        <meta name="author" content="u6k.yu1@gmail.com">\r
+        <meta name="copyright" content="Copyright (C) 2010 u6k.yu1@gmail.com All rights reserved.">\r
+        <meta name="keywords" content="小遣い,家計簿" lang="ja">\r
+        <meta name="description" content="小遣い帳サービス。">\r
+        <meta name="robots" content="nofollow">\r
+        <title>トップ - 小遣い帳(仮)</title>\r
+    </head>\r
+    <body>\r
+        <h1>小遣い帳(仮)</h1>\r
+        <h2>一覧(詳細)</h2>\r
+        <c:forEach items="${requestScope.moneyDiaryFormList}" var="moneyDiaryForm">\r
+        <hr>\r
+        <h3><fmt:formatDate value="${moneyDiaryForm.diaryDate}" pattern="yyyy/MM/dd" timeZone="JST" />の一覧</h3>\r
+        <table border="0">\r
+            <c:forEach items="${moneyDiaryForm.itemList}" var="item">\r
+            <tr>\r
+                <td><c:out value="${item.item}" /></td>\r
+                <td><c:out value="${item.money}" />円</td>\r
+            </tr>\r
+            </c:forEach>\r
+        </table>\r
+        </c:forEach>\r
+    </body>\r
+</html>\r
diff --git a/money-notebook/war/WEB-INF/page/mobile/user/diary_monthly.jsp b/money-notebook/war/WEB-INF/page/mobile/user/diary_monthly.jsp
new file mode 100644 (file)
index 0000000..80955d9
--- /dev/null
@@ -0,0 +1,70 @@
+<%@ page contentType="text/html; charset=UTF-8"\r
+         pageEncoding="UTF-8" %>\r
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>\r
+<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>\r
+<%\r
+    response.setDateHeader("Date", System.currentTimeMillis());\r
+    response.setDateHeader("Expires", 0);\r
+    response.setHeader("Pragma", "no-cache");\r
+    response.setHeader("Cache-Control", "no-cache");\r
+    response.addHeader("Cache-Control", "no-store");\r
+    response.addHeader("Cache-Control", "max-age=0");\r
+%>\r
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\r
+<html>\r
+    <head>\r
+        <meta http-equiv="content-type" content="text/html; charset=UTF-8">\r
+        <meta http-equiv="content-language" content="ja">\r
+        <meta http-equiv="content-style-type" content="text/css">\r
+        <meta http-equiv="content-script-type" content="text/javascript">\r
+        <meta http-equiv="pragma" content="no-cache">\r
+        <meta http-equiv="cache-control" content="no-cache">\r
+        <meta http-equiv="expires" content="0">\r
+        <meta name="author" content="u6k.yu1@gmail.com">\r
+        <meta name="copyright" content="Copyright (C) 2010 u6k.yu1@gmail.com All rights reserved.">\r
+        <meta name="keywords" content="小遣い,家計簿" lang="ja">\r
+        <meta name="description" content="小遣い帳サービス。">\r
+        <meta name="robots" content="nofollow">\r
+        <title>トップ - 小遣い帳(仮)</title>\r
+    </head>\r
+    <body>\r
+        <h1>小遣い帳(仮)</h1>\r
+        <h2>トップ</h2>\r
+        <hr>\r
+        <h3>記帳メールアドレス</h3>\r
+        <p><input type="text" value="<c:out value="${sessionScope.id}" />@money-notebook.appspotmail.com"></p>\r
+        <hr>\r
+        <h3>収支合計</h3>\r
+        <p>\r
+            <table border="0">\r
+                <tr>\r
+                    <td>今日(<fmt:formatDate value="${requestScope.diaryDate}" pattern="MM/dd" timeZone="JST" />)</td>\r
+                    <td>:</td>\r
+                    <td><c:out value="${requestScope.totalMoneyToday}" />円</td>\r
+                </tr>\r
+                <tr>\r
+                    <td>今週(<fmt:formatDate value="${requestScope.weekStartDate}" pattern="MM/dd" timeZone="JST" />~<fmt:formatDate value="${requestScope.weekEndDate}" pattern="MM/dd" timeZone="JST" />)</td>\r
+                    <td>:</td>\r
+                    <td><c:out value="${requestScope.totalMoneyThisWeek}" />円</td>\r
+                </tr>\r
+                <tr>\r
+                    <td>今月(<fmt:formatDate value="${requestScope.monthStartDate}" pattern="MM/dd" timeZone="JST" />~<fmt:formatDate value="${requestScope.monthEndDate}" pattern="MM/dd" timeZone="JST" />)</td>\r
+                    <td>:</td>\r
+                    <td><c:out value="${requestScope.totalMoneyThisMonth}" />円</td>\r
+                </tr>\r
+            </table>\r
+        </p>\r
+        <hr>\r
+        <p>\r
+            今日の収支明細<br>\r
+            <table border="0">\r
+                       <c:forEach items="${requestScope.moneyList}" var="money">\r
+                       <tr>\r
+                           <td><c:out value="${money.item}" /></td>\r
+                    <td><c:out value="${money.money}" />円</td>\r
+                       </tr>\r
+                       </c:forEach>\r
+            </table>\r
+        </p>\r
+    </body>\r
+</html>\r
diff --git a/money-notebook/war/WEB-INF/page/mobile/user/diary_weekly.jsp b/money-notebook/war/WEB-INF/page/mobile/user/diary_weekly.jsp
new file mode 100644 (file)
index 0000000..80955d9
--- /dev/null
@@ -0,0 +1,70 @@
+<%@ page contentType="text/html; charset=UTF-8"\r
+         pageEncoding="UTF-8" %>\r
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>\r
+<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>\r
+<%\r
+    response.setDateHeader("Date", System.currentTimeMillis());\r
+    response.setDateHeader("Expires", 0);\r
+    response.setHeader("Pragma", "no-cache");\r
+    response.setHeader("Cache-Control", "no-cache");\r
+    response.addHeader("Cache-Control", "no-store");\r
+    response.addHeader("Cache-Control", "max-age=0");\r
+%>\r
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\r
+<html>\r
+    <head>\r
+        <meta http-equiv="content-type" content="text/html; charset=UTF-8">\r
+        <meta http-equiv="content-language" content="ja">\r
+        <meta http-equiv="content-style-type" content="text/css">\r
+        <meta http-equiv="content-script-type" content="text/javascript">\r
+        <meta http-equiv="pragma" content="no-cache">\r
+        <meta http-equiv="cache-control" content="no-cache">\r
+        <meta http-equiv="expires" content="0">\r
+        <meta name="author" content="u6k.yu1@gmail.com">\r
+        <meta name="copyright" content="Copyright (C) 2010 u6k.yu1@gmail.com All rights reserved.">\r
+        <meta name="keywords" content="小遣い,家計簿" lang="ja">\r
+        <meta name="description" content="小遣い帳サービス。">\r
+        <meta name="robots" content="nofollow">\r
+        <title>トップ - 小遣い帳(仮)</title>\r
+    </head>\r
+    <body>\r
+        <h1>小遣い帳(仮)</h1>\r
+        <h2>トップ</h2>\r
+        <hr>\r
+        <h3>記帳メールアドレス</h3>\r
+        <p><input type="text" value="<c:out value="${sessionScope.id}" />@money-notebook.appspotmail.com"></p>\r
+        <hr>\r
+        <h3>収支合計</h3>\r
+        <p>\r
+            <table border="0">\r
+                <tr>\r
+                    <td>今日(<fmt:formatDate value="${requestScope.diaryDate}" pattern="MM/dd" timeZone="JST" />)</td>\r
+                    <td>:</td>\r
+                    <td><c:out value="${requestScope.totalMoneyToday}" />円</td>\r
+                </tr>\r
+                <tr>\r
+                    <td>今週(<fmt:formatDate value="${requestScope.weekStartDate}" pattern="MM/dd" timeZone="JST" />~<fmt:formatDate value="${requestScope.weekEndDate}" pattern="MM/dd" timeZone="JST" />)</td>\r
+                    <td>:</td>\r
+                    <td><c:out value="${requestScope.totalMoneyThisWeek}" />円</td>\r
+                </tr>\r
+                <tr>\r
+                    <td>今月(<fmt:formatDate value="${requestScope.monthStartDate}" pattern="MM/dd" timeZone="JST" />~<fmt:formatDate value="${requestScope.monthEndDate}" pattern="MM/dd" timeZone="JST" />)</td>\r
+                    <td>:</td>\r
+                    <td><c:out value="${requestScope.totalMoneyThisMonth}" />円</td>\r
+                </tr>\r
+            </table>\r
+        </p>\r
+        <hr>\r
+        <p>\r
+            今日の収支明細<br>\r
+            <table border="0">\r
+                       <c:forEach items="${requestScope.moneyList}" var="money">\r
+                       <tr>\r
+                           <td><c:out value="${money.item}" /></td>\r
+                    <td><c:out value="${money.money}" />円</td>\r
+                       </tr>\r
+                       </c:forEach>\r
+            </table>\r
+        </p>\r
+    </body>\r
+</html>\r
diff --git a/money-notebook/war/WEB-INF/page/mobile/user/top.jsp b/money-notebook/war/WEB-INF/page/mobile/user/top.jsp
new file mode 100644 (file)
index 0000000..8bfcb9a
--- /dev/null
@@ -0,0 +1,75 @@
+<%@ page contentType="text/html; charset=UTF-8"\r
+         pageEncoding="UTF-8" %>\r
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>\r
+<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>\r
+<%\r
+    response.setDateHeader("Date", System.currentTimeMillis());\r
+    response.setDateHeader("Expires", 0);\r
+    response.setHeader("Pragma", "no-cache");\r
+    response.setHeader("Cache-Control", "no-cache");\r
+    response.addHeader("Cache-Control", "no-store");\r
+    response.addHeader("Cache-Control", "max-age=0");\r
+%>\r
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\r
+<html>\r
+    <head>\r
+        <meta http-equiv="content-type" content="text/html; charset=UTF-8">\r
+        <meta http-equiv="content-language" content="ja">\r
+        <meta http-equiv="content-style-type" content="text/css">\r
+        <meta http-equiv="content-script-type" content="text/javascript">\r
+        <meta http-equiv="pragma" content="no-cache">\r
+        <meta http-equiv="cache-control" content="no-cache">\r
+        <meta http-equiv="expires" content="0">\r
+        <meta name="author" content="u6k.yu1@gmail.com">\r
+        <meta name="copyright" content="Copyright (C) 2010 u6k.yu1@gmail.com All rights reserved.">\r
+        <meta name="keywords" content="小遣い,家計簿" lang="ja">\r
+        <meta name="description" content="小遣い帳サービス。">\r
+        <meta name="robots" content="nofollow">\r
+        <title>トップ - 小遣い帳(仮)</title>\r
+    </head>\r
+    <body>\r
+        <h1>小遣い帳(仮)</h1>\r
+        <h2>トップ</h2>\r
+        <hr>\r
+        <h3>記帳メールアドレス</h3>\r
+        <p><input type="text" value="<c:out value="${sessionScope.id}" />@money-notebook.appspotmail.com"></p>\r
+        <hr>\r
+        <h3>収支合計</h3>\r
+        <p>\r
+            <table border="0">\r
+                <tr>\r
+                    <td>今日(<fmt:formatDate value="${requestScope.moneyDiaryForm.diaryDate}" pattern="MM/dd" timeZone="JST" />)</td>\r
+                    <td>:</td>\r
+                    <td><c:out value="${requestScope.moneyDiaryForm.money}" />円</td>\r
+                </tr>\r
+                <tr>\r
+                    <td>今週(<fmt:formatDate value="${requestScope.weekStartDate}" pattern="MM/dd" timeZone="JST" />~<fmt:formatDate value="${requestScope.weekEndDate}" pattern="MM/dd" timeZone="JST" />)</td>\r
+                    <td>:</td>\r
+                    <td><c:out value="${requestScope.totalMoneyThisWeek}" />円</td>\r
+                </tr>\r
+                <tr>\r
+                    <td>今月(<fmt:formatDate value="${requestScope.monthStartDate}" pattern="MM/dd" timeZone="JST" />~<fmt:formatDate value="${requestScope.monthEndDate}" pattern="MM/dd" timeZone="JST" />)</td>\r
+                    <td>:</td>\r
+                    <td><c:out value="${requestScope.totalMoneyThisMonth}" />円</td>\r
+                </tr>\r
+            </table>\r
+        </p>\r
+        <hr>\r
+        <p>\r
+            今日の収支明細<br>\r
+            <table border="0">\r
+                <c:forEach items="${requestScope.moneyDiaryForm.itemList}" var="item">\r
+                <tr>\r
+                    <td><c:out value="${item.item}" /></td>\r
+                    <td><c:out value="${item.money}" />円</td>\r
+                </tr>\r
+                </c:forEach>\r
+            </table>\r
+        </p>\r
+        <hr>\r
+        <p>\r
+            <a href="/m/user/<c:out value="${sessionScope.id}" />/diary/daily/20100101/20101231/">一覧(日毎)</a><br>\r
+            <a href="/m/user/<c:out value="${sessionScope.id}" />/diary/detail/20100101/20101231/">一覧(詳細)</a>\r
+        </p>\r
+    </body>\r
+</html>\r
diff --git a/money-notebook/war/WEB-INF/urlrewrite.xml b/money-notebook/war/WEB-INF/urlrewrite.xml
new file mode 100644 (file)
index 0000000..3cce99a
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.2//EN"\r
+                            "http://tuckey.org/res/dtds/urlrewrite3.2.dtd">\r
+<urlrewrite>\r
+\r
+    <rule>\r
+        <from>^/m/regist/([0-9]+)/$</from>\r
+        <to>/m/regist/?id=$1</to>\r
+    </rule>\r
+    <rule>\r
+        <from>^/m/regist/([0-9]+)/finish$</from>\r
+        <to>/m/regist/finish?id=$1</to>\r
+    </rule>\r
+    <rule>\r
+        <from>^/m/user/([0-9]+)/diary/daily/([0-9]+)/([0-9]+)/$</from>\r
+        <to>/m/user/diary?id=$1&amp;mode=daily&amp;begin=$2&amp;end=$3</to>\r
+    </rule>\r
+    <rule>\r
+        <from>^/m/user/([0-9]+)/diary/detail/([0-9]+)/([0-9]+)/$</from>\r
+        <to>/m/user/diary?id=$1&amp;mode=detail&amp;begin=$2&amp;end=$3</to>\r
+    </rule>\r
+    <rule>\r
+        <from>^/m/user/([0-9]+)/top$</from>\r
+        <to>/m/user/top?id=$1</to>\r
+    </rule>\r
+    <rule>\r
+        <from>^/m/user/([0-9]+)/tutorial$</from>\r
+        <to>/m/user/tutorial?id=$1</to>\r
+    </rule>\r
+\r
+</urlrewrite>\r
diff --git a/money-notebook/war/WEB-INF/web.xml b/money-notebook/war/WEB-INF/web.xml
new file mode 100644 (file)
index 0000000..c4eea66
--- /dev/null
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">\r
+<web-app>\r
+\r
+    <!-- Servlets -->\r
+    <servlet>\r
+        <servlet-name>gwt_IndexService</servlet-name>\r
+        <servlet-class>jp.gr.java_conf.u6k.money_notebook.gwt.server.IndexServiceImpl</servlet-class>\r
+    </servlet>\r
+    <servlet>\r
+        <servlet-name>mail_CreateMoneyServlet</servlet-name>\r
+        <servlet-class>jp.gr.java_conf.u6k.money_notebook.web.servlet.mail.CreateMoneyServlet</servlet-class>\r
+    </servlet>\r
+    <servlet>\r
+        <servlet-name>mail_RegistMailServlet</servlet-name>\r
+        <servlet-class>jp.gr.java_conf.u6k.money_notebook.web.servlet.mail.RegistMailServlet</servlet-class>\r
+    </servlet>\r
+    <servlet>\r
+        <servlet-name>mobile_IndexServlet</servlet-name>\r
+        <servlet-class>jp.gr.java_conf.u6k.money_notebook.web.servlet.mobile.IndexServlet</servlet-class>\r
+    </servlet>\r
+    <servlet>\r
+        <servlet-name>mobile_LoginServlet</servlet-name>\r
+        <servlet-class>jp.gr.java_conf.u6k.money_notebook.web.servlet.mobile.LoginServlet</servlet-class>\r
+    </servlet>\r
+    <servlet>\r
+        <servlet-name>mobile_RegistServlet</servlet-name>\r
+        <servlet-class>jp.gr.java_conf.u6k.money_notebook.web.servlet.mobile.RegistServlet</servlet-class>\r
+    </servlet>\r
+    <servlet>\r
+        <servlet-name>mobile_RegistFinishServlet</servlet-name>\r
+        <servlet-class>jp.gr.java_conf.u6k.money_notebook.web.servlet.mobile.RegistFinishServlet</servlet-class>\r
+    </servlet>\r
+    <servlet>\r
+        <servlet-name>mobile_user_DiaryServlet</servlet-name>\r
+        <servlet-class>jp.gr.java_conf.u6k.money_notebook.web.servlet.mobile.user.DiaryServlet</servlet-class>\r
+    </servlet>\r
+    <servlet>\r
+        <servlet-name>mobile_user_TopServlet</servlet-name>\r
+        <servlet-class>jp.gr.java_conf.u6k.money_notebook.web.servlet.mobile.user.TopServlet</servlet-class>\r
+    </servlet>\r
+    <servlet>\r
+        <servlet-name>mobile_user_TutorialServlet</servlet-name>\r
+        <servlet-class>jp.gr.java_conf.u6k.money_notebook.web.servlet.mobile.user.TutorialServlet</servlet-class>\r
+    </servlet>\r
+    <servlet>\r
+        <servlet-name>admin_MaintenanceServlet</servlet-name>\r
+        <servlet-class>jp.gr.java_conf.u6k.money_notebook.web.servlet.admin.MaintenanceServlet</servlet-class>\r
+    </servlet>\r
+    <servlet>\r
+        <servlet-name>admin_UserDataServlet</servlet-name>\r
+        <servlet-class>jp.gr.java_conf.u6k.money_notebook.web.servlet.admin.UserDataServlet</servlet-class>\r
+    </servlet>\r
+    <servlet>\r
+        <servlet-name>admin_UserIdListServlet</servlet-name>\r
+        <servlet-class>jp.gr.java_conf.u6k.money_notebook.web.servlet.admin.UserIdListServlet</servlet-class>\r
+    </servlet>\r
+\r
+    <servlet-mapping>\r
+        <servlet-name>gwt_IndexService</servlet-name>\r
+        <url-pattern>/index/index</url-pattern>\r
+    </servlet-mapping>\r
+    <servlet-mapping>\r
+        <servlet-name>mobile_IndexServlet</servlet-name>\r
+        <url-pattern>/m/</url-pattern>\r
+    </servlet-mapping>\r
+    <servlet-mapping>\r
+        <servlet-name>mobile_LoginServlet</servlet-name>\r
+        <url-pattern>/m/login</url-pattern>\r
+    </servlet-mapping>\r
+    <servlet-mapping>\r
+        <servlet-name>mobile_RegistServlet</servlet-name>\r
+        <url-pattern>/m/regist/</url-pattern>\r
+    </servlet-mapping>\r
+    <servlet-mapping>\r
+        <servlet-name>mobile_RegistFinishServlet</servlet-name>\r
+        <url-pattern>/m/regist/finish</url-pattern>\r
+    </servlet-mapping>\r
+    <servlet-mapping>\r
+        <servlet-name>mobile_user_DiaryServlet</servlet-name>\r
+        <url-pattern>/m/user/diary</url-pattern>\r
+    </servlet-mapping>\r
+    <servlet-mapping>\r
+        <servlet-name>mobile_user_TopServlet</servlet-name>\r
+        <url-pattern>/m/user/top</url-pattern>\r
+    </servlet-mapping>\r
+    <servlet-mapping>\r
+        <servlet-name>mobile_user_TutorialServlet</servlet-name>\r
+        <url-pattern>/m/user/tutorial</url-pattern>\r
+    </servlet-mapping>\r
+    <servlet-mapping>\r
+        <servlet-name>mail_RegistMailServlet</servlet-name>\r
+        <url-pattern>/_ah/mail/regist@money-notebook.appspotmail.com</url-pattern>\r
+    </servlet-mapping>\r
+    <servlet-mapping>\r
+        <servlet-name>mail_CreateMoneyServlet</servlet-name>\r
+        <url-pattern>/_ah/mail/*</url-pattern>\r
+    </servlet-mapping>\r
+    <servlet-mapping>\r
+        <servlet-name>admin_MaintenanceServlet</servlet-name>\r
+        <url-pattern>/admin/maintenance</url-pattern>\r
+    </servlet-mapping>\r
+    <servlet-mapping>\r
+        <servlet-name>admin_UserDataServlet</servlet-name>\r
+        <url-pattern>/admin/data/user</url-pattern>\r
+    </servlet-mapping>\r
+    <servlet-mapping>\r
+        <servlet-name>admin_UserIdListServlet</servlet-name>\r
+        <url-pattern>/admin/data/user_id_list</url-pattern>\r
+    </servlet-mapping>\r
+\r
+    <!-- Filters -->\r
+    <filter>\r
+        <filter-name>RequestLogFilter</filter-name>\r
+        <filter-class>jp.gr.java_conf.u6k.money_notebook.web.filter.RequestLogFilter</filter-class>\r
+    </filter>\r
+    <filter-mapping>\r
+        <filter-name>RequestLogFilter</filter-name>\r
+        <url-pattern>/*</url-pattern>\r
+    </filter-mapping>\r
+\r
+    <filter>\r
+        <filter-name>LoginCheckFilter</filter-name>\r
+        <filter-class>jp.gr.java_conf.u6k.money_notebook.web.filter.LoginCheckFilter</filter-class>\r
+    </filter>\r
+    <filter-mapping>\r
+        <filter-name>LoginCheckFilter</filter-name>\r
+        <url-pattern>/m/user/*</url-pattern>\r
+    </filter-mapping>\r
+\r
+    <filter>\r
+        <filter-name>UrlRewriteFilter</filter-name>\r
+        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>\r
+    </filter>\r
+    <filter-mapping>\r
+        <filter-name>UrlRewriteFilter</filter-name>\r
+        <url-pattern>/*</url-pattern>\r
+        <dispatcher>REQUEST</dispatcher>\r
+        <dispatcher>FORWARD</dispatcher>\r
+    </filter-mapping>\r
+\r
+    <!-- Default page to serve -->\r
+    <welcome-file-list>\r
+        <welcome-file>index.html</welcome-file>\r
+    </welcome-file-list>\r
+\r
+    <!-- Access Security -->\r
+    <security-constraint>\r
+        <web-resource-collection>\r
+            <url-pattern>/_ah/mail/*</url-pattern>\r
+            <url-pattern>/admin/*</url-pattern>\r
+        </web-resource-collection>\r
+        <auth-constraint>\r
+            <role-name>admin</role-name>\r
+        </auth-constraint>\r
+    </security-constraint>\r
+\r
+</web-app>\r
diff --git a/money-notebook/war/admin/data/user.jsp b/money-notebook/war/admin/data/user.jsp
new file mode 100644 (file)
index 0000000..a5ee8b7
--- /dev/null
@@ -0,0 +1,43 @@
+<%@ page contentType="text/html; charset=UTF-8"\r
+         pageEncoding="UTF-8" %>\r
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>\r
+<%\r
+    response.setDateHeader("Date", System.currentTimeMillis());\r
+    response.setDateHeader("Expires", 0);\r
+    response.setHeader("Pragma", "no-cache");\r
+    response.setHeader("Cache-Control", "no-cache");\r
+    response.addHeader("Cache-Control", "no-store");\r
+    response.addHeader("Cache-Control", "max-age=0");\r
+%>\r
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\r
+<html>\r
+    <head>\r
+        <meta http-equiv="content-type" content="text/html; charset=UTF-8">\r
+        <meta http-equiv="content-language" content="ja">\r
+        <meta http-equiv="content-style-type" content="text/css">\r
+        <meta http-equiv="content-script-type" content="text/javascript">\r
+        <meta http-equiv="pragma" content="no-cache">\r
+        <meta http-equiv="cache-control" content="no-cache">\r
+        <meta http-equiv="expires" content="0">\r
+        <meta name="author" content="u6k.yu1@gmail.com">\r
+        <meta name="copyright" content="Copyright (C) 2010 u6k.yu1@gmail.com All rights reserved.">\r
+        <meta name="keywords" content="小遣い,家計簿" lang="ja">\r
+        <meta name="description" content="小遣い帳サービス。">\r
+        <meta name="robots" content="nofollow">\r
+        <title>小遣い帳(仮)</title>\r
+    </head>\r
+    <body>\r
+        <h1>小遣い帳(仮)</h1>\r
+        <h2>管理 - ユーザー・データのバックアップ、リストア\r
+        <hr>\r
+        <h3>バックアップ</h3>\r
+        <form action="/admin/data/user" method="get">\r
+            ID: <input type="text" name="id" id="id"><input type="submit" value="バックアップ">\r
+        </form>\r
+        <hr>\r
+        <h3>リストア</h3>\r
+        <form action="/admin/data/user" method="post">\r
+            JSONデータ<textarea name="data" id="data"></textarea><input type="submit" value="リストア">\r
+        </form>\r
+    </body>\r
+</html>\r
diff --git a/money-notebook/war/index.html b/money-notebook/war/index.html
new file mode 100644 (file)
index 0000000..0eabae8
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\r
+<html>\r
+    <head>\r
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\r
+        <title>お小遣い帳(仮)</title>\r
+        <script type="text/javascript" language="javascript" src="index/index.nocache.js"></script>\r
+    </head>\r
+    <body>\r
+        <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex="-1" style="position:absolute; width:0; height:0; border:0;"></iframe>\r
+        <div id="content"></div>\r
+    </body>\r
+</html>\r