You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by sn...@apache.org on 2007/05/25 00:14:17 UTC
svn commit: r541450 - in /roller/trunk/components: ./ core/ core/build/
core/build/compile/ core/build/compile/business/
core/build/compile/business/org/ core/build/compile/business/org/apache/
core/build/compile/business/org/apache/roller/ core/build/...
Author: snoopdave
Date: Thu May 24 15:14:14 2007
New Revision: 541450
URL: http://svn.apache.org/viewvc?view=rev&rev=541450
Log:
New JPA backend merge: new "core" component with shared DB code
Added:
roller/trunk/components/
roller/trunk/components/core/
roller/trunk/components/core/build/
roller/trunk/components/core/build.properties
roller/trunk/components/core/build.xml
roller/trunk/components/core/build/compile/
roller/trunk/components/core/build/compile/business/
roller/trunk/components/core/build/compile/business/org/
roller/trunk/components/core/build/compile/business/org/apache/
roller/trunk/components/core/build/compile/business/org/apache/roller/
roller/trunk/components/core/build/compile/business/org/apache/roller/business/
roller/trunk/components/core/build/compile/business/org/apache/roller/business/hibernate/
roller/trunk/components/core/build/compile/business/org/apache/roller/business/jpa/
roller/trunk/components/core/build/compile/business/org/apache/roller/util/
roller/trunk/components/core/build/lib/
roller/trunk/components/core/dist/
roller/trunk/components/core/src/
roller/trunk/components/core/src/java/
roller/trunk/components/core/src/java/org/
roller/trunk/components/core/src/java/org/apache/
roller/trunk/components/core/src/java/org/apache/roller/
roller/trunk/components/core/src/java/org/apache/roller/RollerException.java
roller/trunk/components/core/src/java/org/apache/roller/business/
roller/trunk/components/core/src/java/org/apache/roller/business/hibernate/
roller/trunk/components/core/src/java/org/apache/roller/business/hibernate/HibernatePersistenceStrategy.java
roller/trunk/components/core/src/java/org/apache/roller/business/hibernate/ThreadLocalSessionContextNoAutoClose.java
roller/trunk/components/core/src/java/org/apache/roller/business/jpa/
roller/trunk/components/core/src/java/org/apache/roller/business/jpa/JPAPersistenceStrategy.java
roller/trunk/components/core/src/java/org/apache/roller/util/
roller/trunk/components/core/src/java/org/apache/roller/util/UUIDGenerator.java
Added: roller/trunk/components/core/build.properties
URL: http://svn.apache.org/viewvc/roller/trunk/components/core/build.properties?view=auto&rev=541450
==============================================================================
--- roller/trunk/components/core/build.properties (added)
+++ roller/trunk/components/core/build.properties Thu May 24 15:14:14 2007
@@ -0,0 +1,9 @@
+
+# compile properties
+build.debug=true
+build.sourcelevel=1.4
+build.deprecation=false
+
+# unit test properties
+junit.fork=true
+junit.haltonerror=false
Added: roller/trunk/components/core/build.xml
URL: http://svn.apache.org/viewvc/roller/trunk/components/core/build.xml?view=auto&rev=541450
==============================================================================
--- roller/trunk/components/core/build.xml (added)
+++ roller/trunk/components/core/build.xml Thu May 24 15:14:14 2007
@@ -0,0 +1,129 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+<project name="Roller Core" default="build" basedir=".">
+
+ <description>Build core Roller utils.</description>
+
+ <property file="build.properties" />
+
+ <!-- core properties -->
+ <property name="build" value="${basedir}/build" />
+ <property name="dist" value="${basedir}/dist" />
+ <property name="src" value="${basedir}/src/java" />
+ <property name="tools" value="${basedir}/../../tools" />
+
+ <!-- build properties -->
+ <property name="build.compile" value="${build}/compile"/>
+ <property name="build.compile.business" value="${build.compile}/business"/>
+ <property name="build.compile.test" value="${build.compile}/test"/>
+ <property name="build.lib" value="${build}/lib"/>
+
+ <fileset id="core-jars" dir="${tools}">
+ <!-- General dependencies -->
+ <include name="lib/jdom.jar"/>
+ <include name="lib/commons-codec-1.3.jar"/>
+ <include name="lib/log4j-1.2.11.jar"/>
+ <include name="lib/jaxen-full.jar"/>
+ <include name="lib/saxpath.jar"/>
+ <include name="lib/commons-lang-2.1.jar"/>
+ <include name="lib/commons-logging-1.0.4.jar"/>
+ <include name="struts-2.0.5/lib/antlr-2.7.2.jar"/>
+ <include name="struts-1.2.4/lib/commons-fileupload.jar"/>
+ <include name="struts-1.2.4/lib/commons-validator.jar"/>
+ <include name="struts-1.2.4/lib/commons-collections.jar"/>
+ <include name="lib/commons-id-0.1-SNAPSHOT.jar"/>
+ <include name="buildtime/activation.jar"/>
+ <include name="buildtime/mail.jar"/>
+
+ <!-- needed for Hibernate -->
+ <include name="hibernate-3.1/hibernate3.jar"/>
+ <include name="hibernate-3.1/lib/antlr.jar"/>
+ <include name="hibernate-3.1/lib/asm.jar"/>
+ <include name="hibernate-3.1/lib/asm-attrs.jar"/>
+ <include name="hibernate-3.1/lib/cglib-2.1.3.jar"/>
+ <include name="hibernate-3.1/lib/ehcache-1.1.jar"/>
+ <include name="hibernate-3.1/lib/dom4j-1.6.1.jar"/>
+ <include name="hibernate-3.1/lib/jta.jar"/>
+ <include name="hibernate-3.1/lib/jdbc2_0-stdext.jar"/>
+
+ <!-- needed for JPA -->
+ <include name="toplink-essentials-9.1/toplink-essentials.jar"/>
+
+ </fileset>
+
+ <path id="core.path">
+ <fileset refid="core-jars" />
+ </path>
+
+ <!-- ============================================== -->
+ <!-- clean out any contents from last build -->
+ <target name="clean" description="Clean (i.e. remove) build and dist dirs">
+ <delete dir="${build}" />
+ <delete dir="${dist}" />
+ </target>
+
+
+ <!-- ============================================== -->
+ <!-- build all code -->
+ <target name="build" depends="build-business" >
+ </target>
+
+ <!-- build the business layer code and jar it up -->
+ <target name="build-business">
+
+ <!-- compile planet classes -->
+ <mkdir dir="${build.compile.business}"/>
+ <javac destdir="${build.compile.business}"
+ debug="${build.debug}"
+ source="${build.sourcelevel}"
+ deprecation="${build.deprecation}">
+
+ <src path="${src}" />
+
+ <classpath>
+ <path refid="core.path"/>
+ </classpath>
+ </javac>
+
+ <!-- Copy resources -->
+ <copy todir="${build.compile.business}">
+ <fileset dir="${src}" excludes="**/*.java, **/*.html, **/*.png" />
+ </copy>
+
+ <!-- Jar up the business layer -->
+ <mkdir dir="${build.lib}"/>
+ <jar basedir="${build.compile.business}"
+ jarfile="${build.lib}/roller-core.jar"/>
+
+ </target>
+
+
+ <!-- ============================================== -->
+ <!-- create distributable components -->
+ <target name="dist" depends="build-business" description="Create Roller core distributables">
+
+ <!-- distributable libraries -->
+ <mkdir dir="${dist}/lib" />
+ <copy todir="${dist}/lib" >
+ <fileset dir="${build.lib}" />
+ </copy>
+
+ </target>
+
+</project>
Added: roller/trunk/components/core/src/java/org/apache/roller/RollerException.java
URL: http://svn.apache.org/viewvc/roller/trunk/components/core/src/java/org/apache/roller/RollerException.java?view=auto&rev=541450
==============================================================================
--- roller/trunk/components/core/src/java/org/apache/roller/RollerException.java (added)
+++ roller/trunk/components/core/src/java/org/apache/roller/RollerException.java Thu May 24 15:14:14 2007
@@ -0,0 +1,135 @@
+/*
+ * 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;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+
+/**
+ * Base Roller exception class.
+ */
+public class RollerException extends Exception {
+
+ private Throwable mRootCause = null;
+
+
+ /**
+ * Construct emtpy exception object.
+ */
+ public RollerException() {
+ super();
+ }
+
+
+ /**
+ * Construct RollerException with message string.
+ * @param s Error message string.
+ */
+ public RollerException(String s) {
+ super(s);
+ }
+
+
+ /**
+ * Construct RollerException, wrapping existing throwable.
+ * @param s Error message
+ * @param t Existing connection to wrap.
+ */
+ public RollerException(String s, Throwable t) {
+ super(s);
+ mRootCause = t;
+ }
+
+
+ /**
+ * Construct RollerException, wrapping existing throwable.
+ * @param t Existing exception to be wrapped.
+ */
+ public RollerException(Throwable t) {
+ mRootCause = t;
+ }
+
+
+ /**
+ * Get root cause object, or null if none.
+ * @return Root cause or null if none.
+ */
+ public Throwable getRootCause() {
+ return mRootCause;
+ }
+
+
+ /**
+ * Get root cause message.
+ * @return Root cause message.
+ */
+ public String getRootCauseMessage() {
+ String rcmessage = null;
+ if (getRootCause()!=null) {
+ if (getRootCause().getCause()!=null) {
+ rcmessage = getRootCause().getCause().getMessage();
+ }
+ rcmessage = (rcmessage == null) ? getRootCause().getMessage() : rcmessage;
+ rcmessage = (rcmessage == null) ? super.getMessage() : rcmessage;
+ rcmessage = (rcmessage == null) ? "NONE" : rcmessage;
+ }
+ return rcmessage;
+ }
+
+
+ /**
+ * Print stack trace for exception and for root cause exception if htere is one.
+ * @see java.lang.Throwable#printStackTrace()
+ */
+ public void printStackTrace() {
+ super.printStackTrace();
+ if (mRootCause != null) {
+ System.out.println("--- ROOT CAUSE ---");
+ mRootCause.printStackTrace();
+ }
+ }
+
+
+ /**
+ * Print stack trace for exception and for root cause exception if htere is one.
+ * @param s Stream to print to.
+ */
+ public void printStackTrace(PrintStream s) {
+ super.printStackTrace(s);
+ if (mRootCause != null) {
+ s.println("--- ROOT CAUSE ---");
+ mRootCause.printStackTrace(s);
+ }
+ }
+
+
+ /**
+ * Print stack trace for exception and for root cause exception if htere is one.
+ * @param s Writer to write to.
+ */
+ public void printStackTrace(PrintWriter s) {
+ super.printStackTrace(s);
+ if (null != mRootCause) {
+ s.println("--- ROOT CAUSE ---");
+ mRootCause.printStackTrace(s);
+ }
+ }
+
+}
Added: roller/trunk/components/core/src/java/org/apache/roller/business/hibernate/HibernatePersistenceStrategy.java
URL: http://svn.apache.org/viewvc/roller/trunk/components/core/src/java/org/apache/roller/business/hibernate/HibernatePersistenceStrategy.java?view=auto&rev=541450
==============================================================================
--- roller/trunk/components/core/src/java/org/apache/roller/business/hibernate/HibernatePersistenceStrategy.java (added)
+++ roller/trunk/components/core/src/java/org/apache/roller/business/hibernate/HibernatePersistenceStrategy.java Thu May 24 15:14:14 2007
@@ -0,0 +1,204 @@
+/*
+ * 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.business.hibernate;
+
+import java.io.StringBufferInputStream;
+import java.util.Properties;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.hibernate.cfg.Configuration;
+import org.apache.roller.RollerException;
+import org.hibernate.cfg.Environment;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+
+
+/**
+ * Base class for Hibernate persistence implementation.
+ *
+ * This class serves as a helper/util class for all of the Hibernate
+ * manager implementations by providing a set of basic persistence methods
+ * that can be easily reused.
+ */
+public class HibernatePersistenceStrategy {
+
+ static final long serialVersionUID = 2561090040518169098L;
+
+ protected static SessionFactory sessionFactory = null;
+
+ private static Log log = LogFactory.getLog(HibernatePersistenceStrategy.class);
+
+ /** No-op so XML parser doesn't hit the network looking for Hibernate DTDs */
+ private EntityResolver noOpEntityResolver = new EntityResolver() {
+ public InputSource resolveEntity(String publicId, String systemId) {
+ return new InputSource(new StringBufferInputStream(""));
+ }
+ };
+
+ /**
+ * Persistence strategy configures itself by using Roller properties:
+ * 'hibernate.configResource' - the resource name of Roller's Hibernate XML configuration file,
+ * 'hibernate.dialect' - the classname of the Hibernate dialect to be used,
+ * 'hibernate.connectionProvider - the classname of Roller's connnection provider impl.
+ */
+ public HibernatePersistenceStrategy(String configResource, String dialect, String connectionProvider) {
+
+ // Read Hibernate config file specified by Roller config
+ Configuration config = new Configuration();
+ config.configure(configResource);
+
+ // Add dialect specified by Roller config and our connection provider
+ Properties props = new Properties();
+ props.put(Environment.DIALECT, dialect);
+ props.put(Environment.CONNECTION_PROVIDER, connectionProvider);
+ config.mergeProperties(props);
+
+ this.sessionFactory = config.buildSessionFactory();
+ }
+
+
+ /**
+ * Get persistence session on current thread.
+ *
+ * This will open a new Session if one is not already open, otherwise
+ * it will return the already open Session.
+ */
+ public Session getSession() {
+
+ log.debug("Obtaining Hibernate Session");
+
+ // get Hibernate Session and make sure we are in a transaction
+ // this will join existing Session/Transaction if they exist
+ Session session = sessionFactory.getCurrentSession();
+ session.beginTransaction();
+
+ return session;
+ }
+
+
+ public void flush() throws RollerException {
+
+ Session session = getSession();
+ try {
+ // first lets flush the current state to the db
+ log.debug("Flushing Hibernate Session");
+ session.flush();
+
+ // then commit the current transaction to finish it
+ log.debug("Committing Hibernate Transaction");
+ session.getTransaction().commit();
+
+ } catch(Throwable t) {
+ // uh oh ... failed persisting, gotta release
+ release();
+
+ // wrap and rethrow so caller knows something bad happened
+ throw new RollerException(t);
+ }
+ }
+
+
+ /**
+ * Release database session, rollback any uncommitted changes.
+ *
+ * IMPORTANT: we don't want to open a transaction and force the use of a
+ * jdbc connection just to close the session and do a rollback, so this
+ * method must be sensitive about how the release is triggered.
+ *
+ * In particular we don't want to use our custom getSession() method which
+ * automatically begins a transaction. Instead we get a Session and check
+ * if there is already an active transaction that needs to be rolled back.
+ * If not then we can close the Session without ever getting a jdbc
+ * connection, which is important for scalability.
+ */
+ public void release() {
+
+ try {
+ Session session = sessionFactory.getCurrentSession();
+
+ if(session != null && session.isOpen()) {
+
+ log.debug("Closing Hibernate Session");
+
+ try {
+ Transaction tx = session.getTransaction();
+
+ if(tx != null && tx.isActive()) {
+ log.debug("Forcing rollback on active transaction");
+ tx.rollback();
+ }
+ } catch(Throwable t) {
+ log.error("ERROR doing Hibernate rollback", t);
+ } finally {
+ if(session.isOpen()) {
+ session.close();
+ }
+ }
+ }
+ } catch(Throwable t) {
+ log.error("ERROR closing Hibernate Session", t);
+ }
+ }
+
+
+ /**
+ * Retrieve object. We return null if the object is not found.
+ */
+ public Object load(String id, Class clazz) throws RollerException {
+
+ if(id == null || clazz == null) {
+ throw new RollerException("Cannot load objects when value is null");
+ }
+
+ return (Object) getSession().get(clazz, id);
+ }
+
+
+ /**
+ * Store object.
+ */
+ public void store(Object obj) throws HibernateException {
+
+ if(obj == null) {
+ throw new HibernateException("Cannot save null object");
+ }
+
+ Session session = getSession();
+
+ session.saveOrUpdate(obj);
+ }
+
+
+ /**
+ * Remove object.
+ */
+ public void remove(Object obj) throws HibernateException {
+
+ if(obj == null) {
+ throw new HibernateException("Cannot remove null object");
+ }
+
+ getSession().delete(obj);
+ }
+
+}
Added: roller/trunk/components/core/src/java/org/apache/roller/business/hibernate/ThreadLocalSessionContextNoAutoClose.java
URL: http://svn.apache.org/viewvc/roller/trunk/components/core/src/java/org/apache/roller/business/hibernate/ThreadLocalSessionContextNoAutoClose.java?view=auto&rev=541450
==============================================================================
--- roller/trunk/components/core/src/java/org/apache/roller/business/hibernate/ThreadLocalSessionContextNoAutoClose.java (added)
+++ roller/trunk/components/core/src/java/org/apache/roller/business/hibernate/ThreadLocalSessionContextNoAutoClose.java Thu May 24 15:14:14 2007
@@ -0,0 +1,130 @@
+/*
+ * 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.business.hibernate;
+
+import org.hibernate.FlushMode;
+import org.hibernate.SessionFactory;
+import org.hibernate.classic.Session;
+import org.hibernate.context.ThreadLocalSessionContext;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+
+/**
+ * This is a special Hibernate SessionContext which was taken from the Hibernate forums so that we can use it
+ * to provide a way to commit our transactions while keeping the Session open for further use. Details here ...
+ *
+ * http://forum.hibernate.org/viewtopic.php?t=958752
+ *
+ * ... which was found from a reference here ...
+ *
+ * http://forum.hibernate.org/viewtopic.php?t=957056
+ *
+ * Extends {@link ThreadLocalSessionContext} to allow for long conversations. It achieves this by setting every
+ * <code>Session</code> it produces to <code>FlushMode.NEVER</code> so that it won't flush unless explicitly asked
+ * to, and by preventing the session from auto-closing or unbinding from the thread after a <code>Transaction</code>
+ * commit. Note that this means the application code must do these functions manually as needed!
+ */
+public class ThreadLocalSessionContextNoAutoClose extends ThreadLocalSessionContext {
+
+ /**
+ * Create a new instance.
+ *
+ * @param factory The <code>SessionFactoryImplementor</code> required by the super constructor.
+ */
+ public ThreadLocalSessionContextNoAutoClose(SessionFactoryImplementor factory) {
+ super(factory);
+ }
+
+
+ /**
+ * Returns <code>false</code> to prevent auto closing.
+ *
+ * @return <code>false</code> to prevent auto closing.
+ */
+ protected boolean isAutoCloseEnabled() {
+ return false;
+ }
+
+
+ /**
+ * Returns <code>false</code> to prevent auto flushing.
+ *
+ * @return <code>false</code> to prevent auto flushing.
+ */
+ protected boolean isAutoFlushEnabled() {
+ return false;
+ }
+
+
+ /**
+ * Uses <code>super.buildOrObtainSession()</code>, then sets the resulting <code>Session</code>'s flush mode
+ * to <code>FlushMode.NEVER</code> to prevent auto-flushing.
+ *
+ * @return A session configured with <code>FlushMode.NEVER</code>.
+ */
+ protected Session buildOrObtainSession() {
+ Session s = super.buildOrObtainSession();
+ s.setFlushMode(FlushMode.NEVER);
+ return s;
+ }
+
+
+ /**
+ * Returns an instance of <code>CleanupSynch</code> which prevents auto closing and unbinding.
+ *
+ * @return A <code>CleanupSynch</code> which prevents auto closing and unbinding.
+ */
+ protected CleanupSynch buildCleanupSynch() {
+ return new NoCleanupSynch(factory);
+ }
+
+
+ /**
+ * A simple extension of <code>CleanupSynch</code> that prevents any cleanup from happening. No session closing or
+ * unbinding.
+ */
+ private static class NoCleanupSynch extends ThreadLocalSessionContext.CleanupSynch {
+
+ /**
+ * Creates a new instance based on the given factory.
+ *
+ * @param factory The required <code>SessionFactory</code> that is passed to the super constructor.
+ */
+ public NoCleanupSynch(SessionFactory factory) {
+ super(factory);
+ }
+
+ /**
+ * Does nothing, thus helping to prevent session closing and/or unbinding.
+ */
+ public void beforeCompletion() {
+ // do nothing
+ }
+
+ /**
+ * Does nothing, thus helping to prevent session closing and/or unbinding.
+ *
+ * @param i
+ */
+ public void afterCompletion(int i) {
+ // do nothing
+ }
+ }
+
+}
Added: roller/trunk/components/core/src/java/org/apache/roller/business/jpa/JPAPersistenceStrategy.java
URL: http://svn.apache.org/viewvc/roller/trunk/components/core/src/java/org/apache/roller/business/jpa/JPAPersistenceStrategy.java?view=auto&rev=541450
==============================================================================
--- roller/trunk/components/core/src/java/org/apache/roller/business/jpa/JPAPersistenceStrategy.java (added)
+++ roller/trunk/components/core/src/java/org/apache/roller/business/jpa/JPAPersistenceStrategy.java Thu May 24 15:14:14 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.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.RollerException;
+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.RollerException on any error
+ */
+ public JPAPersistenceStrategy(
+ String puName,
+ String jndiName,
+ Properties properties) throws RollerException {
+
+ // 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 RollerException(pe);
+ }
+ }
+
+ /**
+ * Construct by finding JPA EntityManagerFactory.
+ * @throws org.apache.roller.RollerException on any error
+ */
+ public JPAPersistenceStrategy(
+ String puName,
+ String driverClass,
+ String connectonUrl,
+ String username,
+ String password,
+ Properties properties) throws RollerException {
+
+ 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 RollerException(pe);
+ }
+ }
+
+ /**
+ * Flush changes to the datastore, commit transaction, release em.
+ * @throws org.apache.roller.RollerException on any error
+ */
+ public void flush() throws RollerException {
+ try {
+ EntityManager em = getEntityManager(true);
+ em.getTransaction().commit();
+ } catch (PersistenceException pe) {
+ throw new RollerException(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.RollerException on any error
+ */
+ public Object store(Object obj) throws RollerException {
+ 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 RollerException on any error deleting object
+ */
+ public void remove(Class clazz, String id) throws RollerException {
+ 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.RollerException on any error
+ */
+ public void remove(Object po) throws RollerException {
+ EntityManager em = getEntityManager(true);
+ em.remove(po);
+ }
+
+ /**
+ * Remove object from persistence storage.
+ * @param pos the persistent objects to remove
+ * @throws org.apache.roller.RollerException on any error
+ */
+ public void removeAll(Collection pos) throws RollerException {
+ 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 RollerException on any error retrieving object
+ */
+ public Object load(Class clazz, String id)
+ throws RollerException {
+ 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.RollerException on any error
+ */
+ public Query getNamedQuery(String queryName)
+ throws RollerException {
+ 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.RollerException on any error
+ */
+ public Query getDynamicQuery(String queryString)
+ throws RollerException {
+ 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.RollerException on any error
+ */
+ public Query getNamedUpdate(String queryName)
+ throws RollerException {
+ 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 RollerException
+ */
+ private static Properties loadPropertiesFromResourceName(
+ String resourceName, ClassLoader cl) throws RollerException {
+ Properties props = new Properties();
+ InputStream in = null;
+ in = cl.getResourceAsStream(resourceName);
+ if (in == null) {
+ //TODO: Check how i18n is done in roller
+ throw new RollerException(
+ "Could not locate properties to load " + resourceName);
+ }
+ try {
+ props.load(in);
+ } catch (IOException ioe) {
+ throw new RollerException(
+ "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();
+ }
+ });
+ }
+}
+
Added: roller/trunk/components/core/src/java/org/apache/roller/util/UUIDGenerator.java
URL: http://svn.apache.org/viewvc/roller/trunk/components/core/src/java/org/apache/roller/util/UUIDGenerator.java?view=auto&rev=541450
==============================================================================
--- roller/trunk/components/core/src/java/org/apache/roller/util/UUIDGenerator.java (added)
+++ roller/trunk/components/core/src/java/org/apache/roller/util/UUIDGenerator.java Thu May 24 15:14:14 2007
@@ -0,0 +1,43 @@
+/*
+ * 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.util;
+
+import org.apache.commons.id.uuid.VersionFourGenerator;
+
+
+/**
+ * Generates UUID values.
+ */
+public class UUIDGenerator {
+
+ private static final VersionFourGenerator uuidGenerator = new VersionFourGenerator();
+
+
+ // non-instantiable
+ private UUIDGenerator() {}
+
+
+ /**
+ * Generate a new UUID.
+ */
+ public static String generateUUID() {
+ return uuidGenerator.nextIdentifier().toString();
+ }
+
+}