/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.aries.samples.blog.persistence.jdbc; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.text.ParseException; import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.sql.DataSource; import org.apache.aries.samples.blog.api.persistence.BlogPersistenceService; import org.apache.aries.samples.blog.persistence.jdbc.entity.AuthorImpl; import org.apache.aries.samples.blog.persistence.jdbc.entity.EntryImpl; /** * This class is the implementation of the blogPersistenceService */ public class BlogPersistenceServiceImpl implements BlogPersistenceService { private DataSource dataSource; private Statements statements; public BlogPersistenceServiceImpl() { this.statements = new Statements(); } /** * set data source */ public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public void init() { Statement s = null; Connection connection = null; try { connection = dataSource.getConnection(); s = connection.createStatement(); String[] createStatments = this.statements .getCreateSchemaStatements(); for (int i = 0; i < createStatments.length; i++) { s.execute(createStatments[i]); } } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } finally { if (s != null) { try { s.close(); } catch (Throwable e) { } } if (connection != null) { try { connection.close(); } catch (Throwable e) { } } } } public void destroy() { Statement s = null; Connection connection = null; try { connection = dataSource.getConnection(); s = connection.createStatement(); String[] dropStatments = this.statements.getDropSchemaStatements(); for (int i = 0; i < dropStatments.length; i++) { s.execute(dropStatments[i]); } } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } finally { if (s != null) { try { s.close(); } catch (Throwable e) { } } if (connection != null) { try { connection.close(); } catch (Throwable e) { } } } } /** * Create an author record * * @param a * The author object to be created * @throws ParseException * @throws ParseException */ public void createAuthor(String email, Date dob, String name, String displayName, String bio) { try { Connection connection = dataSource.getConnection(); String sql = "INSERT INTO AUTHOR VALUES (?,?,?,?,?)"; PreparedStatement ppsm = connection.prepareStatement(sql); ppsm.setString(1, email); ppsm.setString(2, bio); ppsm.setString(3, displayName); if (dob != null) ppsm.setDate(4, new java.sql.Date(dob.getTime())); else ppsm.setDate(4, null); ppsm.setString(5, name); int insertRows = ppsm.executeUpdate(); ppsm.close(); connection.close(); if (insertRows != 1) throw new IllegalArgumentException("The Author " + email + " cannot be inserted."); } catch (SQLException e) { e.printStackTrace(); throw new IllegalArgumentException(e.getMessage()); } } /** * Create a blog entry record * * @param a * The author * @param title * The title of the post * @param blogText * The text of the post * @param tags * */ public void createBlogPost(String authorEmail, String title, String blogText, List<String> tags) { AuthorImpl a = getAuthor(authorEmail); if(title == null) title = ""; Date publishDate = new Date(System.currentTimeMillis()); if(tags == null) tags = new ArrayList<String>(); try { Connection connection = dataSource.getConnection(); // let's find the max id from the blogentry table String sql = "SELECT max(id) FROM BLOGENTRY"; PreparedStatement ppsm = connection.prepareStatement(sql); ResultSet rs = ppsm.executeQuery(); // we only expect to have one row returned rs.next(); long max_id = rs.getLong(1); ppsm.close(); long post_id = max_id + 1; sql = "INSERT INTO BLOGENTRY VALUES (?,?,?,?,?,?)"; ppsm = connection.prepareStatement(sql); ppsm.setLong(1, post_id); ppsm.setString(2, blogText); if (publishDate != null) ppsm .setDate(3, new java.sql.Date(publishDate .getTime())); else ppsm.setDate(3, null); ppsm.setString(4, title); ppsm.setDate(5, null); ppsm.setString(6, a.getEmail()); int rows = ppsm.executeUpdate(); if (rows != 1) throw new IllegalArgumentException( "The blog entry record cannot be inserted: " + blogText); ppsm.close(); // insert a row in the relationship table sql = "INSERT INTO Author_BlogEntry VALUES (?,?)"; ppsm = connection.prepareStatement(sql); ppsm.setString(1, a.getEmail()); ppsm.setLong(2, post_id); rows = ppsm.executeUpdate(); ppsm.close(); connection.close(); if (rows != 1) throw new IllegalArgumentException( "The Author_BlogEntry record cannot be inserted: " + a.getEmail() + " , " + post_id); } catch (SQLException sqle) { sqle.printStackTrace(); } } /** * Find the blog entry record with the specified title * * @param The title to be searched * @return The blogEntry record */ public EntryImpl findBlogEntryByTitle(String title) { EntryImpl be = null; String sql = "SELECT * FROM BlogEntry e WHERE e.title = '" + title + "'"; List<EntryImpl> blogEntries = findBlogs(sql); // just return the first blog entry for the time being if ((blogEntries != null) && (blogEntries.size() > 0)) be = blogEntries.get(0); return be; } /** * Return all author records in the Author table * * @return the list of Author records */ public List<AuthorImpl> getAllAuthors() { String sql = "SELECT * FROM Author"; List<AuthorImpl> list = findAuthors(sql); return list; } /** * Return all blog entry records from BlogEntry table with the most recent * published blog entries first * * @return a list of blogEntry object */ public List<EntryImpl> getAllBlogEntries() { String sql = "SELECT * FROM BlogEntry b ORDER BY b.publishDate DESC"; List<EntryImpl> list = findBlogs(sql); return list; } /** * Return the number of the blog entry records * * @return the number of the blog Entry records */ public int getNoOfBlogEntries() { int count = 0; String sql = "SELECT count(*) FROM BLOGENTRY"; try { Connection connection = dataSource.getConnection(); PreparedStatement ppsm = connection.prepareStatement(sql); ResultSet rs = ppsm.executeQuery(); // we only expect to have one row returned rs.next(); count = rs.getInt(1); ppsm.close(); connection.close(); } catch (SQLException sqle) { sqle.printStackTrace(); } return count; } /** * Return the portion of blog Entries * * @param firstPostIndex * The index of the first blog entry to be returned * @param noOfPosts * The number of blog entry to be returned * @return The list of the blog entry record */ public List<EntryImpl> getBlogEntries(int firstPostIndex, int noOfPosts) { String sql = "SELECT * FROM BlogEntry b ORDER BY b.publishDate DESC"; List<EntryImpl> emptyList = new ArrayList<EntryImpl>(); List<EntryImpl> blogs = findBlogs(sql); // we only return a portion of the list if (blogs == null) return emptyList; // We need to make sure we won't throw IndexOutOfBoundException if the // supplied // index is out of the list range int maximumIndex = blogs.size(); // if the first index is minus or greater than the last item index of // the list, return an empty list if ((firstPostIndex < 0) || (noOfPosts <= 0) || (firstPostIndex > maximumIndex)) return emptyList; // return the required number of the blog entries or the available blog // entries int lastIndex = noOfPosts + firstPostIndex; // we need to make sure we return the blog entries at most up to the // final record return (blogs.subList(firstPostIndex, (lastIndex > maximumIndex) ? maximumIndex : lastIndex)); } /** * Return the author with the specified email address * * @param emailAddress * The email address * @return The author record */ public AuthorImpl getAuthor(String emailAddress) { String sql = "SELECT * FROM AUTHOR a where a.email='" + emailAddress + "'"; List<AuthorImpl> authors = findAuthors(sql); if (authors.size() == 0) return null; else if (authors.size() > 1) throw new IllegalArgumentException( "Email address should be unique per author"); return authors.get(0); // just return the first author } /** * Return the blog entries modified between the date range of [start, end] * * @param start * The start date * @param end * The end date * @return The list of blog entries */ public List<EntryImpl> getBlogEntriesModifiedBetween(Date start, Date end) { // String sql = "SELECT * FROM BlogEntry b WHERE (b.updatedDate >= " + // startTS +" AND b.updatedDate <= " + endTS + ") OR (b.publishDate >= " // +startTS + " AND b.publishDate <= " + endTS + // ") ORDER BY b.publishDate ASC"; String sql = "SELECT * FROM BlogEntry b WHERE (Date(b.updatedDate) BETWEEN '" + start + "' AND '" + end + "') OR (Date(b.publishDate) BETWEEN '" + start + "' AND '" + end + "') ORDER BY b.publishDate ASC"; return findBlogs(sql); } /** * Return a list of blog entries belonging to the author with the specified * email address * * @param emailAddress * the author's email address * @return The list of blog entries */ public List<EntryImpl> getBlogsForAuthor(String emailAddress) { String sql = "SELECT * FROM BlogEntry b WHERE b.AUTHOR_EMAIL='" + emailAddress + "'"; return findBlogs(sql); } /** * Update the author record * * @param email * The email associated with an author * @param dob * The author's date of birth * @param name * the author's name * @param displayName * The displayName * @param bio * The aouthor's bio */ public void updateAuthor(String email, Date dob, String name, String displayName, String bio) { String sql = "UPDATE AUTHOR a SET bio = ?, displayName = ?, dob = ?, name =? WHERE email ='" + email + "'"; int updatedRows = 0; try { Connection connection = dataSource.getConnection(); PreparedStatement ppsm = connection.prepareStatement(sql); ppsm.setString(1, bio); ppsm.setString(2, displayName); if (dob != null) ppsm.setDate(3, new java.sql.Date(dob.getTime())); else ppsm.setDate(3, null); ppsm.setString(4, name); updatedRows = ppsm.executeUpdate(); ppsm.close(); connection.close(); if (updatedRows != 1) throw new IllegalArgumentException("The Author " + email + " cannot be updated."); } catch (SQLException e) { e.printStackTrace(); } } /** * Update the blog entry record * * */ public void updateBlogEntry(long id, String email, String title, String blogText, List<String> tags, Date updatedDate) { if (id == -1) throw new IllegalArgumentException( "Not a BlogEntry returned by this interface"); EntryImpl b = getBlogEntryById(id); String sql_se = "SELECT * FROM BLOGENTRY bp WHERE bp.id = " + id; String email_old = null; // let's find out the email address for the blog post to see whether the // table Author_BlogEntry needs to be updated // if the email is updated, we need to update the table Author_BlogEntry // to reflect the change. try { Connection connection = dataSource.getConnection(); PreparedStatement ppsm = connection.prepareStatement(sql_se); ResultSet rs = ppsm.executeQuery(); // there should be just one record rs.next(); email_old = rs.getString("AUTHOR_EMAIL"); ppsm.close(); connection.close(); } catch (SQLException sqle) { sqle.printStackTrace(); } String sql = "UPDATE BLOGENTRY bp SET bp.blogText = ?, bp.publishDate = ?, bp.title = ?, bp.updatedDate = ?, bp.AUTHOR_EMAIL = ? where bp.id = " + id; int updatedRows = 0; try { Connection connection = dataSource.getConnection(); PreparedStatement ppsm = connection.prepareStatement(sql); ppsm.setString(1, blogText); if (b.getPublishDate() != null) ppsm .setDate(2, new java.sql.Date(b.getPublishDate() .getTime())); else ppsm.setDate(2, null); ppsm.setString(3, b.getTitle()); if (b.getUpdatedDate() != null) ppsm .setDate(4, new java.sql.Date(b.getUpdatedDate() .getTime())); else ppsm.setDate(4, null); ppsm.setString(5, email); updatedRows = ppsm.executeUpdate(); ppsm.close(); connection.close(); if (updatedRows != 1) throw new IllegalArgumentException("The Blog " + b.getId() + " cannot be updated."); } catch (SQLException e) { e.printStackTrace(); } // if the email address is changed, we need to need to update the // relationship table Author_BlogEntry if ((email_old != null) && (!!!email_old.equals(email))) { // update the table Author_BlogEntry String sql_ab = "UDPATE Author_BlogEntry ab SET ab.AUTHOR_EMAIL = '" + email + "'"; updatedRows = 0; try { Connection connection = dataSource.getConnection(); PreparedStatement ppsm = connection.prepareStatement(sql_ab); updatedRows = ppsm.executeUpdate(); ppsm.close(); connection.close(); if (updatedRows != 1) throw new IllegalArgumentException( "The Author_BlogEntry with the postsID " + b.getId() + " cannot be updated."); } catch (SQLException e) { e.printStackTrace(); } } } /** * Delete the author record with the specified email address * * @param emailAddress * The author's email address * */ public void removeAuthor(String emailAddress) { // we need to remove the author and its blog entries try { String sql = "DELETE FROM BLOGENTRY bp WHERE bp.AUTHOR_EMAIL = '" + emailAddress + "'"; Connection connection = dataSource.getConnection(); PreparedStatement ppsm = connection.prepareStatement(sql); ppsm.executeUpdate(); ppsm.close(); // delete the records from Author_BlogEntry sql = "DELETE FROM Author_BlogEntry ab WHERE ab.AUTHOR_EMAIL = '" + emailAddress + "'"; ppsm = connection.prepareStatement(sql); ppsm.executeUpdate(); ppsm.close(); // delete the author record sql = "DELETE FROM Author a WHERE a.EMAIL = '" + emailAddress + "'"; ppsm = connection.prepareStatement(sql); ppsm.executeUpdate(); ppsm.close(); connection.close(); } catch (SQLException sqle) { sqle.printStackTrace(); } } /** * Delete the blog entry record specified by the blogEntry * * @param blogEntry * the blog entry record to be deleted */ public void removeBlogEntry(long id) { if (id == -1) throw new IllegalArgumentException( "Not a BlogEntry returned by this interface"); try { String sql = "DELETE FROM BLOGENTRY bp WHERE bp.id = " + id; Connection connection = dataSource.getConnection(); PreparedStatement ppsm = connection.prepareStatement(sql); ppsm.executeUpdate(); ppsm.close(); // We also need to delete the records from Author_BlogEntry, as this // table is a kind of link between author and blogentry record sql = "DELETE FROM Author_BlogEntry ab WHERE ab.POSTS_ID = " + id; ppsm = connection.prepareStatement(sql); ppsm.executeUpdate(); ppsm.close(); connection.close(); } catch (SQLException sqle) { sqle.printStackTrace(); } } /** * Return the blog entry record with the specified id * * @param postId * The blogEntry record id */ public EntryImpl getBlogEntryById(long postId) { String sql = "SELECT * FROM BlogEntry b WHERE b.id = " + postId; List<EntryImpl> blogs = findBlogs(sql); if (blogs.size() == 0) return null; if (blogs.size() > 1) throw new IllegalArgumentException("Blog id is not unique"); return blogs.get(0); } /** * Return a list of authors with the sql query * * @param sql * The SQL query * @return A list of author records */ private List<AuthorImpl> findAuthors(String sql) { List<AuthorImpl> authorList = new ArrayList<AuthorImpl>(); try { Connection connection = dataSource.getConnection(); PreparedStatement ppsm = connection.prepareStatement(sql); ResultSet ars = ppsm.executeQuery(); while (ars.next()) { AuthorImpl ar = new AuthorImpl(); ar.setBio(ars.getString("bio")); ar.setDisplayName(ars.getString("displayName")); ar.setDob(ars.getDate("dob")); String email = ars.getString("email"); ar.setEmail(email); ar.setName(ars.getString("name")); // let's find the blog entries for the author String sql_be = "SELECT * FROM BLOGENTRY be WHERE be.AUTHOR_EMAIL = '" + email + "'"; PreparedStatement ppsm2 = connection.prepareStatement(sql_be); ResultSet rs = ppsm2.executeQuery(); List<EntryImpl> blogs = new ArrayList<EntryImpl>(); while (rs.next()) { EntryImpl blog = new EntryImpl(); blog.setAuthor(ar); blog.setId(rs.getLong("id")); blog.setBlogText(rs.getString("blogText")); blog.setPublishDate(rs.getDate("publishDate")); blog.setTitle(rs.getString("title")); blog.setUpdatedDate(rs.getDate("updatedDate")); blogs.add(blog); } ar.setEntries(blogs); authorList.add(ar); ppsm2.close(); } ppsm.close(); connection.close(); } catch (Exception e) { e.printStackTrace(); } return authorList; } /** * Return a list of blog entries with the sql query * * @param sql * The sql query to be executed * @return a list of blogEntry records */ private List<EntryImpl> findBlogs(String sql) { List<EntryImpl> blogEntryList = new ArrayList<EntryImpl>(); try { Connection connection = dataSource.getConnection(); PreparedStatement ppsm = connection.prepareStatement(sql); ResultSet blogrs = ppsm.executeQuery(); while (blogrs.next()) { EntryImpl be = new EntryImpl(); be.setId(blogrs.getLong("id")); be.setBlogText(blogrs.getString("blogText")); be.setPublishDate(blogrs.getDate("publishDate")); be.setTitle(blogrs.getString("title")); be.setUpdatedDate(blogrs.getDate("updatedDate")); // find the author email address String author_email = blogrs.getString("AUTHOR_EMAIL"); String author_sql = "SELECT * FROM Author a WHERE a.email ='" + author_email + "'"; List<AuthorImpl> authors = findAuthors(author_sql); // there should be just one entry, as email is the primary key // for the Author table if (authors.size() != 1) throw new IllegalArgumentException( "We got more than one author with the same email address. This is wrong"); else be.setAuthor(authors.get(0)); blogEntryList.add(be); } ppsm.close(); connection.close(); } catch (Exception e) { e.printStackTrace(); } return blogEntryList; } }