[myblog] r442 committed - Initial import. the myblog2's springmvc branch.

3 views
Skip to first unread message

myb...@googlecode.com

unread,
Jun 1, 2011, 4:06:21 AM6/1/11
to mybl...@googlegroups.com
Revision: 442
Author: rory.cn
Date: Wed Jun 1 01:04:00 2011
Log: Initial import. the myblog2's springmvc branch.
http://code.google.com/p/myblog/source/detail?r=442

Added:
/branches/myblog-springmvc/pom.xml
/branches/myblog-springmvc/src
/branches/myblog-springmvc/src/main
/branches/myblog-springmvc/src/main/java
/branches/myblog-springmvc/src/main/java/com
/branches/myblog-springmvc/src/main/java/com/myblog
/branches/myblog-springmvc/src/main/java/com/myblog/domain
/branches/myblog-springmvc/src/main/java/com/myblog/domain/Blog.java
/branches/myblog-springmvc/src/main/java/com/myblog/repository
/branches/myblog-springmvc/src/main/java/com/myblog/repository/BlogDao.java

/branches/myblog-springmvc/src/main/java/com/myblog/repository/BlogDaoImpl.java
/branches/myblog-springmvc/src/main/java/com/myblog/service

/branches/myblog-springmvc/src/main/java/com/myblog/service/AddPermission.java

/branches/myblog-springmvc/src/main/java/com/myblog/service/AddPermissionValidator.java

/branches/myblog-springmvc/src/main/java/com/myblog/service/BlogManager.java

/branches/myblog-springmvc/src/main/java/com/myblog/service/BlogManagerImpl.java

/branches/myblog-springmvc/src/main/java/com/myblog/service/BlogValidator.java

/branches/myblog-springmvc/src/main/java/com/myblog/service/DataSourcePopulator.java
/branches/myblog-springmvc/src/main/java/com/myblog/web

/branches/myblog-springmvc/src/main/java/com/myblog/web/AddDeleteBlogController.java

/branches/myblog-springmvc/src/main/java/com/myblog/web/AdminPermissionController.java

/branches/myblog-springmvc/src/main/java/com/myblog/web/IndexController.java
/branches/myblog-springmvc/src/main/resources

/branches/myblog-springmvc/src/main/resources/applicationContext-common-authorization.xml

/branches/myblog-springmvc/src/main/resources/applicationContext-common-business.xml
/branches/myblog-springmvc/src/main/resources/log4j.properties
/branches/myblog-springmvc/src/main/resources/messages.properties
/branches/myblog-springmvc/src/main/resources/views.properties
/branches/myblog-springmvc/src/main/webapp
/branches/myblog-springmvc/src/main/webapp/META-INF
/branches/myblog-springmvc/src/main/webapp/META-INF/MANIFEST.MF
/branches/myblog-springmvc/src/main/webapp/WEB-INF

/branches/myblog-springmvc/src/main/webapp/WEB-INF/applicationContext-security.xml
/branches/myblog-springmvc/src/main/webapp/WEB-INF/blogs-servlet.xml
/branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp
/branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/add.jsp
/branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/addPermission.jsp
/branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/adminPermission.jsp
/branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/deletePermission.jsp
/branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/deleted.jsp
/branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/hello.jsp
/branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/include.jsp
/branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/index.jsp
/branches/myblog-springmvc/src/main/webapp/WEB-INF/spring.tld
/branches/myblog-springmvc/src/main/webapp/WEB-INF/tiles
/branches/myblog-springmvc/src/main/webapp/WEB-INF/tiles/baseLayout.jsp
/branches/myblog-springmvc/src/main/webapp/WEB-INF/tiles/body.jsp
/branches/myblog-springmvc/src/main/webapp/WEB-INF/tiles/footer.jsp
/branches/myblog-springmvc/src/main/webapp/WEB-INF/tiles/header.jsp
/branches/myblog-springmvc/src/main/webapp/WEB-INF/tiles/menu.jsp
/branches/myblog-springmvc/src/main/webapp/WEB-INF/tiles-defs.xml
/branches/myblog-springmvc/src/main/webapp/WEB-INF/web.xml
/branches/myblog-springmvc/src/main/webapp/accessDenied.jsp
/branches/myblog-springmvc/src/main/webapp/error.html
/branches/myblog-springmvc/src/main/webapp/exitUser.jsp
/branches/myblog-springmvc/src/main/webapp/index.jsp
/branches/myblog-springmvc/src/main/webapp/login.jsp
/branches/myblog-springmvc/src/main/webapp/secure
/branches/myblog-springmvc/src/main/webapp/secure/debug.jsp
/branches/myblog-springmvc/src/main/webapp/switchUser.jsp
/branches/myblog-springmvc/src/test
/branches/myblog-springmvc/src/test/java
/branches/myblog-springmvc/src/test/resources
Modified:
/branches/myblog-springmvc

