Author: agilliland
Date: Sun Jun 3 11:17:03 2007
New Revision: 543952
URL: http://svn.apache.org/viewvc?view=rev&rev=543952
Log:
need to add JPAPersistenceStrategy to weblogger code.
Added:
roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/jpa/JPAPersistenceStrategy.java
Added:
roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/jpa/JPAPersistenceStrategy.java
URL:
http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/jpa/JPAPersistenceStrategy.java?view=auto&rev=543952
==============================================================================
---
roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/jpa/JPAPersistenceStrategy.java
(added)
+++
roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/jpa/JPAPersistenceStrategy.java
Sun Jun 3 11:17:03 2007
@@ -0,0 +1,375 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. 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. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.business.jpa;
+
+import java.util.Collection;
+import java.util.Properties;
+import java.util.Iterator;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.io.InputStream;
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.weblogger.WebloggerException;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityManager;
+import javax.persistence.FlushModeType;
+import javax.persistence.Persistence;
+import javax.persistence.PersistenceException;
+import javax.persistence.Query;
+
+
+/**
+ * JPAPersistenceStrategy is responsible for the lowest-level interaction with
+ * the JPA API.
+ */
+// TODO handle PersistenceExceptions!
+public class JPAPersistenceStrategy {
+
+ /**
+ * The thread local EntityManager.
+ */
+ private final ThreadLocal threadLocalEntityManager = new ThreadLocal();
+
+ /**
+ * The EntityManagerFactory for this Roller instance.
+ */
+ private EntityManagerFactory emf = null;
+
+ /**
+ * The logger instance for this class.
+ */
+ private static Log logger = LogFactory.getFactory().getInstance(
+ JPAPersistenceStrategy.class);
+
+ /**
+ * Construct by finding JPA EntityManagerFactory.
+ * @throws org.apache.roller.WebloggerException on any error
+ */
+ public JPAPersistenceStrategy(
+ String puName,
+ String jndiName,
+ Properties properties) throws WebloggerException {
+
+ // set strategy used by Datamapper
+ // You can configure JPA completely via the JPAEMF.properties file
+ Properties emfProps = loadPropertiesFromResourceName(
+ "JPAEMF.properties", getContextClassLoader());
+
+ // Add additional properties passed in
+ Enumeration keys = properties.keys();
+ while (keys.hasMoreElements()) {
+ String key = (String)keys.nextElement();
+ String value = properties.getProperty(key);
+ logger.info(key + ": " + value);
+ emfProps.setProperty(key, value);
+ }
+
+ emfProps.setProperty("openjpa.ConnectionFactoryName", jndiName);
+
+ try {
+ this.emf = Persistence.createEntityManagerFactory(puName,
emfProps);
+ } catch (PersistenceException pe) {
+ logger.error("ERROR: creating entity manager", pe);
+ throw new WebloggerException(pe);
+ }
+ }
+
+ /**
+ * Construct by finding JPA EntityManagerFactory.
+ * @throws org.apache.roller.WebloggerException on any error
+ */
+ public JPAPersistenceStrategy(
+ String puName,
+ String driverClass,
+ String connectonUrl,
+ String username,
+ String password,
+ Properties properties) throws WebloggerException {
+
+ logger.info("driverClass: " + driverClass);
+ logger.info("connectionURL: " + connectonUrl);
+ logger.info("username: " + username);
+
+ // set strategy used by Datamapper
+ // You can configure JPA completely via the JPAEMF.properties file
+ Properties emfProps = loadPropertiesFromResourceName(
+ "JPAEMF.properties", getContextClassLoader());
+
+ // Add additional properties passed in
+ Enumeration keys = properties.keys();
+ while (keys.hasMoreElements()) {
+ String key = (String)keys.nextElement();
+ String value = properties.getProperty(key);
+ logger.info(key + ": " + value);
+ emfProps.setProperty(key, value);
+ }
+
+ // Try to please all the players
+ emfProps.setProperty("openjpa.ConnectionDriverName", driverClass);
+ emfProps.setProperty("openjpa.ConnectionURL", connectonUrl);
+ emfProps.setProperty("openjpa.ConnectionUserName", username);
+ emfProps.setProperty("openjpa.ConnectionPassword", password);
+
+ emfProps.setProperty("toplink.jdbc.driver", driverClass);
+ emfProps.setProperty("toplink.jdbc.url", connectonUrl);
+ emfProps.setProperty("toplink.jdbc.user", username);
+ emfProps.setProperty("toplink.jdbc.password", password);
+
+ emfProps.setProperty("hibernate.connection.driver_class",driverClass);
+ emfProps.setProperty("hibernate.connection.url", connectonUrl);
+ emfProps.setProperty("hibernate.connection.username", username);
+ emfProps.setProperty("hibernate.connection.password", password);
+
+ try {
+ this.emf = Persistence.createEntityManagerFactory(puName,
emfProps);
+ } catch (PersistenceException pe) {
+ logger.error("ERROR: creating entity manager", pe);
+ throw new WebloggerException(pe);
+ }
+ }
+
+ /**
+ * Flush changes to the datastore, commit transaction, release em.
+ * @throws org.apache.roller.WebloggerException on any error
+ */
+ public void flush() throws WebloggerException {
+ try {
+ EntityManager em = getEntityManager(true);
+ em.getTransaction().commit();
+ } catch (PersistenceException pe) {
+ throw new WebloggerException(pe);
+ }
+ }
+
+ /**
+ * Release database session, rolls back any uncommitted changes.
+ */
+ public void release() {
+ EntityManager em = getEntityManager(false);
+ if (isTransactionActive(em)) {
+ em.getTransaction().rollback();
+ }
+ em.close();
+ setThreadLocalEntityManager(null);
+ }
+
+ /**
+ * Store object using an existing transaction.
+ * @param obj the object to persist
+ * @return the object persisted
+ * @throws org.apache.roller.WebloggerException on any error
+ */
+ public Object store(Object obj) throws WebloggerException {
+ EntityManager em = getEntityManager(true);
+ if (!em.contains(obj)) {
+ // If entity is not managed we can assume it is new
+ em.persist(obj);
+ }
+ return obj;
+ }
+
+ /**
+ * Remove object from persistence storage.
+ * @param clazz the class of object to remove
+ * @param id the id of the object to remove
+ * @throws WebloggerException on any error deleting object
+ */
+ public void remove(Class clazz, String id) throws WebloggerException {
+ EntityManager em = getEntityManager(true);
+ Object po = em.find(clazz, id);
+ em.remove(po);
+ }
+
+ /**
+ * Remove object from persistence storage.
+ * @param po the persistent object to remove
+ * @throws org.apache.roller.WebloggerException on any error
+ */
+ public void remove(Object po) throws WebloggerException {
+ EntityManager em = getEntityManager(true);
+ em.remove(po);
+ }
+
+ /**
+ * Remove object from persistence storage.
+ * @param pos the persistent objects to remove
+ * @throws org.apache.roller.WebloggerException on any error
+ */
+ public void removeAll(Collection pos) throws WebloggerException {
+ EntityManager em = getEntityManager(true);
+ for (Iterator iterator = pos.iterator(); iterator.hasNext();) {
+ Object obj = iterator.next();
+ em.remove(obj);
+ }
+ }
+
+ /**
+ * Retrieve object, no transaction needed.
+ * @param clazz the class of object to retrieve
+ * @param id the id of the object to retrieve
+ * @return the object retrieved
+ * @throws WebloggerException on any error retrieving object
+ */
+ public Object load(Class clazz, String id)
+ throws WebloggerException {
+ EntityManager em = getEntityManager(false);
+ return em.find(clazz, id);
+ }
+
+ /**
+ * Return true if a transaction is active on the current EntityManager.
+ * @param em the persistence manager
+ * @return true if the persistence manager is not null and has an active
+ * transaction
+ */
+ private boolean isTransactionActive(EntityManager em) {
+ if (em == null) {
+ return false;
+ }
+ return em.getTransaction().isActive();
+ }
+
+ /**
+ * Get the EntityManager associated with the current thread of control.
+ * @param isTransactionRequired true if a transaction is begun if not
+ * already active
+ * @return the EntityManager
+ */
+ private EntityManager getEntityManager(boolean isTransactionRequired) {
+ EntityManager em = getThreadLocalEntityManager();
+ if (isTransactionRequired && !em.getTransaction().isActive()) {
+ em.getTransaction().begin();
+ }
+ return em;
+ }
+
+ /**
+ * Get the current ThreadLocal EntityManager
+ */
+ private EntityManager getThreadLocalEntityManager() {
+ EntityManager em = (EntityManager) threadLocalEntityManager.get();
+ if (em == null) {
+ em = emf.createEntityManager();
+ threadLocalEntityManager.set(em);
+ }
+ return em;
+ }
+
+ /**
+ * Set the current ThreadLocal EntityManager
+ */
+ private void setThreadLocalEntityManager(Object em) {
+ threadLocalEntityManager.set(em);
+ }
+
+ /**
+ * Get named query with FlushModeType.COMMIT
+ * @param clazz the class of instances to find
+ * @param queryName the name of the query
+ * @throws org.apache.roller.WebloggerException on any error
+ */
+ public Query getNamedQuery(String queryName)
+ throws WebloggerException {
+ EntityManager em = getEntityManager(false);
+ Query q = em.createNamedQuery(queryName);
+ // Never flush for queries. Roller code assumes this behavior
+ q.setFlushMode(FlushModeType.COMMIT);
+ return q;
+ }
+
+ /**
+ * Create query from queryString with FlushModeType.COMMIT
+ * @param queryString the quuery
+ * @throws org.apache.roller.WebloggerException on any error
+ */
+ public Query getDynamicQuery(String queryString)
+ throws WebloggerException {
+ EntityManager em = getEntityManager(false);
+ Query q = em.createQuery(queryString);
+ // Never flush for queries. Roller code assumes this behavior
+ q.setFlushMode(FlushModeType.COMMIT);
+ return q;
+ }
+
+ /**
+ * Get named update query with default flush mode
+ * @param clazz the class of instances to find
+ * @param queryName the name of the query
+ * @throws org.apache.roller.WebloggerException on any error
+ */
+ public Query getNamedUpdate(String queryName)
+ throws WebloggerException {
+ EntityManager em = getEntityManager(true);
+ Query q = em.createNamedQuery(queryName);
+ return q;
+ }
+
+ /**
+ * Loads properties from given resourceName using given class loader
+ * @param resourceName The name of the resource containing properties
+ * @param cl Classloeder to be used to locate the resouce
+ * @return A properties object
+ * @throws WebloggerException
+ */
+ private static Properties loadPropertiesFromResourceName(
+ String resourceName, ClassLoader cl) throws WebloggerException {
+ Properties props = new Properties();
+ InputStream in = null;
+ in = cl.getResourceAsStream(resourceName);
+ if (in == null) {
+ //TODO: Check how i18n is done in roller
+ throw new WebloggerException(
+ "Could not locate properties to load " + resourceName);
+ }
+ try {
+ props.load(in);
+ } catch (IOException ioe) {
+ throw new WebloggerException(
+ "Could not load properties from " + resourceName);
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException ioe) {
+ }
+ }
+ }
+
+ return props;
+ }
+
+ /**
+ * Get the context class loader associated with the current thread. This is
+ * done in a doPrivileged block because it is a secure method.
+ * @return the current thread's context class loader.
+ */
+ private static ClassLoader getContextClassLoader() {
+ return (ClassLoader) AccessController.doPrivileged(
+ new PrivilegedAction() {
+ public Object run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ }
+}