--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="com.google.appengine.eclipse.core.GAE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="lib" path="war/WEB-INF/lib/spring-webmvc.jar"/>
+ <classpathentry kind="lib" path="war/WEB-INF/lib/commons-logging.jar"/>
+ <classpathentry kind="lib" path="war/WEB-INF/lib/spring-modules-validation.jar"/>
+ <classpathentry kind="lib" path="war/WEB-INF/lib/aspectjrt.jar"/>
+ <classpathentry kind="lib" path="war/WEB-INF/lib/aspectjweaver.jar"/>
+ <classpathentry kind="lib" path="war/WEB-INF/lib/spring-aop.jar"/>
+ <classpathentry kind="lib" path="war/WEB-INF/lib/spring-beans.jar"/>
+ <classpathentry kind="lib" path="war/WEB-INF/lib/spring-context-support.jar"/>
+ <classpathentry kind="lib" path="war/WEB-INF/lib/spring-context.jar"/>
+ <classpathentry kind="lib" path="war/WEB-INF/lib/spring-core.jar"/>
+ <classpathentry kind="lib" path="war/WEB-INF/lib/spring-web.jar"/>
+ <classpathentry kind="lib" path="war/WEB-INF/lib/aopalliance.jar"/>
+ <classpathentry kind="output" path="war/WEB-INF/classes"/>
+</classpath>
--- /dev/null
+*.class
+*.jar
+*.bin
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>RabbitBTS</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.google.appengine.eclipse.core.enhancerbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.google.appengine.eclipse.core.projectValidator</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>com.google.appengine.eclipse.core.gaeNature</nature>
+ <nature>com.google.gdt.eclipse.core.webAppNature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+#Sat Jul 18 19:11:00 JST 2009
+eclipse.preferences.version=1
+filesCopiedToWebInfLib=appengine-api-1.0-sdk-1.2.2.jar|datanucleus-appengine-1.0.2.final.jar|datanucleus-core-1.1.4-gae.jar|datanucleus-jpa-1.1.4.jar|geronimo-jpa_3.0_spec-1.1.1.jar|geronimo-jta_1.1_spec-1.1.1.jar|jdo2-api-2.3-ea.jar
--- /dev/null
+#Sun Jul 19 06:24:41 JST 2009
+eclipse.preferences.version=1
+jarsExcludedFromWebInfLib=
--- /dev/null
+#Sun Jul 19 06:24:41 JST 2009
+eclipse.preferences.version=1
+filesCopiedToWebInfLib=
--- /dev/null
+<?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>
--- /dev/null
+org.apache.commons.logging.Log=org.apache.commons.logging.impl.Jdk14Logger
\ No newline at end of file
--- /dev/null
+# 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
--- /dev/null
+package rabbitBTS;
+
+import javax.jdo.JDOHelper;
+import javax.jdo.PersistenceManagerFactory;
+
+public final class PMF {
+ private static final PersistenceManagerFactory pmfInstance = JDOHelper
+ .getPersistenceManagerFactory("transactions-optional");
+
+ private PMF() {
+ };
+
+ public static PersistenceManagerFactory get() {
+ return pmfInstance;
+ }
+}
--- /dev/null
+package rabbitBTS;
+
+import java.util.logging.Logger;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.google.appengine.api.users.User;
+import com.google.appengine.api.users.UserService;
+import com.google.appengine.api.users.UserServiceFactory;
+
+
+/**
+ * Short hand Methods.
+ *
+ * @author senju
+ *
+ */
+public final class Sht {
+
+ public static final User user(){
+ UserService userService = UserServiceFactory.getUserService();
+ return userService.getCurrentUser();
+ }
+
+ public static final String loginUrl(HttpServletRequest req){
+ UserService userService = UserServiceFactory.getUserService();
+ return userService.createLoginURL(req.getRequestURI());
+ }
+
+ public static final String logoutUrl(HttpServletRequest req){
+ UserService userService = UserServiceFactory.getUserService();
+ return userService.createLogoutURL(req.getRequestURI());
+ }
+
+ @SuppressWarnings("unchecked")
+ public static final Logger log(Class c){
+ return Logger.getLogger(c.getName());
+ }
+
+ public static final Logger log(Object o){
+ return Logger.getLogger(o.getClass().getName());
+ }
+}
--- /dev/null
+package rabbitBTS;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.springframework.beans.propertyeditors.CustomDateEditor;
+import org.springframework.beans.propertyeditors.StringTrimmerEditor;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.support.WebBindingInitializer;
+import org.springframework.web.context.request.WebRequest;
+
+public class SomeBindingInitializer implements WebBindingInitializer {
+
+ @Override
+ public void initBinder(WebDataBinder binder, WebRequest request) {
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ dateFormat.setLenient(false);
+ binder.registerCustomEditor(Date.class, new CustomDateEditor(
+ dateFormat, false));
+ binder.registerCustomEditor(String.class,
+ new StringTrimmerEditor(false));
+
+ }
+
+}
--- /dev/null
+package rabbitBTS;
+
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+
+@Aspect
+public class TestAspect {
+
+ @Pointcut("execution(* rabbitBTS.controllers.*Controllere.*(..))")
+ public void controllerPointcut(){
+
+ }
+
+ @Before("rabbitBTS.TestAspect.controllerPointcut()")
+ public void before(){
+ Sht.log(this).info("ASPECT before");
+ }
+
+}
--- /dev/null
+package rabbitBTS.controllers;
+
+
+import java.util.Date;
+import java.util.List;
+
+import javax.jdo.PersistenceManager;
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.Validator;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import rabbitBTS.PMF;
+import rabbitBTS.Sht;
+import rabbitBTS.models.BbsPost;
+
+@Controller
+public class BbsController implements IController{
+ @Autowired
+ private Validator validator;
+
+ @RequestMapping(method = RequestMethod.GET)
+ public void index(ModelMap model, HttpServletRequest req) {
+ Sht.log(this).finest("index called");
+ BbsPost g = new BbsPost();
+ g.setAuthor(Sht.user());
+ model.addAttribute(g);
+ model.addAttribute("loginurl", Sht.loginUrl(req));
+ model.addAttribute("logouturl", Sht.logoutUrl(req));
+ model.addAttribute("posts",fetchBbsPosts());
+ }
+
+ @RequestMapping(method = RequestMethod.POST)
+ public String postEdit(BbsPost g, BindingResult result){
+ Sht.log(this).finest("submit called");
+ g.setAuthor(Sht.user());
+ g.setDate(new Date());
+ if(g.getAuthor() == null){
+ Sht.log(this).finest("author is null.");
+ return null;
+ }
+ validator.validate(g, result);
+ if(result.hasErrors()){
+ Sht.log(this).finest("content is empty.");
+ return null;
+ }
+ PersistenceManager pm = PMF.get().getPersistenceManager();
+ try{
+ pm.makePersistent(g);
+ }finally{
+ pm.close();
+ }
+
+ return "redirect:index.html";
+ }
+
+ @SuppressWarnings("unchecked")
+ private List<BbsPost> fetchBbsPosts(){
+ String q = "select from " + BbsPost.class.getName();
+ return (List<BbsPost>) PMF.get().getPersistenceManager().newQuery(q).execute();
+ }
+
+
+}
--- /dev/null
+package rabbitBTS.controllers;
+
+public interface IController {
+
+}
--- /dev/null
+package rabbitBTS.controllers;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+@Controller
+public class IndexController {
+ @RequestMapping(method = RequestMethod.GET, value = "/index.html")
+ public void index() {
+
+ }
+
+}
--- /dev/null
+package rabbitBTS.controllers;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import rabbitBTS.Sht;
+import rabbitBTS.exceptions.NotRegisteredException;
+import rabbitBTS.models.UserProfile;
+import rabbitBTS.services.AccountServices;
+
+@Controller
+public class RegisterController implements IController {
+ @Autowired
+ private AccountServices accountServices;
+
+ @RequestMapping(method = RequestMethod.GET)
+ public String index(HttpServletRequest req) {
+ try {
+ UserProfile up = accountServices.fetchUserProfile();
+ if (up == null) {
+ // googleにログインしてない場合
+ return Sht.loginUrl(req);
+ } else {
+ // すでに登録済みの場合ホームへリダイレクト
+ return "redirect:/home.html";
+ }
+ } catch (NotRegisteredException e) {
+ // 正常系
+ return null;
+ }
+ }
+}
--- /dev/null
+package rabbitBTS.exceptions;
+
+/**
+ * ユーザーが新規登録を行っていない場合に発生する。
+ *
+ * @author senju
+ *
+ */
+@SuppressWarnings("serial")
+public class NotRegisteredException extends Exception {
+
+ // TODO: リファクタリング(国際化どうやんだ?)
+ private static final String msg = "ユーザーが新規登録を行っていません。";
+
+ public NotRegisteredException() {
+ super(msg);
+ }
+
+ public NotRegisteredException(Throwable cause) {
+ super(msg, cause);
+ }
+
+}
--- /dev/null
+package rabbitBTS.interceptors;
+
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import rabbitBTS.Sht;
+
+public class TraceInterceptor extends HandlerInterceptorAdapter {
+
+ @Override
+ public boolean preHandle(HttpServletRequest request,
+ HttpServletResponse response, Object handler) throws Exception {
+ Sht.log(handler.getClass()).finest("REQEST");
+ return true;
+ }
+
+}
--- /dev/null
+package rabbitBTS.models;
+
+import java.util.Date;
+
+import javax.jdo.annotations.IdGeneratorStrategy;
+import javax.jdo.annotations.IdentityType;
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.Persistent;
+import javax.jdo.annotations.PrimaryKey;
+
+import org.springmodules.validation.bean.conf.loader.annotation.handler.NotBlank;
+
+import com.google.appengine.api.users.User;
+
+@PersistenceCapable(identityType = IdentityType.APPLICATION)
+public class BbsPost {
+ @PrimaryKey
+ @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
+ private Long id;
+ @Persistent
+ private User author;
+ @Persistent
+ @NotBlank
+ private String content;
+ @Persistent
+ private Date date;
+
+ public BbsPost(){
+
+ }
+
+ public BbsPost(User author, String content, Date date){
+ this.author = author;
+ this.content = content;
+ this.date = date;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public User getAuthor() {
+ return author;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public void setAuthor(User author) {
+ this.author = author;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ public void setDate(Date date) {
+ this.date = date;
+ }
+}
--- /dev/null
+package rabbitBTS.models;
+
+import java.util.Date;
+
+import javax.jdo.annotations.IdGeneratorStrategy;
+import javax.jdo.annotations.IdentityType;
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.Persistent;
+import javax.jdo.annotations.PrimaryKey;
+
+import com.google.appengine.api.users.User;
+
+@PersistenceCapable(identityType = IdentityType.APPLICATION)
+public class UserProfile {
+ @PrimaryKey
+ @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
+ private Long userProfileId;
+
+ // google user
+ @Persistent
+ private User gu;
+
+ @Persistent
+ private Date lastAccess;
+
+ public Long getUserProfileId() {
+ return userProfileId;
+ }
+
+ public User getGu() {
+ return gu;
+ }
+
+ public Date getLastAccess() {
+ return lastAccess;
+ }
+
+ public void setGu(User gu) {
+ this.gu = gu;
+ }
+
+ public void setLastAccess(Date lastAccess) {
+ this.lastAccess = lastAccess;
+ }
+}
--- /dev/null
+package rabbitBTS.services;
+
+import java.util.List;
+
+import javax.jdo.Query;
+
+import org.springframework.stereotype.Service;
+
+import rabbitBTS.PMF;
+import rabbitBTS.Sht;
+import rabbitBTS.exceptions.NotRegisteredException;
+import rabbitBTS.models.UserProfile;
+
+import com.google.appengine.api.users.User;
+
+/**
+ * アカウント/ユーザープロファイルまわりのサービス
+ * @author senju
+ */
+@Service()
+public class AccountServices {
+
+ /**
+ * 現在ログイン中のgoogleアカウントのユーザープロファイルを取得する。
+ *
+ * @return 取得したユーザープロファイル。ログインしていない場合はnull
+ * @throws NotRegisteredException 未登録ユーザーの場合
+ */
+ @SuppressWarnings("unchecked")
+ public UserProfile fetchUserProfile() throws NotRegisteredException {
+ User gu = Sht.user();
+ if(gu == null){
+ return null;
+ }
+ Query q = PMF.get().getPersistenceManager().newQuery(UserProfile.class);
+ q.setFilter("gu == u");
+ q.declareImports("import com.google.appengine.api.users.User;");
+ q.declareParameters("User u");
+ List<UserProfile> up = (List<UserProfile>) q.execute(gu);
+ if(up.size() == 0){
+ throw new NotRegisteredException();
+ }
+
+ return up.get(0);
+ }
+}
--- /dev/null
+<!-- Indices written at Thu, 23 Jul 2009 14:58:37 UTC -->
+
+<datastore-indexes/>
+
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
+ <application>rabbit-bts</application>
+ <version>1</version>
+
+ <!-- Configure java.util.logging -->
+ <system-properties>
+ <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
+ </system-properties>
+
+</appengine-web-app>
\ No newline at end of file
--- /dev/null
+<?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>
--- /dev/null
+org.apache.commons.logging.Log=org.apache.commons.logging.impl.Jdk14Logger
\ No newline at end of file
--- /dev/null
+# 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
--- /dev/null
+issueはログインしてないと登録できないことにする(AOP制御なのであとでやる。)
+
+ユーザーグループ/コミュニティの導入
+
+ロールの導入(報告者、バグの状態を変更できる人、システムの管理者など)
+ bugzillaはQA担当とかまで用意してるけどどうしよう?
+
+チェンジセット(バグの属性変更の履歴)を蓄積しなきゃいけないので面倒
+
+必要な画面
+ コミュニケーション系
+ ユーザー検索
+ プロジェクトに招待
+ 削除(管理者のみ)
+ プロジェクト検索
+ プロジェクト削除(プロジェクト管理者のみ)
+ プロジェクトに参加
+ プロジェクト詳細
+ プロジェクト一覧->issue一覧へ
+ 製品削除(プロジェクト管理者のみ)
+ ユーザー一覧(プロジェクト管理者のみ)
+ インデックス系
+ サマリー
+ 新規/活発なプロジェクト等?
+ 新規登録へのリンク(非ログイン時)
+ プロフィール系
+ 新規登録画面
+ ユーザーホーム
+ メッセージ一覧
+ プロジェクト一覧
+
+
+ issue系
+ 一覧
+ 検索
+ 報告
+ 詳細(コメントリスティング、属性変更履歴を兼ねる)
+ 属性変更
+
+ 管理
\ No newline at end of file
--- /dev/null
+# 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 = WARNING
+
+# 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
+
+org.springframework.level=INFO
+rabbitBTS.level=FINEST
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties version="1.0">
+<entry key="BbsPost.content[not.blank]">
+内容がないよう
+</entry>
+
+</properties>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
+
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-2.5.xsd
+ http://www.springframework.org/schema/aop
+ http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
+ ">
+ <!-- aspect -->
+ <!--
+ <aop:aspectj-autoproxy /> <bean
+ class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"
+ /> <bean class="rabbitBTS.TestAspect" />
+ -->
+ <!-- validator -->
+ <bean id="configurationLoader"
+ class="org.springmodules.validation.bean.conf.loader.annotation.AnnotationBeanValidationConfigurationLoader" />
+ <bean id="validator" class="org.springmodules.validation.bean.BeanValidator"
+ p:configurationLoader-ref="configurationLoader" />
+ <!-- Load messages -->
+ <bean id="messageSource"
+ class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
+ p:basenames="WEB-INF/messages">
+ <property name="cacheSeconds" value="1"></property>
+ </bean>
+
+ <!-- Controller etc. -->
+ <bean
+ class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
+ <property name="interceptors">
+ <list>
+ <ref bean="tracer"></ref>
+ </list>
+ </property>
+ </bean>
+ <bean id="annotationMethodHandlerAdapter"
+ class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
+ <!-- spring bugs -->
+ <property name="webBindingInitializer">
+ <bean class="rabbitBTS.SomeBindingInitializer" />
+ </property>
+ </bean>
+ <bean
+ class="org.springframework.web.servlet.view.InternalResourceViewResolver">
+ <property name="viewClass"
+ value="org.springframework.web.servlet.view.JstlView" />
+ <property name="prefix" value="/WEB-INF/views/" />
+ <property name="suffix" value=".jsp" />
+ </bean>
+ <bean class="rabbitBTS.interceptors.TraceInterceptor" id="tracer" />
+
+ <bean
+ class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
+ <property name="interceptors">
+ <list>
+ <ref bean="tracer"></ref>
+ </list>
+ </property>
+ </bean>
+
+ <context:component-scan base-package="rabbitBTS"
+ use-default-filters="true" />
+
+
+
+ <!-- trace log -->
+ <!--
+ <bean id="dInterceptor"
+ class="org.springframework.aop.interceptor.DebugInterceptor" /> <bean
+ id="advisor"
+ class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
+ <property name="advice"> <ref bean="dInterceptor" /> </property>
+ <property name="mappedName"> <value>index</value> </property> </bean>
+ -->
+
+</beans>
--- /dev/null
+<%@ page language="java" contentType="text/html; charset=UTF-8"
+ pageEncoding="UTF-8"%>
+<%@ page isELIgnored="false" %>
+
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
+<%@ taglib prefix="sp" uri="http://www.springframework.org/tags" %>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+
+<title>BBS App
+<c:if test="${bbsPost.author != null }"> - </c:if>
+<c:out value="${bbsPost.author.nickname}" /></title>
+
+</head>
+<body>
+<p>BBS App</p>
+<c:choose>
+<c:when test="${bbsPost.author == null }">
+<a href="${loginurl}">ログイン</a>
+</c:when>
+<c:otherwise>
+<a href="${logouturl}">ログアウト</a>
+</c:otherwise>
+</c:choose>
+
+<table>
+<c:forEach var="g" items="${posts}">
+<tr>
+<td>${g.author.nickname }</td>
+<td>${g.content }</td>
+<td>${g.date }</td>
+</tr>
+</c:forEach>
+</table>
+
+<p><a href="postEdit.html">投稿する</a></p>
+
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<%@ page language="java" contentType="text/html; charset=UTF-8"
+ pageEncoding="UTF-8"%>
+<%@ page isELIgnored="false"%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
+<%@ taglib prefix="sp" uri="http://www.springframework.org/tags"%>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>POST Edit</title>
+</head>
+<body>
+
+<form:form modelAttribute="bbsPost" method="post"
+ action="postEdit.html">
+ <form:textarea path="content" />
+ <form:errors path="content"></form:errors>
+ <input type="submit" />
+</form:form>
+
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<%@ page language="java" contentType="text/html; charset=UTF-8"
+ pageEncoding="UTF-8"%>
+<%@ page isELIgnored="false"%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
+<%@ taglib prefix="sp" uri="http://www.springframework.org/tags"%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>Rabbit BTS</title>
+</head>
+<body>
+<div class="header">
+ログイン or <a href="/register">新規登録</a>
+<a href="/home.html">ユーザー名</a>
+</div>
+<h1>Rabbit BTSへようこそ</h1>
+<a href="/bbs">BBS</a>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
+ <servlet>
+ <servlet-name>rabbitBTS</servlet-name>
+ <servlet-class>
+ org.springframework.web.servlet.DispatcherServlet
+ </servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>rabbitBTS</servlet-name>
+ <url-pattern>*.html</url-pattern>
+ </servlet-mapping>
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+</web-app>