=======================================
--- /dev/null
+++ /branches/myblog-springmvc/pom.xml Wed Jun 1 01:04:00 2011
@@ -0,0 +1,296 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.myblog</groupId>
+ <artifactId>myblog</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ <packaging>war</packaging>
+ <name>myblog</name>
+ <description>This is the most simplest yet powerfull blog
engine</description>
+ <repositories>
+ </repositories>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>tomcat-maven-plugin</artifactId>
+ <version>1.1</version>
+ <configuration>
+ <url>http://localhost:8080/manager/html</url>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.2</version>
+ </plugin>
+ <plugin>
+ <!-- Download UMLGraph from the website and set PATH to the bin and
CLASSPATH to the Lib -->
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.8</version>
+ <configuration>
+ <doclet>org.umlgraph.doclet.UmlGraphDoc</doclet>
+ <docletArtifact>
+ <groupId>org.umlgraph</groupId>
+ <artifactId>doclet</artifactId>
+ <version>5.1</version>
+ </docletArtifact>
+ <additionalparam>-views</additionalparam>
+ <useStandardDocletOptions>true</useStandardDocletOptions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-expression</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-asm</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-aop</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-tx</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-jdbc</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context-support</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet.jsp</groupId>
+ <artifactId>jsp-api</artifactId>
+ <version>2.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.transaction</groupId>
+ <artifactId>jta</artifactId>
+ <version>1.1</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.persistence</groupId>
+ <artifactId>persistence-api</artifactId>
+ <version>1.0</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <version>5.1.6</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.14</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.6.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>1.6.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.6.0</version>
+ </dependency>
+
+ <!-- Spring Security -->
+
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-acl</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-core</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-web</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-config</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-taglibs</artifactId>
+ <version>3.0.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ <version>3.2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>aopalliance</groupId>
+ <artifactId>aopalliance</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>hessian</groupId>
+ <artifactId>hessian</artifactId>
+ <version>3.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>net.sf.ehcache</groupId>
+ <artifactId>ehcache</artifactId>
+ <version>1.6.2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.aspectj</groupId>
+ <artifactId>aspectjrt</artifactId>
+ <version>1.6.8</version>
+ </dependency>
+ <dependency>
+ <groupId>org.aspectj</groupId>
+ <artifactId>aspectjweaver</artifactId>
+ <version>1.6.8</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>jstl</artifactId>
+ <version>1.2</version>
+ </dependency>
+
+ <!-- Hibernate -->
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-core</artifactId>
+ <version>3.3.1.GA</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-search</artifactId>
+ <version>3.1.0.GA</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate</artifactId>
+ <version>3.2.1.ga</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-annotations</artifactId>
+ <version>3.2.1.ga</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ <version>3.2.1.ga</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-validator</artifactId>
+ <version>4.0.2.GA</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-api</artifactId>
+ <version>2.1.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-compat</artifactId>
+ <version>2.1.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-core</artifactId>
+ <version>2.1.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-jsp</artifactId>
+ <version>2.1.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-portlet</artifactId>
+ <version>2.1.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-servlet</artifactId>
+ <version>2.1.4</version>
+ </dependency>
+ <!-- Tiles Exception solution -->
+ <dependency>
+ <groupId>javax.portlet</groupId>
+ <artifactId>portlet-api</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.umlgraph</groupId>
+ <artifactId>doclet</artifactId>
+ <version>5.1</version>
+ </dependency>
+ </dependencies>
+</project>
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/java/com/myblog/domain/Blog.java
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,58 @@
+package com.myblog.domain;
+
+import java.io.Serializable;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+/**
+ *
+ * @author Jimmy
+ *
+ */
+
+@Entity
+@Table(name="blog")
+public class Blog implements Serializable {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -591581206254377693L;
+
+ private Long id;
+ private String title;
+ private String content;
+
+ //~ Constructors
===================================================================================================
+
+ public Blog(String title, String content) {
+ this.title = title;
+ this.content = content;
+ }
+
+ public Blog() {}
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+}
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/java/com/myblog/repository/BlogDao.java
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,32 @@
+package com.myblog.repository;
+
+import java.util.List;
+
+import com.myblog.domain.Blog;
+
+
+/**
+ * Provides access to the application's persistence layer.
+ *
+ * @author Jimmy
+ */
+public interface BlogDao {
+ //~ Methods
========================================================================================================
+
+ public void create(Blog blog);
+
+ public void delete(Long blogId);
+
+ public List<Blog> findAll();
+
+ public List<String> findAllPrincipals();
+
+ public List<String> findAllRoles();
+
+ public Blog getById(Long id);
+
+ public void update(Blog blog);
+
+ public long getLastId();
+
+}
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/java/com/myblog/repository/BlogDaoImpl.java
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,99 @@
+package com.myblog.repository;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+
+import org.springframework.jdbc.core.PreparedStatementSetter;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.support.JdbcDaoSupport;
+
+import com.myblog.domain.Blog;
+
+
+/**
+ * Base implementation of {@link BlogDao} that uses Spring's JdbcTemplate.
+ *
+ * @author Jimmy
+ */
+public class BlogDaoImpl extends JdbcDaoSupport implements BlogDao {
+
+ //~ Methods
========================================================================================================
+
+ public void create(final Blog blog) {
+ getJdbcTemplate().update("insert into blogs values (?, ?, ?)", new
PreparedStatementSetter() {
+ public void setValues(PreparedStatement ps) throws
SQLException {
+ ps.setLong(1, blog.getId());
+ ps.setString(2, blog.getTitle());
+ ps.setString(3, blog.getContent());
+ }
+ });
+ }
+
+ public void delete(final Long blogId) {
+ getJdbcTemplate().update("delete from blogs where id = ?", new
PreparedStatementSetter() {
+ public void setValues(PreparedStatement ps) throws
SQLException {
+ ps.setLong(1, blogId);
+ }
+ });
+ }
+
+ public void update(final Blog blog) {
+ getJdbcTemplate().update("update blogs set title = ?, content = ?
where id = ?", new PreparedStatementSetter() {
+ public void setValues(PreparedStatement ps) throws
SQLException {
+ ps.setString(1, blog.getTitle());
+ ps.setString(2, blog.getContent());
+ ps.setLong(3, blog.getId());
+ }
+ });
+ }
+
+ public List<Blog> findAll() {
+ return getJdbcTemplate().query("select id, title, content from
blogs order by id", new RowMapper<Blog>() {
+ public Blog mapRow(ResultSet rs, int rowNum) throws
SQLException {
+ return mapBlog(rs);
+ }
+ });
+ }
+
+ public List<String> findAllPrincipals() {
+ return getJdbcTemplate().queryForList("select username from users
order by username", String.class);
+ }
+
+ public List<String> findAllRoles() {
+ return getJdbcTemplate().queryForList("select distinct authority
from authorities order by authority", String.class);
+ }
+
+ public Blog getById(Long id) {
+ List<Blog> list = getJdbcTemplate().query("select id, title,
content from blogs where id = ? order by id", new RowMapper<Blog>() {
+ public Blog mapRow(ResultSet rs, int rowNum) throws
SQLException {
+ return mapBlog(rs);
+ }
+ }, id);
+
+ if (list.size() == 0) {
+ return null;
+ } else {
+ return (Blog) list.get(0);
+ }
+ }
+ public long getLastId() {
+ List<Blog> list = getJdbcTemplate().query("SELECT * FROM blogs
WHERE ID = (SELECT MAX(ID) FROM blogs)", new RowMapper<Blog>() {
+ public Blog mapRow(ResultSet rs, int rowNum) throws
SQLException {
+ return mapBlog(rs);
+ }
+ });
+ Blog blog = (Blog) list.get(0);
+ return blog.getId();
+ }
+
+ private Blog mapBlog(ResultSet rs) throws SQLException {
+ Blog blog = new Blog();
+ blog.setId(new Long(rs.getLong("id")));
+ blog.setTitle(rs.getString("title"));
+ blog.setContent(rs.getString("content"));
+ return blog;
+ }
+}
+
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/java/com/myblog/service/AddPermission.java
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,45 @@
+package com.myblog.service;
+
+import org.springframework.security.acls.domain.BasePermission;
+import com.myblog.domain.Blog;
+
+
+/**
+ * Model object for add permission use case.
+ *
+ * @author Jimmy
+ */
+
+public class AddPermission {
+ //~ Instance fields
================================================================================================
+
+ public Blog blog;
+ public Integer permission = BasePermission.READ.getMask();
+ public String recipient;
+
+ //~ Methods
========================================================================================================
+
+ public Blog getBlog() {
+ return blog;
+ }
+
+ public Integer getPermission() {
+ return permission;
+ }
+
+ public String getRecipient() {
+ return recipient;
+ }
+
+ public void setBlog(Blog blog) {
+ this.blog = blog;
+ }
+
+ public void setPermission(Integer permission) {
+ this.permission = permission;
+ }
+
+ public void setRecipient(String recipient) {
+ this.recipient = recipient;
+ }
+}
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/java/com/myblog/service/AddPermissionValidator.java
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,44 @@
+package com.myblog.service;
+
+import org.springframework.security.acls.domain.BasePermission;
+import org.springframework.validation.Errors;
+import org.springframework.validation.ValidationUtils;
+import org.springframework.validation.Validator;
+
+
+/**
+ * Validates {@link AddPermission}.
+ *
+ * @author Jimmy
+ */
+public class AddPermissionValidator implements Validator {
+ //~ Methods
========================================================================================================
+
+ @SuppressWarnings("unchecked")
+ public boolean supports(Class clazz) {
+ return clazz.equals(AddPermission.class);
+ }
+
+ public void validate(Object obj, Errors errors) {
+ AddPermission addPermission = (AddPermission) obj;
+
+
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "permission", "err.permission", "Permission
is required. *");
+
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "recipient", "err.recipient", "Recipient
is required. *");
+
+ if (addPermission.getPermission() != null) {
+ int permission = addPermission.getPermission().intValue();
+
+ if ((permission != BasePermission.ADMINISTRATION.getMask())
+ && (permission != BasePermission.READ.getMask()) &&
(permission != BasePermission.DELETE.getMask())) {
+
errors.rejectValue("permission", "err.permission.invalid", "The indicated
permission is invalid. *");
+ }
+ }
+
+ if (addPermission.getRecipient() != null) {
+ if (addPermission.getRecipient().length() > 100) {
+ errors.rejectValue("recipient", "err.recipient.length",
+ "The recipient is too long (maximum 100 characters).
*");
+ }
+ }
+ }
+}
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/java/com/myblog/service/BlogManager.java
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,45 @@
+package com.myblog.service;
+
+import org.springframework.security.access.prepost.PostFilter;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.acls.model.Permission;
+import org.springframework.security.acls.model.Sid;
+
+import com.myblog.domain.Blog;
+
+import java.util.List;
+
+
+/**
+ * Interface for the application's services layer.
+ *
+ * @author Jimmy
+ */
+public interface BlogManager {
+ //~ Methods
========================================================================================================
+ @PreAuthorize("hasPermission(#blog, admin)")
+ public void addPermission(Blog blog, Sid recipient, Permission
permission);
+
+ @PreAuthorize("hasPermission(#blog, admin)")
+ public void deletePermission(Blog blog, Sid recipient, Permission
permission);
+
+ @PreAuthorize("hasRole('ROLE_USER')")
+ public void create(Blog blog);
+
+ @PreAuthorize("hasPermission(#blog, 'delete') or hasPermission(#blog,
admin)")
+ public void delete(Blog blog);
+
+ @PreAuthorize("hasRole('ROLE_USER')")
+ @PostFilter("hasPermission(filterObject, 'read') or
hasPermission(filterObject, admin)")
+ public List<Blog> getAll();
+
+ @PreAuthorize("hasRole('ROLE_USER')")
+ public List<String> getAllRecipients();
+
+ @PreAuthorize(
+ "hasPermission(#id, 'com.myblog.domain.Blog', read) or " +
+ "hasPermission(#id, 'com.myblog.domain.Blog', admin)")
+ public Blog getById(Long id);
+
+ public Blog getRandomBlog();
+}
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/java/com/myblog/service/BlogManagerImpl.java
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,178 @@
+package com.myblog.service;
+
+
+import org.springframework.security.acls.domain.BasePermission;
+import org.springframework.security.acls.domain.ObjectIdentityImpl;
+import org.springframework.security.acls.domain.PrincipalSid;
+import org.springframework.security.acls.model.AccessControlEntry;
+import org.springframework.security.acls.model.MutableAcl;
+import org.springframework.security.acls.model.MutableAclService;
+import org.springframework.security.acls.model.NotFoundException;
+import org.springframework.security.acls.model.ObjectIdentity;
+import org.springframework.security.acls.model.Permission;
+import org.springframework.security.acls.model.Sid;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.support.ApplicationObjectSupport;
+import org.springframework.util.Assert;
+import com.myblog.domain.Blog;
+import com.myblog.repository.BlogDao;
+import java.util.List;
+import java.util.Random;
+
+
+/**
+ * Concrete implementation of {@link BlogManager}.
+ *
+ * @author Jimmy
+ */
+@Transactional
+public class BlogManagerImpl extends ApplicationObjectSupport implements
BlogManager, InitializingBean {
+ //~ Instance fields
================================================================================================
+
+ private BlogDao blogDao;
+ private MutableAclService mutableAclService;
+// private int counter = 1000;
+
+ //~ Methods
========================================================================================================
+
+ public void afterPropertiesSet() throws Exception {
+ Assert.notNull(blogDao, "blogDao required");
+ Assert.notNull(mutableAclService, "mutableAclService required");
+ }
+
+ public void addPermission(Blog blog, Sid recipient, Permission
permission) {
+ MutableAcl acl;
+ ObjectIdentity oid = new ObjectIdentityImpl(Blog.class,
blog.getId());
+
+ try {
+ acl = (MutableAcl) mutableAclService.readAclById(oid);
+ } catch (NotFoundException nfe) {
+ acl = mutableAclService.createAcl(oid);
+ }
+
+ acl.insertAce(acl.getEntries().size(), permission, recipient,
true);
+ mutableAclService.updateAcl(acl);
+
+ logger.debug("Added permission " + permission + " for Sid " +
recipient + " blog " + blog);
+ }
+
+ public void create(Blog blog) {
+ // Create the Blog itself
+ blog.setId(getLastId()+1);
+ blogDao.create(blog);
+
+ // Grant the current principal administrative permission to the
blog
+ addPermission(blog, new PrincipalSid(getUsername()),
BasePermission.ADMINISTRATION);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Created blog " + blog + " and granted admin
permission to recipient " + getUsername());
+ }
+ }
+
+ public void delete(Blog blog) {
+ blogDao.delete(blog.getId());
+
+ // Delete the ACL information as well
+ ObjectIdentity oid = new ObjectIdentityImpl(Blog.class,
blog.getId());
+ mutableAclService.deleteAcl(oid, false);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Deleted blog " + blog + " including ACL
permissions");
+ }
+ }
+
+ public void deletePermission(Blog blog, Sid recipient, Permission
permission) {
+ ObjectIdentity oid = new ObjectIdentityImpl(Blog.class,
blog.getId());
+ MutableAcl acl = (MutableAcl) mutableAclService.readAclById(oid);
+
+ // Remove all permissions associated with this particular
recipient (string equality to KISS)
+ List<AccessControlEntry> entries = acl.getEntries();
+
+ for (int i = 0; i < entries.size(); i++) {
+ if (entries.get(i).getSid().equals(recipient) &&
entries.get(i).getPermission().equals(permission)) {
+ acl.deleteAce(i);
+ }
+ }
+
+ mutableAclService.updateAcl(acl);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Deleted blog " + blog + " ACL permissions for
recipient " + recipient);
+ }
+ }
+
+ @Transactional(readOnly=true)
+ public List<Blog> getAll() {
+ logger.debug("Returning all blogs");
+
+ return blogDao.findAll();
+ }
+
+ @Transactional(readOnly=true)
+ public List<String> getAllRecipients() {
+ logger.debug("Returning all recipients");
+
+ return blogDao.findAllPrincipals();
+ }
+
+ @Transactional(readOnly=true)
+ public Blog getById(Long id) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Returning blog with id: " + id);
+ }
+
+ return blogDao.getById(id);
+ }
+
+ @Transactional(readOnly=true)
+ public long getLastId() {
+ long id = blogDao.getLastId();
+ if (logger.isDebugEnabled()) {
+ logger.debug("Returning blog table's last id: " + id);
+ }
+ return id;
+ }
+
+
+ /**
+ * This is a public method.
+ */
+ @Transactional(readOnly=true)
+ public Blog getRandomBlog() {
+ logger.debug("Returning random blog");
+
+ Random rnd = new Random();
+ List<Blog> blogs = blogDao.findAll();
+ int getNumber = rnd.nextInt(blogs.size());
+
+ return blogs.get(getNumber);
+ }
+
+ protected String getUsername() {
+ Authentication auth =
SecurityContextHolder.getContext().getAuthentication();
+
+ if (auth.getPrincipal() instanceof UserDetails) {
+ return ((UserDetails) auth.getPrincipal()).getUsername();
+ } else {
+ return auth.getPrincipal().toString();
+ }
+ }
+
+ public void setBlogDao(BlogDao blogDao) {
+ this.blogDao = blogDao;
+ }
+
+ public void setMutableAclService(MutableAclService mutableAclService) {
+ this.mutableAclService = mutableAclService;
+ }
+
+ public void update(Blog blog) {
+ blogDao.update(blog);
+
+ logger.debug("Updated blog " + blog);
+ }
+}
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/java/com/myblog/service/BlogValidator.java
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,33 @@
+package com.myblog.service;
+
+import org.springframework.validation.Errors;
+import org.springframework.validation.Validator;
+
+import com.myblog.domain.Blog;
+
+
+/**
+ * Validates {@link Blog}.
+ *
+ * @author Jimmy
+ */
+public class BlogValidator implements Validator {
+ //~ Methods
========================================================================================================
+
+ @SuppressWarnings("unchecked")
+ public boolean supports(Class clazz) {
+ return clazz.equals(Blog.class);
+ }
+
+ public void validate(Object obj, Errors errors) {
+ Blog wc = (Blog) obj;
+
+ if ((wc.getTitle() == null) || (wc.getTitle().length() < 3) ||
(wc.getTitle().length() > 50)) {
+ errors.rejectValue("title", "err.title", "Title 3-50
characters is required. *");
+ }
+
+ if ((wc.getContent() == null) || (wc.getContent().length() < 3) ||
(wc.getContent().length() > 50)) {
+ errors.rejectValue("content", "err.content", "Content 3-50
characters is required. *");
+ }
+ }
+}
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/java/com/myblog/service/DataSourcePopulator.java
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,220 @@
+package com.myblog.service;
+
+import java.util.Random;
+
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.security.acls.domain.AclImpl;
+import org.springframework.security.acls.domain.BasePermission;
+import org.springframework.security.acls.domain.ObjectIdentityImpl;
+import org.springframework.security.acls.domain.PrincipalSid;
+import org.springframework.security.acls.model.MutableAcl;
+import org.springframework.security.acls.model.MutableAclService;
+import org.springframework.security.acls.model.ObjectIdentity;
+import org.springframework.security.acls.model.Permission;
+import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.TransactionCallback;
+import org.springframework.transaction.support.TransactionTemplate;
+import org.springframework.util.Assert;
+
+import com.myblog.domain.Blog;
+
+/**
+ * Populates the Blogs database with blog and ACL information.
+ *
+ * @author Jimmy Kaushal
+ */
+public class DataSourcePopulator implements InitializingBean {
+ // ~ Instance fields
+ //
================================================================================================
+
+ JdbcTemplate template;
+ private MutableAclService mutableAclService;
+ final Random rnd = new Random();
+ TransactionTemplate tt;
+
+ final String[] titles = { "How to create Blog", "How to repair motor
bike", "How to think in programming",
+ "How to win friends", "How to code in Java", "What is OOP",
+ "What is WWW", "What is Space", "Wonders of Earth","How to setup IBM
Websphere" };
+ final String[] content = { "Just write something which you think would
help people",
+ "Get a book from Barnes and noble and read it, and do exactly as it
says",
+ "Programming is very vast field, but whatever programming language you
pick, learn the fundamentals fully",
+ "You dont need to win friends, they become friends because they want to
be. Just be yourself and friendly person",
+ "Java is OOPs based, just learn some fundamentals and follow some good
books",
+ "Object Oriennted Programming which has changed the programming world
and the way coding is done nowadays",
+ "World Wide Web, this is a network of networks where all the LANs, WANs
are connected",
+ "SPACE is just SPACE, nobody knows its size, where it ends, whats
beyond it",
+ "Wonders of Earth, like Taj Mahal, Eifel tower etc. they all have their
history and something unique about them",
+ "Just follow the documentation of IBM and do some research and set it
up"};
+ private int createEntities = 10;
+
+ // ~ Methods
+ //
========================================================================================================
+
+ public void afterPropertiesSet() throws Exception {
+ Assert.notNull(mutableAclService, "mutableAclService required");
+ Assert.notNull(template, "dataSource required");
+ Assert.notNull(tt, "platformTransactionManager required");
+
+ // Set a user account that will initially own all the created data
+ Authentication authRequest = new
UsernamePasswordAuthenticationToken("rod", "koala",AuthorityUtils.createAuthorityList("ROLE_IGNORED"));
+ SecurityContextHolder.getContext().setAuthentication(authRequest);
+
+ try {
+ template.execute("DROP TABLE blogs");
+ template.execute("DROP TABLE authorities");
+ template.execute("DROP TABLE users");
+ template.execute("DROP TABLE acl_entry");
+ template.execute("DROP TABLE acl_object_identity");
+ template.execute("DROP TABLE acl_class");
+ template.execute("DROP TABLE acl_sid");
+ } catch (Exception e) {
+ System.out.println("Failed to drop tables: " + e.getMessage());
+ }
+ template.execute("SET SQL_MODE=\"NO_AUTO_VALUE_ON_ZERO\";");
+
+ /*ACL Tables Creation*/
+ template.execute("CREATE TABLE IF NOT EXISTS `acl_sid` ( id bigint
unsigned not null auto_increment primary key, principal tinyint(1) not
null, sid varchar(100) not null, unique index acl_sid_idx_1 (sid,
principal)) engine = InnoDb;");
+ template.execute("CREATE TABLE IF NOT EXISTS `acl_class` ( `ID`
bigint(20) NOT NULL auto_increment, `CLASS` varchar(100) NOT NULL,
PRIMARY KEY (`ID`), UNIQUE KEY `UNIQUE_UK_2` (`CLASS`)) ENGINE=InnoDB
DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;");
+ template.execute("CREATE TABLE IF NOT EXISTS `acl_object_identity` (
`ID` bigint(20) NOT NULL auto_increment, `OBJECT_ID_CLASS` bigint(20) NOT
NULL, `OBJECT_ID_IDENTITY` bigint(20) NOT NULL, `PARENT_OBJECT`
bigint(20) default NULL, `OWNER_SID` bigint(20) default NULL,
`ENTRIES_INHERITING` tinyint(1) NOT NULL, PRIMARY KEY (`ID`), UNIQUE KEY
`UNIQUE_UK_3` (`OBJECT_ID_CLASS`,`OBJECT_ID_IDENTITY`), KEY `OWNER_SID`
(`OWNER_SID`), KEY `PARENT_OBJECT` (`PARENT_OBJECT`)) ENGINE=InnoDB
DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;");
+ template.execute("CREATE TABLE IF NOT EXISTS `acl_entry` ( `ID`
bigint(20) NOT NULL auto_increment, `acl_object_identity` bigint(20) NOT
NULL, `ACE_ORDER` int(11) NOT NULL, `SID` bigint(20) NOT NULL, `MASK`
int(11) NOT NULL, `GRANTING` tinyint(1) NOT NULL, `AUDIT_SUCCESS`
tinyint(1) NOT NULL, `AUDIT_FAILURE` tinyint(1) NOT NULL, PRIMARY KEY
(`ID`), UNIQUE KEY `UNIQUE_UK_4` (`acl_object_identity`,`ACE_ORDER`), KEY
`SID` (`SID`)) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;");
+
+ /*ACL Tables Creation*/
+ template.execute("CREATE TABLE IF NOT EXISTS `users` ( `USERNAME`
varchar(50) NOT NULL, `PASSWORD` varchar(50) NOT NULL, `ENABLED` bit(1)
NOT NULL, PRIMARY KEY (`USERNAME`)) ENGINE=InnoDB DEFAULT
CHARSET=latin1;");
+ template.execute("CREATE TABLE IF NOT EXISTS `authorities` ( `USERNAME`
varchar(50) NOT NULL, `AUTHORITY` varchar(50) NOT NULL, UNIQUE KEY
`IX_AUTH_USERNAME` (`USERNAME`,`AUTHORITY`)) ENGINE=InnoDB DEFAULT
CHARSET=latin1;");
+ template.execute("CREATE TABLE IF NOT EXISTS `blogs` ( `ID` bigint(20)
NOT NULL, `TITLE` varchar(50) NOT NULL, `CONTENT` varchar(500) NOT NULL,
PRIMARY KEY (`ID`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;");
+
+ /*Delete Tables*/
+ template.execute("DELETE FROM blogs");
+ template.execute("DELETE FROM authorities");
+ template.execute("DELETE FROM users");
+ template.execute("DELETE FROM acl_entry");
+ template.execute("DELETE FROM acl_object_identity");
+ template.execute("DELETE FROM acl_class");
+ template.execute("DELETE FROM acl_sid");
+
+ /*Insert Records into Tables users, authorities and blogs (First 2 Blogs
are inserting here)*/
+ template.execute("INSERT INTO `users` (`USERNAME`, `PASSWORD`,
`ENABLED`) VALUES('bill', '2b58af6dddbd072ed27ffc86725d7d3a',
1),('bob', '2b58af6dddbd072ed27ffc86725d7d3a',
1),('dianne', '65d15fe9156f9c4bbffd98085992a44e',
1),('jane', '2b58af6dddbd072ed27ffc86725d7d3a',
1),('peter', '22b5c9accc6e1ba628cedc63a72d57f8', '\0'),('rod', 'a564de63c2d0da68cf47586ee05984d7',
1),('scott', '2b58af6dddbd072ed27ffc86725d7d3a', 0);");
+ template.execute("INSERT INTO `authorities` (`USERNAME`, `AUTHORITY`)
VALUES('bill', 'ROLE_USER'),('bob', 'ROLE_USER'),('dianne', 'ROLE_USER'),('jane', 'ROLE_USER'),('peter', 'ROLE_USER'),('rod', 'ROLE_SUPERVISOR'),('rod', 'ROLE_USER'),('scott', 'ROLE_USER');");
+// template.execute("INSERT INTO `blogs` (`ID`, `TITLE`, `CONTENT`)
VALUES(1, 'My First Blog', 'This is the First Blog which I came up
with'),(2, 'My Second Blog', 'This is the Second Blog which I came up
with');");
+
+ /*That's inseting Titles, Contents into Blogs (from 10 to 49)*/
+ for (int i = 1; i < createEntities; i++) {
+ template.execute("INSERT INTO blogs VALUES (" + i + ", '"+ titles[i]
+ "', '" + content[i] + "');");
+ }
+
+ // Create acl_object_identity rows (and also acl_class rows as needed)
+ for (int i = 1; i < createEntities; i++) {
+ final ObjectIdentity objectIdentity = new
ObjectIdentityImpl(Blog.class, new Long(i));
+ tt.execute(new TransactionCallback<Object>() {
+ public Object doInTransaction(TransactionStatus arg0) {
+ mutableAclService.createAcl(objectIdentity);
+ return null;
+ }
+ });
+ }
+
+ // Now grant some permissions
+ grantPermissions(1, "rod", BasePermission.ADMINISTRATION);
+ grantPermissions(2, "rod", BasePermission.READ);
+ grantPermissions(3, "rod", BasePermission.READ);
+ grantPermissions(3, "rod", BasePermission.WRITE);
+ grantPermissions(3, "rod", BasePermission.DELETE);
+ grantPermissions(4, "rod", BasePermission.ADMINISTRATION);
+ grantPermissions(4, "dianne", BasePermission.ADMINISTRATION);
+ grantPermissions(4, "scott", BasePermission.READ);
+ grantPermissions(5, "dianne", BasePermission.ADMINISTRATION);
+ grantPermissions(5, "dianne", BasePermission.READ);
+ grantPermissions(6, "dianne", BasePermission.READ);
+ grantPermissions(6, "dianne", BasePermission.WRITE);
+ grantPermissions(6, "dianne", BasePermission.DELETE);
+ grantPermissions(6, "scott", BasePermission.READ);
+ grantPermissions(7, "scott", BasePermission.ADMINISTRATION);
+ grantPermissions(8, "dianne", BasePermission.ADMINISTRATION);
+ grantPermissions(8, "dianne", BasePermission.READ);
+ grantPermissions(8, "scott", BasePermission.READ);
+ grantPermissions(9, "scott", BasePermission.ADMINISTRATION);
+ grantPermissions(9, "scott", BasePermission.READ);
+ grantPermissions(9, "scott", BasePermission.WRITE);
+ grantPermissions(9, "scott", BasePermission.DELETE);
+
+ // Now expressly change the owner of the first ten blogs
+ // We have to do this last, because "rod" owns all of them (doing it
+ // sooner would prevent ACL updates)
+ // Note that ownership has no impact on permissions - they're separate
+ // (ownership only allows ACl editing)
+ changeOwner(5, "dianne");
+ changeOwner(6, "dianne");
+ changeOwner(7, "scott");
+ changeOwner(8, "dianne");
+ changeOwner(9, "scott");
+
+ String[] users = { "bill", "bob", "jane" }; // don't want to mess around
+ // with consistent sample
+ // data
+ Permission[] permissions = { BasePermission.ADMINISTRATION,
+ BasePermission.READ, BasePermission.DELETE };
+
+// for (int i = 1; i < createEntities; i++) {
+// String user = users[rnd.nextInt(users.length)];
+// Permission permission = permissions[rnd.nextInt(permissions.length)];
+// grantPermissions(i, user, permission);
+//
+// String user2 = users[rnd.nextInt(users.length)];
+// Permission permission2 = permissions[rnd.nextInt(permissions.length)];
+// grantPermissions(i, user2, permission2);
+// }
+
+ SecurityContextHolder.clearContext();
+ }
+
+ private void changeOwner(int blogNumber, String newOwnerUsername) {
+ AclImpl acl = (AclImpl) mutableAclService.readAclById(new
ObjectIdentityImpl(Blog.class, new Long(blogNumber)));
+ acl.setOwner(new PrincipalSid(newOwnerUsername));
+ updateAclInTransaction(acl);
+ }
+
+ public int getCreateEntities() {
+ return createEntities;
+ }
+
+ private void grantPermissions(int blogNumber, String recipientUsername,
Permission permission) {
+ AclImpl acl = (AclImpl) mutableAclService.readAclById(new
ObjectIdentityImpl(Blog.class, new Long(blogNumber)));
+ acl.insertAce(acl.getEntries().size(), permission, new
PrincipalSid(recipientUsername), true);
+ updateAclInTransaction(acl);
+ }
+
+ public void setCreateEntities(int createEntities) {
+ this.createEntities = createEntities;
+ }
+
+ private void updateAclInTransaction(final MutableAcl acl) {
+ tt.execute(new TransactionCallback<Object>() {
+ public Object doInTransaction(TransactionStatus arg0) {
+ mutableAclService.updateAcl(acl);
+
+ return null;
+ }
+ });
+ }
+
+ public void setDataSource(DataSource dataSource) {
+ this.template = new JdbcTemplate(dataSource);
+ }
+
+ public void setMutableAclService(MutableAclService mutableAclService) {
+ this.mutableAclService = mutableAclService;
+ }
+
+ public void setPlatformTransactionManager(PlatformTransactionManager
platformTransactionManager) {
+ this.tt = new TransactionTemplate(platformTransactionManager);
+ }
+
+}
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/java/com/myblog/web/AddDeleteBlogController.java
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,67 @@
+package com.myblog.web;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.Validator;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.myblog.domain.Blog;
+import com.myblog.service.BlogManager;
+import com.myblog.service.BlogValidator;
+
+/**
+ *
+ * @author Jimmy
+ * @since 3.0
+ */
+@Controller
+public class AddDeleteBlogController {
+ @Autowired
+ private BlogManager blogManager;
+ private final Validator validator = new BlogValidator();
+
+ /**
+ * Displays the "add Blog" form.
+ */
+ @RequestMapping(value="/secure/add.htm", method=RequestMethod.GET)
+ public ModelAndView addBlogDisplay() {
+ return new ModelAndView("add", "blog", new Blog());
+ }
+
+ @InitBinder
+ public void initBinder(WebDataBinder binder) {
+ System.out.println("A binder for object: " +
binder.getObjectName());
+ }
+
+ /**
+ * Handles the submission of the blog form, creating a new instance if
+ * the title and content are valid.
+ */
+ @RequestMapping(value="/secure/add.htm", method=RequestMethod.POST)
+ public String addBlog(Blog form, BindingResult result) {
+ validator.validate(form, result);
+
+ if (result.hasErrors()) {
+ return "add";
+ }
+
+ Blog blog = new Blog(form.getTitle(), form.getContent());
+ blogManager.create(blog);
+
+ return "redirect:/secure/index.htm";
+ }
+
+ @RequestMapping(value="/secure/del.htm", method=RequestMethod.GET)
+ public ModelAndView handleRequest(@RequestParam("blogId") int blogId) {
+ Blog blog = blogManager.getById(Long.valueOf(blogId));
+ blogManager.delete(blog);
+
+ return new ModelAndView("deleted", "blog", blog);
+ }
+}
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/java/com/myblog/web/AdminPermissionController.java
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,171 @@
+package com.myblog.web;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.MessageSource;
+import org.springframework.context.MessageSourceAware;
+import org.springframework.context.support.MessageSourceAccessor;
+import org.springframework.dao.DataAccessException;
+import org.springframework.security.acls.domain.BasePermission;
+import org.springframework.security.acls.domain.DefaultPermissionFactory;
+import org.springframework.security.acls.domain.ObjectIdentityImpl;
+import org.springframework.security.acls.domain.PermissionFactory;
+import org.springframework.security.acls.domain.PrincipalSid;
+import org.springframework.security.acls.model.Acl;
+import org.springframework.security.acls.model.AclService;
+import org.springframework.security.acls.model.Permission;
+import org.springframework.security.acls.model.Sid;
+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.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.SessionAttributes;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.myblog.domain.Blog;
+import com.myblog.service.AddPermission;
+import com.myblog.service.AddPermissionValidator;
+import com.myblog.service.BlogManager;
+
+/**
+ * Web controller to handle <tt>Permission</tt> administration functions -
adding and deleting
+ * permissions for blogs.
+ *
+ * @author Jimmy
+ */
+@Controller
+@SessionAttributes("addPermission")
+public final class AdminPermissionController implements MessageSourceAware{
+ @Autowired
+ private AclService aclService;
+ @Autowired
+ private BlogManager blogManager;
+ private MessageSourceAccessor messages;
+ private final Validator addPermissionValidator = new
AddPermissionValidator();
+ private final PermissionFactory permissionFactory = new
DefaultPermissionFactory();
+
+ /**
+ * Displays the permission admin page for a particular blog.
+ */
+ @RequestMapping(value="/secure/adminPermission.htm",
method=RequestMethod.GET)
+ public ModelAndView displayAdminPage(@RequestParam("blogId") int
blogId) {
+ Blog blog = blogManager.getById(Long.valueOf(blogId));
+ Acl acl = aclService.readAclById(new ObjectIdentityImpl(blog));
+
+ Map<String, Object> model = new HashMap<String, Object>();
+ model.put("blog", blog);
+ model.put("acl", acl);
+
+ return new ModelAndView("adminPermission", "model", model);
+ }
+
+ /**
+ * Displays the "add permission" page for a blog.
+ */
+ @RequestMapping(value="/secure/addPermission.htm",
method=RequestMethod.GET)
+ public ModelAndView
displayAddPermissionPageForBlog(@RequestParam("blogId") int blogId) {
+ Blog blog = blogManager.getById(new Long(blogId));
+
+ AddPermission addPermission = new AddPermission();
+ addPermission.setBlog(blog);
+
+ Map<String,Object> model = new HashMap<String,Object>();
+ model.put("addPermission", addPermission);
+ model.put("recipients", listRecipients());
+ model.put("permissions", listPermissions());
+
+ return new ModelAndView("addPermission", model);
+ }
+
+ @InitBinder("addPermission")
+ public void initBinder(WebDataBinder binder) {
+ binder.setAllowedFields("recipient", "permission");
+ }
+
+ /**
+ * Handles submission of the "add permission" form.
+ */
+ @RequestMapping(value="/secure/addPermission.htm",
method=RequestMethod.POST)
+ public String addPermission(AddPermission addPermission, BindingResult
result, ModelMap model) {
+ addPermissionValidator.validate(addPermission, result);
+
+ if (result.hasErrors()) {
+ model.put("recipients", listRecipients());
+ model.put("permissions", listPermissions());
+
+ return "addPermission";
+ }
+
+ PrincipalSid sid = new PrincipalSid(addPermission.getRecipient());
+ Permission permission =
permissionFactory.buildFromMask(addPermission.getPermission());
+
+ try {
+ blogManager.addPermission(addPermission.getBlog(), sid,
permission);
+ } catch (DataAccessException existingPermission) {
+ existingPermission.printStackTrace();
+
result.rejectValue("recipient", "err.recipientExistsForBlog", "Addition
failure.");
+
+ model.put("recipients", listRecipients());
+ model.put("permissions", listPermissions());
+ return "addPermission";
+ }
+
+ return "redirect:/secure/index.htm";
+ }
+
+ /**
+ * Deletes a permission
+ */
+ @RequestMapping(value="/secure/deletePermission.htm")
+ public ModelAndView deletePermission(
+ @RequestParam("blogId") int blogId,
+ @RequestParam("sid") String sid,
+ @RequestParam("permission") int mask) {
+
+ Blog blog = blogManager.getById(new Long(blogId));
+
+ Sid sidObject = new PrincipalSid(sid);
+ Permission permission = permissionFactory.buildFromMask(mask);
+
+ blogManager.deletePermission(blog, sidObject, permission);
+
+ Map<String, Object> model = new HashMap<String, Object>();
+ model.put("blog", blog);
+ model.put("sid", sidObject);
+ model.put("permission", permission);
+
+ return new ModelAndView("deletePermission", "model", model);
+ }
+
+ private Map<Integer, String> listPermissions() {
+ Map<Integer, String> map = new LinkedHashMap<Integer, String>();
+ map.put(Integer.valueOf(BasePermission.ADMINISTRATION.getMask()),
messages.getMessage("select.administer", "Administer"));
+ map.put(Integer.valueOf(BasePermission.READ.getMask()),
messages.getMessage("select.read", "Read"));
+ map.put(Integer.valueOf(BasePermission.DELETE.getMask()),
messages.getMessage("select.delete", "Delete"));
+
+ return map;
+ }
+
+ private Map<String, String> listRecipients() {
+ Map<String, String> map = new LinkedHashMap<String, String>();
+ map.put("", messages.getMessage("select.pleaseSelect", "-- please
select --"));
+
+ for (String recipient : blogManager.getAllRecipients()) {
+ map.put(recipient, recipient);
+ }
+
+ return map;
+ }
+
+ public void setMessageSource(MessageSource messageSource) {
+ this.messages = new MessageSourceAccessor(messageSource);
+ }
+}
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/java/com/myblog/web/IndexController.java
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,82 @@
+package com.myblog.web;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.PermissionEvaluator;
+import org.springframework.security.acls.AclPermissionEvaluator;
+import org.springframework.security.acls.domain.BasePermission;
+import org.springframework.security.acls.model.Permission;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.myblog.domain.Blog;
+import com.myblog.service.BlogManager;
+
+/**
+ * Controller which handles simple, single request use cases such as index
pages and blog deletion.
+ *
+ * @author Jimmy
+ */
+@Controller
+public class IndexController {
+ private final static Permission[] HAS_DELETE = new Permission[]
{BasePermission.DELETE, BasePermission.ADMINISTRATION};
+ private final static Permission[] HAS_ADMIN = new Permission[]
{BasePermission.ADMINISTRATION};
+
+ //~ Instance fields
================================================================================================
+
+ @Autowired
+ private BlogManager blogManager;
+ @Autowired
+ private PermissionEvaluator permissionEvaluator;
+
+ //~ Methods
========================================================================================================
+
+ /**
+ * The public index page, used for unauthenticated users.
+ */
+ @RequestMapping(value="/hello.htm", method=RequestMethod.GET)
+ public ModelAndView displayPublicIndex() {
+ Blog rnd = blogManager.getRandomBlog();
+ return new ModelAndView("hello", "blog", rnd);
+ }
+
+ /**
+ * The index page for an authenticated user.
+ * <p>
+ * This controller displays a list of all the blogs for which the
current user has read or admin permissions.
+ * It makes a call to {@link BlogManager#getAll()} which automatically
filters the returned list using Spring
+ * Security's ACL mechanism (see the expression annotations on this
interface for the details).
+ * <p>
+ * In addition to rendering the list of blogs, the view will also
include a "Del" or "Admin" link beside the
+ * blog, depending on whether the user has the corresponding
permissions (admin permission is assumed to imply
+ * delete here). This information is stored in the model using the
injected {@link PermissionEvaluator} instance.
+ * The implementation should be an instance of {@link
AclPermissionEvaluator} or one which is compatible with Spring
+ * Security's ACL module.
+ */
+ @RequestMapping(value="/secure/index.htm", method=RequestMethod.GET)
+ public ModelAndView displayUserBlogs() {
+ List<Blog> myBlogsList = blogManager.getAll();
+ Map<Blog, Boolean> hasDelete = new HashMap<Blog,
Boolean>(myBlogsList.size());
+ Map<Blog, Boolean> hasAdmin = new HashMap<Blog,
Boolean>(myBlogsList.size());
+
+ Authentication user =
SecurityContextHolder.getContext().getAuthentication();
+
+ for (Blog blog : myBlogsList) {
+ hasDelete.put(blog,
Boolean.valueOf(permissionEvaluator.hasPermission(user, blog, HAS_DELETE)));
+ hasAdmin.put(blog,
Boolean.valueOf(permissionEvaluator.hasPermission(user, blog, HAS_ADMIN)));
+ }
+
+ Map<String, Object> model = new HashMap<String, Object>();
+ model.put("blogs", myBlogsList);
+ model.put("hasDeletePermission", hasDelete);
+ model.put("hasAdminPermission", hasAdmin);
+
+ return new ModelAndView("index", "model", model);
+ }
+}
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/resources/applicationContext-common-authorization.xml
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:security="http://www.springframework.org/schema/security"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">
+
+<!-- Application context containing the ACL beans. -->
+
+ <!-- ========= ACL SERVICE DEFINITIONS ========= -->
+
+ <bean id="aclCache"
class="org.springframework.security.acls.domain.EhCacheBasedAclCache">
+ <constructor-arg>
+ <bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
+ <property name="cacheManager">
+ <bean
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
+ </property>
+ <property name="cacheName" value="aclCache"/>
+ </bean>
+ </constructor-arg>
+ </bean>
+
+ <bean id="lookupStrategy"
class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
+ <constructor-arg ref="dataSource"/>
+ <constructor-arg ref="aclCache"/>
+ <constructor-arg>
+ <bean
class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
+ <constructor-arg>
+ <list>
+ <bean
class="org.springframework.security.core.authority.GrantedAuthorityImpl">
+ <constructor-arg value="ROLE_ADMINISTRATOR"/>
+ </bean>
+ <bean
class="org.springframework.security.core.authority.GrantedAuthorityImpl">
+ <constructor-arg value="ROLE_ADMINISTRATOR"/>
+ </bean>
+ <bean
class="org.springframework.security.core.authority.GrantedAuthorityImpl">
+ <constructor-arg value="ROLE_ADMINISTRATOR"/>
+ </bean>
+ </list>
+ </constructor-arg>
+ </bean>
+ </constructor-arg>
+ <constructor-arg>
+ <bean
class="org.springframework.security.acls.domain.ConsoleAuditLogger"/>
+ </constructor-arg>
+ </bean>
+
+ <bean id="aclService"
class="org.springframework.security.acls.jdbc.JdbcMutableAclService">
+ <constructor-arg ref="dataSource"/>
+ <constructor-arg ref="lookupStrategy"/>
+ <constructor-arg ref="aclCache"/>
+ <property name="classIdentityQuery" value="SELECT @@IDENTITY"/>
+ <property name="sidIdentityQuery" value="SELECT @@IDENTITY"/>
+ </bean>
+
+</beans>
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/resources/applicationContext-common-business.xml
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- Application context containing business beans. Used by all artifacts.
-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
+ <property name="driverClassName" value="com.mysql.jdbc.Driver" />
+ <property name="url"
value="jdbc:mysql://localhost:3306/myblog?useUnicode=true&amp;characterEncoding=utf-8"
/>
+ <property name="username" value="root" />
+ <property name="password" value="root" />
+ </bean>
+
+ <bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
+ <property name="dataSource" ref="dataSource"/>
+ </bean>
+
+ <tx:annotation-driven transaction-manager="transactionManager" />
+
+ <!-- Uncomment the following lines when first time you run the application
+ because DataSourcePopulator class will create and populate the tables for
you in mysql under "blog" database for testing purposes -->
+ <bean id="dataSourcePopulator"
class="com.myblog.service.DataSourcePopulator">
+ <property name="dataSource" ref="dataSource"/>
+ <property name="mutableAclService" ref="aclService"/>
+ <property name="platformTransactionManager"
ref="transactionManager"/>
+ </bean>
+
+ <bean id="blogManager" class="com.myblog.service.BlogManagerImpl">
+ <property name="blogDao">
+ <bean class="com.myblog.repository.BlogDaoImpl">
+ <property name="dataSource" ref="dataSource"/>
+ </bean>
+ </property>
+ <property name="mutableAclService" ref="aclService"/>
+ </bean>
+
+</beans>
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/resources/log4j.properties Wed Jun
1 01:04:00 2011
@@ -0,0 +1,20 @@
+# Global logging configuration
+log4j.rootLogger=DEBUG, stdout, fileout
+
+log4j.logger.com.myblog=DEBUG
+log4j.logger.org.springframework.web.*=DEBUG
+log4j.logger.org.springframework.security=DEBUG
+
+# Console output...
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.conversionPattern=[%p,%c{1},%t] %m%n
+
+# Rolling log file output...
+log4j.appender.fileout=org.apache.log4j.RollingFileAppender
+log4j.appender.fileout.File=myblog.log
+#log4j.appender.fileout.File=${webapp.root}/WEB-INF/log4j.log
+log4j.appender.fileout.MaxFileSize=1024KB
+log4j.appender.fileout.MaxBackupIndex=1
+log4j.appender.fileout.layout=org.apache.log4j.PatternLayout
+log4j.appender.fileout.layout.conversionPattern=%d{ABSOLUTE} %5p %c{1},%t:%L
- %m%n
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/resources/messages.properties Wed
Jun 1 01:04:00 2011
@@ -0,0 +1,6 @@
+err.title=Title 3-50 characters is required.
+err.content=Content 3-50 characters is required.
+err.permission=Permission is required.
+err.recipient=Recipient is required.
+err.permission.invalid=The indicated permission is invalid.
+err.recipient.length=The recipient is too long (maximum 100 characters).
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/resources/views.properties Wed Jun
1 01:04:00 2011
@@ -0,0 +1,5 @@
+hello.(class)=org.springframework.web.servlet.view.tiles2.TilesView
+hello.url=hello
+
+index.(class)=org.springframework.web.servlet.view.tiles2.TilesView
+index.url=index
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/webapp/META-INF/MANIFEST.MF Wed
Jun 1 01:04:00 2011
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path:
+
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/webapp/WEB-INF/applicationContext-security.xml
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- - Application context containing authentication, channel - security
+ and web URI beans. - - Only used by "filter" artifact. - -->
+
+<b:beans xmlns="http://www.springframework.org/schema/security"
+ xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
+
+ <global-method-security pre-post-annotations="enabled">
+ <expression-handler ref="expressionHandler" />
+ </global-method-security>
+
+ <http realm="Blogs Realm">
+ <intercept-url pattern="/" access="IS_AUTHENTICATED_ANONYMOUSLY" />
+ <intercept-url pattern="/index.jsp"
access="IS_AUTHENTICATED_ANONYMOUSLY" />
+ <intercept-url pattern="/hello.htm"
access="IS_AUTHENTICATED_ANONYMOUSLY" />
+ <intercept-url pattern="/login.jsp*"
access="IS_AUTHENTICATED_ANONYMOUSLY" />
+ <intercept-url pattern="/switchuser.jsp" access="ROLE_SUPERVISOR" />
+ <intercept-url pattern="/j_spring_security_switch_user"
+ access="ROLE_SUPERVISOR" />
+ <intercept-url pattern="/**" access="ROLE_USER" />
+
+ <form-login login-page="/login.jsp"
+ authentication-failure-url="/login.jsp?login_error=1" />
+ <http-basic />
+ <logout logout-success-url="/index.jsp" />
+ <remember-me />
+ <custom-filter ref="switchUserProcessingFilter"
+ position="SWITCH_USER_FILTER" />
+ </http>
+
+ <authentication-manager>
+ <authentication-provider>
+ <password-encoder hash="md5" />
+ <jdbc-user-service data-source-ref="dataSource" />
+ </authentication-provider>
+ </authentication-manager>
+
+ <!-- Automatically receives AuthenticationEvent messages -->
+ <b:bean id="loggerListener"
+ class="org.springframework.security.authentication.event.LoggerListener"
/>
+
+ <!-- Filter used to switch the user context. Note: the switch and exit url
+ must be secured based on the role granted the ability to 'switch' to
another
+ user -->
+ <!-- In this example 'rod' has ROLE_SUPERVISOR that can switch to regular
+ ROLE_USER(s) -->
+ <b:bean id="switchUserProcessingFilter"
+
class="org.springframework.security.web.authentication.switchuser.SwitchUserFilter"
+ autowire="byType">
+ <b:property name="targetUrl" value="/secure/index.htm" />
+ </b:bean>
+
+ <b:bean id="expressionHandler"
+
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
+ <b:property name="permissionEvaluator" ref="permissionEvaluator" />
+ </b:bean>
+
+ <b:bean id="permissionEvaluator"
+ class="org.springframework.security.acls.AclPermissionEvaluator">
+ <b:constructor-arg ref="aclService" />
+ </b:bean>
+</b:beans>
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/webapp/WEB-INF/blogs-servlet.xml
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,41 @@
+<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+
<!--=======================================================================================-->
+ <!-- Tiles Configuration -->
+
<!--=======================================================================================-->
+ <!--<bean id="viewResolver"
class="org.springframework.web.servlet.view.ResourceBundleViewResolver"
p:basename="views" />
+ <bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
+ <property name="definitions">
+ <list>
+ <value>/WEB-INF/tiles-defs.xml</value>
+ </list>
+ </property>
+ </bean>
+ <context:component-scan base-package="com.myblog"/>
+ <context:annotation-config />
+
+ <bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
+ <property name="basename" value="messages"/>
+ </bean>-->
+
+
<!--=======================================================================================-->
+ <!-- General Configuration Either comment this whole block or tiles
block, don't keep both -->
+
<!--=======================================================================================-->
+
+ <context:component-scan base-package="com.myblog"/>
+
+ <context:annotation-config />
+
+ <bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
+ <property name="basename" value="messages"/>
+ </bean>
+
+ <bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
+ <property name="prefix" value="/WEB-INF/jsp/"/>
+ <property name="suffix" value=".jsp"/>
+ </bean>
+
+</beans>
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/add.jsp Wed Jun
1 01:04:00 2011
@@ -0,0 +1,40 @@
+<%@ include file="/WEB-INF/jsp/include.jsp" %>
+<html>
+<head><title>Add New Blog</title></head>
+<body>
+<h1>Add Blog</h1>
+<form method="post">
+ <table width="95%" bgcolor="f8f8ff" border="0" cellspacing="0"
cellpadding="5">
+ <tr>
+ <td alignment="right" width="20%">Title:</td>
+ <spring:bind path="blog.title">
+ <td width="20%">
+ <input type="text" name="title" value="<c:out
value="${status.value}"/>">
+ </td>
+ <td width="60%">
+ <font color="red"><c:out value="${status.errorMessage}"/></font>
+ </td>
+ </spring:bind>
+ </tr>
+ <tr>
+ <td alignment="right" width="20%">Content:</td>
+ <spring:bind path="blog.content">
+ <td width="20%">
+ <input type="text" name="content" value="<c:out
value="${status.value}"/>">
+ </td>
+ <td width="60%">
+ <font color="red"><c:out value="${status.errorMessage}"/></font>
+ </td>
+ </spring:bind>
+ </tr>
+ </table>
+ <br>
+ <spring:hasBindErrors name="blog">
+ <b>Please fix all errors!</b>
+ </spring:hasBindErrors>
+ <br><br>
+ <input name="execute" type="submit" alignment="center" value="Execute">
+</form>
+<a href="<c:url value="../hello.htm"/>">Home</a>
+</body>
+</html>
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/addPermission.jsp
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,55 @@
+<%@ include file="/WEB-INF/jsp/include.jsp" %>
+<html>
+<head><title>Add Permission</title></head>
+<body>
+<h1>Add Permission</h1>
+<form method="post">
+ <table width="95%" bgcolor="f8f8ff" border="0" cellspacing="0"
cellpadding="5">
+ <tr>
+ <td alignment="right" width="20%">Blog:</td>
+ <td width="60%"><c:out value="${addPermission.blog}"/></td>
+ </tr>
+ <tr>
+ <td alignment="right" width="20%">Recipient:</td>
+ <spring:bind path="addPermission.recipient">
+ <td width="20%">
+ <select name="<c:out value="${status.expression}"/>">
+ <c:forEach var="thisRecipient" items="${recipients}">
+ <option <c:if test="${thisRecipient.key ==
status.value}">selected</c:if> value="<c:out
value="${thisRecipient.key}"/>">
+ <c:out value="${thisRecipient.value}"/></option>
+ </c:forEach>
+ </select>
+ </td>
+ <td width="60%">
+ <font color="red"><c:out value="${status.errorMessage}"/></font>
+ </td>
+ </spring:bind>
+ </tr>
+ <tr>
+ <td alignment="right" width="20%">Permission:</td>
+ <spring:bind path="addPermission.permission">
+ <td width="20%">
+ <select name="<c:out value="${status.expression}"/>">
+ <c:forEach var="thisPermission" items="${permissions}">
+ <option <c:if test="${thisPermission.key ==
status.value}">selected</c:if> value="<c:out
value="${thisPermission.key}"/>">
+ <c:out value="${thisPermission.value}"/></option>
+ </c:forEach>
+ </select>
+ </td>
+ <td width="60%">
+ <font color="red"><c:out value="${status.errorMessage}"/></font>
+ </td>
+ </spring:bind>
+ </tr>
+ </table>
+ <br>
+ <spring:hasBindErrors name="blog">
+ <b>Please fix all errors!</b>
+ </spring:hasBindErrors>
+ <br><br>
+ <input name="execute" type="submit" alignment="center" value="Execute">
+</form>
+<p>
+<A HREF="<c:url value="adminPermission.htm"><c:param name="blogId"
value="${addPermission.blog.id}"/></c:url>">Admin Permission</A> <a
href="<c:url value="index.htm"/>">Manage</a>
+</body>
+</html>
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/adminPermission.jsp
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,30 @@
+<%@ include file="/WEB-INF/jsp/include.jsp" %>
+
+<html>
+<head><title>Administer Permissions</title></head>
+<body>
+<h1>Administer Permissions</h1>
+<p>
+<code>
+<c:out value="${model.blog}"/>
+</code>
+</p>
+<table cellpadding="3" border="0">
+<c:forEach var="acl" items="${model.acl.entries}">
+ <tr>
+ <td>
+ <code>
+ <c:out value="${acl}"/>
+ </code>
+ </td>
+ <td>
+ <a href="<c:url value="deletePermission.htm"><c:param name="blogId"
value="${model.blog.id}"/><c:param name="sid"
value="${acl.sid.principal}"/><c:param name="permission"
value="${acl.permission.mask}"/></c:url>">Del</a>
+ </td>
+ </tr>
+</c:forEach>
+</table>
+<p>
+<a href="<c:url value="addPermission.htm"><c:param name="blogId"
value="${model.blog.id}"/></c:url>">Add Permission</a> <a href="<c:url
value="index.htm"/>">Manage</a>
+</p>
+</body>
+</html>
=======================================
--- /dev/null
+++
/branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/deletePermission.jsp
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,20 @@
+<%@ include file="/WEB-INF/jsp/include.jsp" %>
+
+<html>
+<head><title>Permission Deleted</title></head>
+<body>
+<h1>Permission Deleted</h1>
+<P>
+<code>
+<c:out value="${model.blog}"/>
+</code>
+<P>
+<code>
+<c:out value="${model.sid}"/>
+</code>
+<code>
+<c:out value="${model.permission}"/>
+</code>
+<p><a href="<c:url value="index.htm"/>">Manage</a>
+</body>
+</html>
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/deleted.jsp Wed
Jun 1 01:04:00 2011
@@ -0,0 +1,13 @@
+<%@ include file="/WEB-INF/jsp/include.jsp" %>
+
+<html>
+<head><title>Deletion completed</title></head>
+<body>
+<h1>Deleted</h1>
+<P>
+<code>
+<c:out value="${blog}"/>
+</code>
+<p><a href="<c:url value="index.htm"/>">Manage</a>
+</body>
+</html>
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/hello.jsp Wed
Jun 1 01:04:00 2011
@@ -0,0 +1,52 @@
+<%@ include file="/WEB-INF/jsp/include.jsp" %>
+
+<html>
+<head><title>Blogs Security Demo</title></head>
+<body>
+<h1>Blogs Security Demo</h1>
+<P>Blogs demonstrates the following central Spring Security capabilities:
+<ul>
+<li><b>Role-based security</b>. Each principal is a member of certain
roles,
+ which are used to restrict access to certain secure objects.</li>
+<li><b>Domain object instance security</b>. The <code>Blog</code>, the
+ main domain object in the application, has an access control list (ACL)
+ that indicates who is allowed read, administer and delete the
object.</li>
+<li><b>Method invocation security</b>. The <code>BlogManager</code> service
+ layer bean has a number of secured (protected) and public (unprotected)
+ methods.</li>
+<li><b>Web request security</b>. The <code>/secure</code> URI path is
protected
+ by Spring Security from principals not holding the
+ <code>ROLE_USER</code> granted authority.</li>
+<li><b>Security unaware application objects</b>. None of the objects
+ are aware of the security being implemented by Spring Security. *</li>
+<li><b>Security taglib usage</b>. All of the JSPs use Spring Security's
+ taglib to evaluate security information. *</li>
+<li><b>Fully declarative security</b>. Every capability is configured in
+ the application context using standard Spring Security classes. *</li>
+<li><b>Database-sourced security data</b>. All of the user, role and ACL
+ information is obtained from a JDBC-compliant database.</li>
+<li><b>Integrated form-based and BASIC authentication</b>. Any BASIC
+ authentication header is detected and used for authentication. Normal
+ interactive form-based authentication is used by default.</li>
+<li><b>Remember-me services</b>. Spring Security's pluggable remember-me
+ strategy is demonstrated, with a corresponding checkbox on the login
form.</li>
+</ul>
+
+* As the application provides an "ACL Administration" use case, those
+classes are necessarily aware of security. But no business use cases are.
+<p>Uncomment the commented lines in applicationContext-common-business.xml
file when first time you run the application
+ because DataSourcePopulator class will create and populate the tables for
you in mysql under "test" database for testing purposes</p>
+<p>Please excuse the lack of look 'n' feel polish in this application.
+It is about security, after all! :-)
+
+<p>To demonstrate a public method on <code>BlogManager</code>,
+here's a random <code>Blog</code>:
+<p>
+<code>
+<c:out value="${blog}"/>
+</code>
+<p>Get started by clicking "Manage"...
+<p><A HREF="<c:url value="secure/index.htm"/>">Manage</a>
+<a href="<c:url value="secure/debug.jsp"/>">Debug</a>
+</body>
+</html>
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/include.jsp Wed
Jun 1 01:04:00 2011
@@ -0,0 +1,6 @@
+<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
+<%@ taglib prefix="security"
uri="http://www.springframework.org/security/tags" %>
+
+<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ page pageEncoding="UTF-8" %>
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/webapp/WEB-INF/jsp/index.jsp Wed
Jun 1 01:04:00 2011
@@ -0,0 +1,32 @@
+<%@ include file="/WEB-INF/jsp/include.jsp" %>
+
+<html>
+<head><title>Your Blogs</title></head>
+<body>
+<h1><security:authentication property="principal.username"/>'s Blogs</h1>
+<P>
+<table cellpadding=3 border=0>
+<tr><td><b>id</b></td><td><b>Title</b></td><td><b>Content</b></td></tr>
+<c:forEach var="blog" items="${model.blogs}" >
+ <tr>
+ <td>
+ <c:out value="${blog.id}"/>
+ </td>
+ <td>
+ <c:out value="${blog.title}"/>
+ </td>
+ <td>
+ <c:out value="${blog.content}"/>
+ </td>
+ <c:if test="${model.hasDeletePermission[blog]}">
+ <td><a href="<c:url value="del.htm"><c:param name="blogId"
value="${blog.id}"/></c:url>">Del</a></td>
+ </c:if>
+ <c:if test="${model.hasAdminPermission[blog]}">
+ <td><a href="<c:url value="adminPermission.htm"><c:param name="blogId"
value="${blog.id}"/></c:url>">Admin Permission</a></td>
+ </c:if>
+ </tr>
+</c:forEach>
+</table>
+<p><a href="<c:url value="add.htm"/>">Add</a> <p><a href="<c:url
value="../j_spring_security_logout"/>">Logoff</a> (also clears any
remember-me cookie)
+</body>
+</html>
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/webapp/WEB-INF/spring.tld Wed Jun
1 01:04:00 2011
@@ -0,0 +1,311 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library
1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
+
+<taglib>
+
+ <tlib-version>1.1.1</tlib-version>
+
+ <jsp-version>1.2</jsp-version>
+
+ <short-name>Spring</short-name>
+
+ <uri>http://www.springframework.org/tags</uri>
+
+ <description>Spring Framework JSP Tag Library. Authors: Rod Johnson,
Juergen Hoeller</description>
+
+
+ <tag>
+
+ <name>htmlEscape</name>
+ <tag-class>org.springframework.web.servlet.tags.HtmlEscapeTag</tag-class>
+ <body-content>JSP</body-content>
+
+ <description>
+ Sets default HTML escape value for the current page.
+ Overrides a "defaultHtmlEscape" context-param in web.xml, if any.
+ </description>
+
+ <attribute>
+ <name>defaultHtmlEscape</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ </tag>
+
+
+ <tag>
+
+ <name>escapeBody</name>
+ <tag-class>org.springframework.web.servlet.tags.EscapeBodyTag</tag-class>
+ <body-content>JSP</body-content>
+
+ <description>
+ Escapes its enclosed body content, applying HTML escaping and/or
JavaScript escaping.
+ The HTML escaping flag participates in a page-wide or application-wide
setting
+ (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in
web.xml).
+ </description>
+
+ <attribute>
+ <name>htmlEscape</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>javaScriptEscape</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ </tag>
+
+
+ <tag>
+
+ <name>message</name>
+ <tag-class>org.springframework.web.servlet.tags.MessageTag</tag-class>
+ <body-content>JSP</body-content>
+
+ <description>
+ Retrieves the message with the given code, or text if code isn't
resolvable.
+ The HTML escaping flag participates in a page-wide or application-wide
setting
+ (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in
web.xml).
+ </description>
+
+ <attribute>
+ <name>code</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>arguments</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>text</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>var</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>htmlEscape</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>javaScriptEscape</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ </tag>
+
+
+ <tag>
+
+ <name>theme</name>
+ <tag-class>org.springframework.web.servlet.tags.ThemeTag</tag-class>
+ <body-content>JSP</body-content>
+
+ <description>
+ Retrieves the theme message with the given code, or text if code isn't
resolvable.
+ The HTML escaping flag participates in a page-wide or application-wide
setting
+ (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in
web.xml).
+ </description>
+
+ <attribute>
+ <name>code</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>arguments</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>text</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>var</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>htmlEscape</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>javaScriptEscape</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ </tag>
+
+
+ <tag>
+
+ <name>hasBindErrors</name>
+ <tag-class>org.springframework.web.servlet.tags.BindErrorsTag</tag-class>
+ <body-content>JSP</body-content>
+
+ <description>
+ Provides Errors instance in case of bind errors.
+ The HTML escaping flag participates in a page-wide or application-wide
setting
+ (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in
web.xml).
+ </description>
+
+ <variable>
+ <name-given>errors</name-given>
+ <variable-class>org.springframework.validation.Errors</variable-class>
+ </variable>
+
+ <attribute>
+ <name>name</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>htmlEscape</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ </tag>
+
+
+ <tag>
+
+ <name>nestedPath</name>
+ <tag-class>org.springframework.web.servlet.tags.NestedPathTag</tag-class>
+ <body-content>JSP</body-content>
+
+ <description>
+ Sets a nested path to be used by the bind tag's path.
+ </description>
+
+ <variable>
+ <name-given>nestedPath</name-given>
+ <variable-class>java.lang.String</variable-class>
+ </variable>
+
+ <attribute>
+ <name>path</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ </tag>
+
+
+ <tag>
+
+ <name>bind</name>
+ <tag-class>org.springframework.web.servlet.tags.BindTag</tag-class>
+ <body-content>JSP</body-content>
+
+ <description>
+ Provides BindStatus object for the given bind path.
+ The HTML escaping flag participates in a page-wide or application-wide
setting
+ (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in
web.xml).
+ </description>
+
+ <variable>
+ <name-given>status</name-given>
+
<variable-class>org.springframework.web.servlet.support.BindStatus</variable-class>
+ </variable>
+
+ <attribute>
+ <name>path</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>ignoreNestedPath</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>htmlEscape</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ </tag>
+
+
+ <tag>
+
+ <name>transform</name>
+ <tag-class>org.springframework.web.servlet.tags.TransformTag</tag-class>
+ <body-content>JSP</body-content>
+
+ <description>
+ Provides transformation of variables to Strings, using an appropriate
+ custom PropertyEditor from BindTag (can only be used inside BindTag).
+ The HTML escaping flag participates in a page-wide or application-wide
setting
+ (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in
web.xml).
+ </description>
+
+ <attribute>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>var</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ <attribute>
+ <name>htmlEscape</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+
+ </tag>
+
+</taglib>
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/webapp/WEB-INF/tiles/baseLayout.jsp
Wed Jun 1 01:04:00 2011
@@ -0,0 +1,32 @@
+<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
+<!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><tiles:insertAttribute name="title" ignore="true"
/></title>
+ </head>
+ <body>
+ <table border="1" cellpadding="2" cellspacing="2" align="center"
width="70%">
+ <tr>
+ <td height="30" colspan="2">
+ <tiles:insertAttribute name="header" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <tiles:insertAttribute name="menu" />
+ </td>
+ <td>
+ <tiles:insertAttribute name="body" />
+ </td>
+ </tr>
+ <tr>
+ <td height="30" colspan="2">
+ <tiles:insertAttribute name="footer" />
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/webapp/WEB-INF/tiles/body.jsp Wed
Jun 1 01:04:00 2011
@@ -0,0 +1,1 @@
+<p> sample body content.</p>
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/webapp/WEB-INF/tiles/footer.jsp Wed
Jun 1 01:04:00 2011
@@ -0,0 +1,1 @@
+<div align="center">&copy; MyBlog.com</div>
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/webapp/WEB-INF/tiles/header.jsp Wed
Jun 1 01:04:00 2011
@@ -0,0 +1,17 @@
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="sec"
uri="http://www.springframework.org/security/tags" %>
+<div align="center" style="font-weight:bold">
+ <table>
+ <tr>
+ <td>Welcome </td>
+ <td><a href="<c:url value="removeUser.htm"/>" >My-Account</a></td>
+ <td>|</td>
+ <td>
+ <a href="<c:url value="/login.jsp"/>">Login</a>
+ <a href="<c:url value="/j_spring_security_logout"/>">Logout</a>
+ </td>
+ <td>|</td>
+ <td><a href="<c:url value="register.htm"/>">Register</a></td>
+ </tr>
+ </table>
+</div>
=======================================
--- /dev/null
+++ /branches/myblog-springmvc/src/main/webapp/WEB-INF/tiles/menu.jsp Wed
Jun 1 01:04:00 2011
@@ -0,0 +1,11 @@
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="sec"
uri="http://www.springframework.org/security/tags" %>
+<!-- Follwing is what we would use to show or hide some section in a page
on the basis of Role -->
+<!-- Uncomment it to see it working -->
+<!-- sec:authorize access="hasRole('ROLE_SUPERVISOR')">
+ This content will only be visible to users who have
+ the "supervisor" authority in their list of <tt>GrantedAuthority</tt>s.-->
+<!-- sec:authorize -->
+<a href="<c:url value="forum.htm"/>" >Forum</a><br>
+<hr/>
+<a href="<c:url value="askquestion.htm"/>" >Ask Question</a><br>
=======================================
***Additional files exist in this changeset.***

Reply all
Reply to author
Forward
0 new messages