r2498 - in trunk: topia-persistence topia-persistence/src/main/java/org/nuiton/topia topia-persistence/src/main/java/org/nuiton/topia/framework topia-persistence/src/main/resources/i18n topia-persistence-hibernate/src/main/java/org/nuiton/topia/persistence topia-persistence-tck/src/test/java/org/nuiton/topia/framework
Author: athimel Date: 2012-05-23 15:00:47 +0200 (Wed, 23 May 2012) New Revision: 2498 Url: http://nuiton.org/repositories/revision/topia/2498 Log: TopiaContextImpl cleaning and commented code reactivation Depreciate import/exportXML and move to TopiaSpecificUtil Create a H2 specific util for backup/restore/clean Added: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaH2Util.java Modified: trunk/topia-persistence-hibernate/src/main/java/org/nuiton/topia/persistence/TopiaHibernateSpecificUtil.java trunk/topia-persistence-tck/src/test/java/org/nuiton/topia/framework/TopiaContextImplTest.java trunk/topia-persistence/pom.xml trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaContext.java trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImpl.java trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaSpecificUtil.java trunk/topia-persistence/src/main/resources/i18n/topia-persistence_en_GB.properties trunk/topia-persistence/src/main/resources/i18n/topia-persistence_es_ES.properties trunk/topia-persistence/src/main/resources/i18n/topia-persistence_fr_FR.properties Modified: trunk/topia-persistence/pom.xml =================================================================== --- trunk/topia-persistence/pom.xml 2012-05-23 09:18:09 UTC (rev 2497) +++ trunk/topia-persistence/pom.xml 2012-05-23 13:00:47 UTC (rev 2498) @@ -122,6 +122,12 @@ <scope>test</scope> </dependency> + <!-- TODO AThimel 23/05/2012 Remove when import/exportXML are removed from TopiaContextImpl --> + <dependency> + <groupId>dom4j</groupId> + <artifactId>dom4j</artifactId> + </dependency> + </dependencies> <build> Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaContext.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaContext.java 2012-05-23 09:18:09 UTC (rev 2497) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/TopiaContext.java 2012-05-23 13:00:47 UTC (rev 2498) @@ -31,6 +31,7 @@ import org.nuiton.topia.event.TopiaEntityVetoable; import org.nuiton.topia.event.TopiaTransactionListener; import org.nuiton.topia.event.TopiaTransactionVetoable; +import org.nuiton.topia.framework.TopiaH2Util; import org.nuiton.topia.framework.TopiaQuery; import org.nuiton.topia.framework.TopiaService; import org.nuiton.topia.persistence.TopiaEntity; @@ -211,6 +212,9 @@ /** * Permet de faire une requete HQL hibernate directement sur la base. * + * WARNING : Depending on the registered service, this method may not + * support something else than queries on TopiaEntity + * * @param hql la requete a faire * @param args les arguments de la requete * @return La liste des resultats @@ -223,6 +227,9 @@ * precisant la fenetre des elements a remonter avec les parametres {@code * startIndex} et {@code endIndex}. * + * WARNING : Depending on the registered service, this method may not + * support something else than queries on TopiaEntity + * * @param hql la requete a faire * @param startIndex la position du premier element a remonter * @param endIndex la position du dernier element a remonter @@ -257,7 +264,9 @@ * * @param xml le flux XML * @throws TopiaException si une erreur survient durant l'import + * @deprecated nobody uses it, will be removed in future versions */ + @Deprecated void importXML(Reader xml) throws TopiaException; /** @@ -272,7 +281,9 @@ * where que doit respecter l'objet pour etre * exporter (entityClass, condition) * @throws TopiaException si une erreur survient durant l'export + * @deprecated nobody uses it, will be removed in future versions */ + @Deprecated void exportXML(Writer xml, Object... entityAndCondition) throws TopiaException; @@ -331,6 +342,29 @@ throws TopiaException, IllegalArgumentException; /** + * Closes the context. All the child contexts will be closed in the same + * time. + * + * @throws TopiaException if any exception + */ + void closeContext() throws TopiaException; + + /** + * Indique si le contexte a ete fermé. + * + * @return {@code true} si le context est fermé, {@code false} autrement + */ + boolean isClosed(); + + /** + * Execute a given sql code inside this transaction. + * + * @param sqlScript the sql script to execute + * @throws TopiaException if any problem occurs while executing the sql script. + */ + void executeSQL(String sqlScript) throws TopiaException; + + /** * Sauve la base de données dans un format natif a la base, la * representation n'est pas portable d'une base a l'autre. Cette methode ne * doit être utilisé que pour un stockage temporaire utile à une @@ -339,7 +373,10 @@ * @param file le nom du fichier ou stocker les informations * @param compress si vrai compress le fichier avec gzip * @throws TopiaException if any exception + * @deprecated use database specific class : {@link TopiaH2Util} + * @see TopiaH2Util#backup(File, boolean) */ + @Deprecated void backup(File file, boolean compress) throws TopiaException; /** @@ -348,7 +385,10 @@ * @param file le fichier ou prendre les informations, il peut-etre * compressé avec gzip ou non. * @throws TopiaException if any exception + * @deprecated use database specific class : {@link TopiaH2Util} + * @see TopiaH2Util#restore(File) */ + @Deprecated void restore(File file) throws TopiaException; /** @@ -359,30 +399,10 @@ * supprimé (ex: h2) ou sera fait sur la base * (postgresql) * @throws TopiaException if any exception + * @deprecated use database specific class : {@link TopiaH2Util} + * @see TopiaH2Util#clear(boolean) */ + @Deprecated void clear(boolean dropDatabase) throws TopiaException; - /** - * Closes the context. All the child contexts will be closed in the same - * time. - * - * @throws TopiaException if any exception - */ - void closeContext() throws TopiaException; - - /** - * Indique si le contexte a ete fermé. - * - * @return {@code true} si le context est fermé, {@code false} autrement - */ - boolean isClosed(); - - /** - * Execute a given sql code inside this transaction. - * - * @param sqlScript the sql script to execute - * @throws TopiaException if any problem occurs while executing the sql script. - */ - void executeSQL(String sqlScript) throws TopiaException; - } //TopiaContext Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImpl.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImpl.java 2012-05-23 09:18:09 UTC (rev 2497) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaContextImpl.java 2012-05-23 13:00:47 UTC (rev 2498) @@ -25,12 +25,21 @@ package org.nuiton.topia.framework; +import com.google.common.base.Predicate; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentFactory; +import org.dom4j.Element; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.SAXReader; +import org.dom4j.io.XMLWriter; import org.nuiton.topia.TopiaContext; import org.nuiton.topia.TopiaContextFactory; import org.nuiton.topia.TopiaException; @@ -56,15 +65,16 @@ import javax.persistence.Query; import javax.persistence.metamodel.EntityType; import java.beans.PropertyChangeListener; -import java.io.BufferedInputStream; import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; +import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.lang.reflect.Field; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; @@ -74,22 +84,7 @@ import java.util.Properties; import java.util.Set; import java.util.WeakHashMap; -import java.util.zip.GZIPInputStream; - -//import org.hibernate.EntityMode; -//import org.hibernate.ReplicationMode; -//import org.hibernate.event.PostDeleteEventListener; -//import org.hibernate.event.PostInsertEventListener; -//import org.hibernate.event.PostLoadEventListener; -//import org.hibernate.event.PostUpdateEventListener; -//import org.hibernate.event.PreDeleteEventListener; -//import org.hibernate.event.PreInsertEventListener; -//import org.hibernate.event.PreLoadEventListener; -//import org.hibernate.event.PreUpdateEventListener; -//import org.hibernate.tool.hbm2ddl.SchemaExport; -//import org.hibernate.tool.hbm2ddl.SchemaUpdate; - /** * Le TopiaContextImpl est le point d'entrée pour accéder aux données. Il est * configuré par un fichier de propriétés. @@ -122,6 +117,17 @@ private static final Log log = LogFactory.getLog(TopiaContextImpl.class); /** + * Predicate to know if the given context is the root context + */ + protected final static Predicate<TopiaContextImplementor> IS_ROOT_CONTEXT = + new Predicate<TopiaContextImplementor>() { + @Override + public boolean apply(TopiaContextImplementor context) { + return context.getParentContext() == null; + } + }; + + /** * This context's parent. Root contexts does not have a parent context */ protected TopiaContextImplementor parentContext; @@ -467,9 +473,6 @@ // hibernateConfiguration.addDirectory(new File(dir)); // } // } - -// // tchemit 2011-05-26 When using hibernate > 3.3, need to make sure all mappings are loaded (the one from directory files are not still done). -// hibernateConfiguration.buildMappings(); // } // } // return hibernateConfiguration; @@ -477,7 +480,6 @@ /* -------------------- CHILD CONTEXT AND DAOS --------------------------*/ - @SuppressWarnings({"unchecked"}) @Override public <E extends TopiaEntity> TopiaDAO<E> getDAO(Class<E> entityClass) throws TopiaException { @@ -487,12 +489,12 @@ "getDAO", "entityClass"); throw new IllegalArgumentException(message); } - if (equals(getRootContext())) { + if (IS_ROOT_CONTEXT.apply(this)) { throw new TopiaException( "You are on root context, you MUST open a transaction to perform any database access."); } Set<EntityType<?>> entities = getEntityManagerFactory().getMetamodel().getEntities(); - boolean found; + boolean found = false; for (EntityType<?> entityType : entities) { String entityName = entityType.getName(); found = @@ -503,13 +505,17 @@ break; } } -// if (!found) { -// log.info(_("topia.persistence.supported.classes.for.context", -// getEntityManagerFactory().getMetamodel().getEntities())); -// throw new TopiaException(String.format( -// "Entity type '%s' not managed by this context, you probably forgot to declare it.", -// entityClass.getName())); -// } + if (!found) { + if (log.isInfoEnabled()) { + String logMessage = String.format( + "List of supported persistence classes : %s", entities); + log.info(logMessage); + } + String exceptionMessage = String.format( + "Entity type '%s' not managed by this context, you probably forgot to declare it.", + entityClass.getName()); + throw new TopiaException(exceptionMessage); + } TopiaDAO<E> result = (TopiaDAO<E>) daoCache.get(entityClass); if (result == null) { @@ -521,8 +527,7 @@ try { Class<TopiaDAO<E>> daoClass = (Class<TopiaDAO<E>>) Class.forName(daoClassname); - TopiaDAO<E> spe = daoClass.getConstructor().newInstance(); - result = spe; + result = daoClass.getConstructor().newInstance(); } catch (Exception eee) { log.warn("specialized DAO " + daoClassname + " not found, use default TopiaDAOHibernate"); @@ -535,7 +540,6 @@ return result; } - @SuppressWarnings({"unchecked"}) @Override public <E extends TopiaEntity, D extends TopiaDAO<E>> D getDAO( Class<E> entityClass, Class<D> daoClass) throws TopiaException { @@ -582,7 +586,7 @@ } throw new TopiaException( - "An error occured while getting a new transaction : " + "An error occurred while getting a new transaction : " + eee.getMessage(), eee); } @@ -596,18 +600,13 @@ @Override public void commitTransaction() throws TopiaException { - boolean isRootContext = equals(getRootContext()); - if (isRootContext) { + if (IS_ROOT_CONTEXT.apply(this)) { String message = String.format("Operation '%s' is not permitted on root context", "commitTransaction"); throw new TopiaException(message); } checkClosed("commitTransaction"); try { -// for (TopiaDAO<? extends TopiaEntity> dao : daoCache.values()) { -// // TODO-fdesbois-20100507 : need to be removed for 2.5 version -// dao.commitTransaction(); -// } EntityTransaction tx = entityManager.getTransaction(); entityManager.flush(); tx.commit(); @@ -618,34 +617,23 @@ parent.getFiresSupport().fireOnPostCommit(this); } -// hibernate.beginTransaction(); entityManager.getTransaction().begin(); - // it's seem necessary to change session after commit - // NON, NON, NON, il ne faut surtout pas le faire, ca pose plein de - // probleme - // hibernate = getEntityManagerFactory().openSession(); - // hibernate.setFlushMode(FlushMode.NEVER); } catch (Exception eee) { - throw new TopiaException( - "An error occured during commit operation : " + + "An error occurred during commit operation : " + eee.getMessage(), eee); } } @Override public void rollbackTransaction() throws TopiaException { - if (equals(getRootContext())) { + if (IS_ROOT_CONTEXT.apply(this)) { String message = String.format("Operation '%s' is not permitted on root context", "rollbackTransaction"); throw new TopiaException(message); } checkClosed("rollbackTransaction"); try { -// for (TopiaDAO<? extends TopiaEntity> dao : daoCache.values()) { -// // TODO-fdesbois-20100507 : need to be removed for 2.5 version -// dao.rollbackTransaction(); -// } EntityTransaction tx = entityManager.getTransaction(); entityManager.clear(); tx.rollback(); @@ -655,7 +643,6 @@ entityManager = getEntityManagerFactory().createEntityManager(); entityManager.setFlushMode(FlushModeType.COMMIT); // TODO AThimel 07/05/2012 Was MANUAL -// hibernate.beginTransaction(); entityManager.getTransaction().begin(); getFiresSupport().fireOnPostRollback(this); @@ -666,22 +653,15 @@ } catch (PersistenceException eee) { throw new TopiaException( - "An error occured during rollback operation : " + + "An error occurred during rollback operation : " + eee.getMessage(), eee); } } @Override public void closeContext() throws TopiaException { - // Throw exception if context is already closed checkClosed("closeContext"); - // FD-20100421 : Ano #546 : no need to copy childContexts, the - // {@link #getChildContext()} provides a thread-safe copy to iterate - // on it. -// TopiaContextImplementor[] children = childContexts.toArray( -// new TopiaContextImplementor[childContexts.size()]); - // Remove all children context for (TopiaContextImplementor child : getChildContexts()) { // Avoid to have exception from checkClosed method on child @@ -690,19 +670,19 @@ } } - // on se desenregistre du context pere et on ferme les connexions si - // on est pas le root context - if (!equals(getRootContext())) { - closed = true; - entityManager.close(); - getParentContext().removeChildContext(this); - } else { + if (IS_ROOT_CONTEXT.apply(this)) { if (entityManagerFactory != null) { entityManagerFactory.close(); closed = true; TopiaContextFactory.removeContext(this); log.debug("TopiaContext removed"); } + } else { + // on se desenregistre du context pere et on ferme les connexions si + // on est pas le root context + closed = true; + entityManager.close(); + getParentContext().removeChildContext(this); } } @@ -711,10 +691,8 @@ */ @Override protected void finalize() throws Throwable { - if (entityManagerFactory != null) { + if (!isClosed()) { closeContext(); - entityManagerFactory.close(); - closed = true; log.debug("TopiaContext finalized"); } } @@ -726,7 +704,9 @@ protected void checkClosed(String method) throws TopiaException { if (closed) { - String message = String.format("This context is closed, unable to perform operation '%s'", method); + String message = String.format( + "This context is closed, unable to perform operation '%s'", + method); throw new TopiaException(message); } } @@ -848,7 +828,6 @@ /* -------------------- GLOBAL OPERATIONS ON SCHEMA ----------------------*/ - @SuppressWarnings({"unchecked"}) @Override public TopiaEntity findByTopiaId(String id) throws TopiaException { checkClosed("findByTopiaId"); @@ -864,7 +843,6 @@ return query.execute(this); } - @SuppressWarnings({"unchecked"}) @Override public TopiaQuery createQuery(Class<?> entityClass, String alias) { return new TopiaQuery((Class<? extends TopiaEntity>)entityClass, alias); @@ -872,34 +850,16 @@ @Override public List<?> find(String hql, Object... args) throws TopiaException { - checkClosed("find"); + List<?> result = find(hql, 0, -1, args); + return result; + } - try { - Query query = getEntityManager().createQuery(hql); - for (int j = 0; j < args.length; j += 2) { - String name = (String) args[j]; - Object value = args[j + 1]; - if (value.getClass().isArray()) { - List<Object> values = Arrays.asList((Object[]) value); - query.setParameter(name, values); -// query.setParameterList(name, value); -// } else if (value instanceof Collection<?>) { -// query.setParameterList(name, (Collection<?>) value); - } else { - query.setParameter(name, value); - } - } - // tchemit 2010-11-30 reproduce the same behaviour than before with the dao legacy - if (useFlushMode) { - query.setFlushMode(FlushModeType.AUTO); - } - List result = query.getResultList(); - result = firesSupport.fireEntitiesLoad(this, result); - return result; - } catch (PersistenceException eee) { - String message = String.format("An error occured (%s) during a query operation : %s", eee.getMessage(), hql); - throw new TopiaException(message, eee); + protected Object transformArrayToCollection(Object value) { + Object result = value; + if (value.getClass().isArray()) { + result = Arrays.asList((Object[]) value); } + return result; } @Override @@ -911,15 +871,13 @@ Query query = getEntityManager().createQuery(hql); for (int j = 0; j < args.length; j += 2) { String name = (String) args[j]; - Object value = args[j + 1]; -// if (value.getClass().isArray()) { -// query.setParameterList(name, (Object[]) value); -// } else { - query.setParameter(name, value); -// } + Object value = transformArrayToCollection(args[j + 1]); + query.setParameter(name, value); } query.setFirstResult(startIndex); - query.setMaxResults(endIndex - startIndex + 1); + if (endIndex >= 0) { + query.setMaxResults(endIndex - startIndex + 1); + } // tchemit 2010-11-30 reproduce the same behaviour than before with the dao legacy if (useFlushMode) { query.setFlushMode(FlushModeType.AUTO); @@ -928,7 +886,9 @@ result = firesSupport.fireEntitiesLoad(this, result); return result; } catch (PersistenceException eee) { - String message = String.format("An error occured (%s) during a query operation : %s", eee.getMessage(), hql); + String message = String.format( + "An error occurred (%s) during a query operation : %s", + eee.getMessage(), hql); throw new TopiaException(message, eee); } } @@ -948,12 +908,16 @@ try { Query query = getEntityManager().createQuery(hql); for (int j = 0; j < args.length; j += 2) { - query.setParameter((String) args[j], args[j + 1]); + String name = (String) args[j]; + Object value = transformArrayToCollection(args[j + 1]); + query.setParameter(name, value); } int result = query.executeUpdate(); return result; } catch (PersistenceException eee) { - String message = String.format("An error occured (%s) during a query operation : %s", eee.getMessage(), hql); + String message = String.format( + "An error occurred (%s) during a query operation : %s", + eee.getMessage(), hql); throw new TopiaException(message, eee); } } @@ -978,6 +942,7 @@ } } + // TODO AThimel 23/05/2012 Work not supported anymore ? // public static class SQLWork implements Work { // private final String script; // @@ -1012,15 +977,13 @@ @Override public void createSchema() throws TopiaException { try { - boolean showSchema = false; - if (log.isDebugEnabled()) { - showSchema = true; - } + boolean showSchema = log.isDebugEnabled(); getFiresSupport().firePreCreateSchema(this); getSpecificUtil().createSchema(showSchema); getFiresSupport().firePostCreateSchema(this); } catch (PersistenceException eee) { - throw new TopiaException("Schema could not be created for the following reason : " + throw new TopiaException( + "Schema could not be created for the following reason : " + eee.getMessage(), eee); } } @@ -1030,7 +993,8 @@ try { getSpecificUtil().showCreateSchema(); } catch (PersistenceException eee) { - throw new TopiaException("Schema creation could not be displayed for the following reason : " + throw new TopiaException( + "Schema creation could not be displayed for the following reason : " + eee.getMessage(), eee); } } @@ -1038,15 +1002,13 @@ @Override public void updateSchema() throws TopiaException { try { - boolean showSchema = false; - if (log.isDebugEnabled()) { - showSchema = true; - } + boolean showSchema = log.isDebugEnabled(); getFiresSupport().firePreUpdateSchema(this); getSpecificUtil().updateSchema(showSchema); getFiresSupport().firePostUpdateSchema(this); } catch (PersistenceException eee) { - throw new TopiaException("Schema could not be updated for the following reason : " + throw new TopiaException( + "Schema could not be updated for the following reason : " + eee.getMessage(), eee); } } @@ -1055,12 +1017,16 @@ /* -------------------- SERVICES MANAGMENT -------------------------------*/ protected String getProperExceptionMessage(Throwable eee) { - return eee.getClass().getSimpleName() + " : " + - eee.getMessage(); + String exceptionName = eee.getClass().getSimpleName(); + String exceptionMessage = eee.getMessage(); + String result = exceptionName + " : " + exceptionMessage; + return result; } protected Map<String, TopiaService> loadServices(Properties config) { + Map<String, TopiaService> result = new HashMap<String, TopiaService>(); + // recherche des services present dans la config for (Enumeration<?> e = config.propertyNames(); e.hasMoreElements();) { String key = (String) e.nextElement(); @@ -1121,16 +1087,11 @@ return result; } - protected boolean serviceEnabled(String name) { - boolean result = getServices().containsKey(name); - return result; - } - /** * Retrieve service name using SERVICE_NAME static field on service * interface. * - * @param interfaceService class of the service + * @param serviceInterface class of the service * @param <E> type of the service that extends {@link * TopiaService} * @return the service name @@ -1138,9 +1099,9 @@ * @throws NoSuchFieldException if no field SERVICE_NAME is defined */ protected <E extends TopiaService> String getServiceName( - Class<E> interfaceService) + Class<E> serviceInterface) throws IllegalAccessException, NoSuchFieldException { - Field f = interfaceService.getField("SERVICE_NAME"); + Field f = serviceInterface.getField("SERVICE_NAME"); String name = (String) f.get(null); return name; } @@ -1159,19 +1120,21 @@ } @Override - public <E extends TopiaService> E getService(Class<E> interfaceService) + public <E extends TopiaService> E getService(Class<E> serviceInterface) throws TopiaNotFoundException { E result; try { - String name = getServiceName(interfaceService); + String name = getServiceName(serviceInterface); result = (E) getService(name); } catch (Exception eee) { - String message = String.format("Could not retrieve service '%s' for following reason : %s", interfaceService, getProperExceptionMessage(eee)); + String message = String.format( + "Could not retrieve service '%s' for following reason : %s", + serviceInterface, getProperExceptionMessage(eee)); throw new TopiaNotFoundException(message, eee); } if (result == null) { throw new TopiaNotFoundException( - String.format("The service '%s' not found.", interfaceService)); + String.format("Service '%s' not found.", serviceInterface)); } return result; } @@ -1182,7 +1145,7 @@ boolean result = false; try { String name = getServiceName(interfaceService); - result = serviceEnabled(name); + result = isServiceEnabled(name); } catch (Exception eee) { String message = String.format( "The service named '%s' could not be found for following reason : %s", @@ -1196,116 +1159,78 @@ return result; } + protected boolean isServiceEnabled(String name) { + boolean result = getServices().containsKey(name); + return result; + } + /* ------------------ IMPORT / EXPORT / REPLICATION ---------------------*/ @Override public void importXML(Reader xml) throws TopiaException { -// checkClosed(String.format("This context is closed, it is not possible to perform the operation '%s'", -// "importXML")); -// -// Document doc; -// -// SAXReader xmlReader = new SAXReader(); -// try { -// doc = xmlReader.read(xml); -// if (log.isDebugEnabled()) { -// log.debug("Lecture du document terminee"); -// } -// } catch (DocumentException de) { -// throw new TopiaException( -// "Could not read XML document for following reason : %s" + -// de.getMessage(), de); -// } -// -// if (doc != null) { -// Session sessionDom4j = getEntityManager().getSession(EntityMode.DOM4J); -// Element rootElement = doc.getRootElement(); -// Iterator<?> it = rootElement.elementIterator(); -// while (it.hasNext()) { -// Element entity = (Element) it.next(); -// try { -// sessionDom4j.replicate(entity, ReplicationMode.EXCEPTION); -// } catch (PersistenceException he) { -// log.warn(String.format( -// "Could not replicate entity '%s' pour following reason : %s", -// entity, he.getMessage()), he); -// } -// } -// // must commit data, otherwise : no effects... -// sessionDom4j.flush(); -// } else { -// throw new TopiaException("Empty document"); -// } + checkClosed("importXML"); + + Document doc; + + SAXReader xmlReader = new SAXReader(); + try { + doc = xmlReader.read(xml); + if (log.isDebugEnabled()) { + log.debug("Lecture du document terminee"); + } + } catch (DocumentException de) { + throw new TopiaException( + "Could not read XML document for following reason : %s" + + de.getMessage(), de); + } + + if (doc != null) { + Element rootElement = doc.getRootElement(); + List<Element> elements = Lists.newArrayList(rootElement.elementIterator()); + + getSpecificUtil().importXML(this, elements); + } else { + throw new TopiaException("Empty document"); + } } @Override - public void exportXML(Writer xml, Object... entityAndcondition) + public void exportXML(Writer xml, Object... entityAndCondition) throws TopiaException { -// checkClosed(String.format("This context is closed, it is not possible to perform the operation '%s'", -// "exportXML")); -// -// String[] queries = buildQueries(entityAndcondition); -// -// // performs queries -// try { -// Session sessionDom4j = getEntityManager().getSession(EntityMode.DOM4J); -// -// Document doc = DocumentFactory.getInstance().createDocument(); -// Element rootElement = doc.addElement("topiaExport"); -// DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); -// String date = format.format(new Date(System.currentTimeMillis())); -// rootElement.addAttribute("date", date); -// -// for (String query : queries) { -// List<?> list = sessionDom4j.createQuery(query).list(); -// for (Object o : list) { -// rootElement.add((Element) o); -// } -// } -// -// /*for (int i = 0; i < entityAndcondition.length;) { -// try { -// entityClass = (Class) entityAndcondition[i++]; -// condition = (String) entityAndcondition[i++]; -// -// String query = "from " + entityClass.getName(); -// if (condition != null && !condition.isEmpty()) { -// query += " where " + condition; -// } -// -// for (Object o : sessionDom4j.createQuery(query).list()) { -// rootElement.add((Element) o); -// } -// } catch (ClassCastException eee) { -// if (i % 2 == 0) { -// throw new IllegalArgumentException( -// "Others arguement must be String not " -// + entityAndcondition[i - 1], eee); -// } else { -// throw new IllegalArgumentException( -// "Others arguement must be Class not " -// + entityAndcondition[i - 1], eee); -// } -// } catch (IndexOutOfBoundsException eee) { -// throw new IllegalArgumentException( -// "Others arguement must be couple of (Class, String)", -// eee); -// } -// }*/ -// -// XMLWriter result = new XMLWriter(xml, -// OutputFormat.createPrettyPrint()); -// result.write(doc); -// result.close(); -// -// } catch (PersistenceException eee) { -// throw new TopiaException("An error occurred during export operation : %s" + -// eee.getMessage(), eee); -// } catch (IOException eee) { -// throw new TopiaException("An error occurred during export operation : %s" + -// eee.getMessage(), eee); -// } + checkClosed("exportXML"); + + List<String> queries = buildQueries(entityAndCondition); + + // performs queries + try { + + Document doc = DocumentFactory.getInstance().createDocument(); + Element rootElement = doc.addElement("topiaExport"); + DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); + String date = format.format(new Date(System.currentTimeMillis())); + rootElement.addAttribute("date", date); + + List<Element> elements = getSpecificUtil().exportXML(this, queries); + + for (Element element : elements) { + rootElement.add(element); + } + + OutputFormat prettyPrint = OutputFormat.createPrettyPrint(); + XMLWriter result = new XMLWriter(xml, prettyPrint); + result.write(doc); + result.close(); + + } catch (PersistenceException eee) { + throw new TopiaException( + "An error occurred during export operation : %s" + + eee.getMessage(), eee); + } catch (IOException eee) { + throw new TopiaException( + "An error occurred during export operation : %s" + + eee.getMessage(), eee); + } } @Override @@ -1320,7 +1245,7 @@ throw new IllegalArgumentException("Can not perform a replication operation on same database."); } - String[] queries = buildQueries(entityAndCondition); + List<String> queries = buildQueries(entityAndCondition); try { for (String query : queries) { if (log.isDebugEnabled()) { @@ -1346,7 +1271,6 @@ throws TopiaException, IllegalArgumentException { checkClosed("replicateEntity"); - TopiaContextImpl destinationContextImpl = (TopiaContextImpl) destinationContext; destinationContextImpl.checkClosed("replicateEntity"); @@ -1372,108 +1296,6 @@ } /** - * Backup database in gzip compressed file. - * - * <b>Note: </b> Only works for h2 database. - * - * @param file file to write backup - * @param compress if true then use gzip to compress file - * @see TopiaContext#backup(File,boolean) - */ - @Override - public void backup(File file, boolean compress) throws TopiaException { - checkClosed("backup"); - try { - String options = ""; - if (compress) { - options += " COMPRESSION GZIP"; - } - - Query query = getEntityManager().createNativeQuery( - "SCRIPT TO '" + file.getAbsolutePath() + "'" + options); - query.getResultList(); - - } catch (Exception eee) { - throw new TopiaException( - "Unable to backup to file : " + eee.getMessage(), eee); - } - } - - /** - * Read database from gzip compressed file - * <p/> - * Only work for h2 database - * - * @see TopiaContext#restore(File) - */ - @Override - public void restore(File file) throws TopiaException { - // send event - getFiresSupport().firePreRestoreSchema(this); - checkClosed("restore"); - - String sql = null; - String options = ""; - try { - // decompresse file in temporary file - InputStream in = new BufferedInputStream(new FileInputStream(file)); - try { - in.mark(2); - - // read header to see if is compressed file - int b = in.read(); - // redundant cast : int magic = ((int) in.read() << 8) | b; - int magic = in.read() << 8 | b; - in.reset(); - - if (magic == GZIPInputStream.GZIP_MAGIC) { - options += " COMPRESSION GZIP"; - } - } finally { - - in.close(); - } - - Query query = getEntityManager().createNativeQuery( - "RUNSCRIPT FROM '" + file.getAbsolutePath() + "'" + options); - - query.executeUpdate(); - - // send event AFTER restore - getFiresSupport().firePostRestoreSchema(this); - } catch (Exception eee) { - throw new TopiaException( - "Unable to restore from file : " + eee.getMessage() + ". " + - "SQL is " + sql, eee); - } - } - - /** - * Only h2 supported for now - * - * @see TopiaContext#clear(boolean) - */ - @Override - public void clear(boolean dropDatabase) throws TopiaException { - try { - TopiaContextImpl root = (TopiaContextImpl) getRootContext(); - TopiaContextImpl tx = (TopiaContextImpl) root.beginTransaction(); - - String sql = "DROP ALL OBJECTS"; - if (dropDatabase) { - sql += " DELETE FILES"; - } - Query query = tx.getEntityManager().createNativeQuery(sql); - query.executeUpdate(); - tx.closeContext(); - root.finalize(); - } catch (Throwable eee) { - throw new TopiaException( - "Unable to perform clear operation : " + eee.getMessage(), eee); - } - } - - /** * Build the list of queries from the given parameter * <code>entityAndCondition</code>. * <p/> @@ -1487,7 +1309,7 @@ * @throws IllegalArgumentException if any pb with the given parameter * (mainly ClassCastException). */ - protected String[] buildQueries(Object... entityAndCondition) + protected List<String> buildQueries(Object... entityAndCondition) throws TopiaException, IllegalArgumentException { Class<?> entityClass; String condition; @@ -1495,7 +1317,6 @@ // si entityAndcondition est vide alors il faut le remplir // avec toutes les entités du mapping (class, null) if (entityAndCondition.length == 0) { -// Map<?,?> classMetadata = getEntityManagerFactory().getAllClassMetadata(); Set<EntityType<?>> classMetadata = getEntityManagerFactory().getMetamodel().getEntities(); entityAndCondition = new Object[classMetadata.size() * 2]; int i = 0; @@ -1518,7 +1339,7 @@ throw new IllegalArgumentException( "entityAndCondition must be a couple of (Class, String)"); } - String queries[] = new String[entityAndCondition.length / 2]; + List<String> queries = Lists.newArrayList(); for (int i = 0; i < entityAndCondition.length;) { try { entityClass = (Class<?>) entityAndCondition[i++]; @@ -1527,15 +1348,15 @@ if (condition != null && !condition.isEmpty()) { query += " where " + condition; } - queries[(i - 1) / 2] = query; + queries.add(query); } catch (ClassCastException e) { if (i % 2 == 0) { throw new IllegalArgumentException( - "Others arguement must be String not " + + "Others argument must be String not " + entityAndCondition[i - 1], e); } else { throw new IllegalArgumentException( - "Others arguement must be Class not " + + "Others argument must be Class not " + entityAndCondition[i - 1], e); } } @@ -1543,7 +1364,6 @@ return queries; } - protected void replicateOnDestinationContext( TopiaContextImplementor destinationContext, Object... entities) throws TopiaException { @@ -1567,5 +1387,19 @@ getSpecificUtil().receiveReplicatedEntity(this, entity); } -} //TopiaContextImpl + @Override + public void backup(File file, boolean compress) throws TopiaException { + new TopiaH2Util(this).backup(file, compress); + } + @Override + public void restore(File file) throws TopiaException { + new TopiaH2Util(this).restore(file); + } + + @Override + public void clear(boolean dropDatabase) throws TopiaException { + new TopiaH2Util(this).clear(dropDatabase); + } + +} //TopiaContextImpl Added: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaH2Util.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaH2Util.java (rev 0) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaH2Util.java 2012-05-23 13:00:47 UTC (rev 2498) @@ -0,0 +1,122 @@ +package org.nuiton.topia.framework; + +import org.nuiton.topia.TopiaException; + +import javax.persistence.Query; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.zip.GZIPInputStream; + +/** + * @author Arnaud Thimel <thimel@codelutin.com> + */ +public class TopiaH2Util { + + protected TopiaContextImpl context; + + public TopiaH2Util(TopiaContextImpl context) { + this.context = context; + } + + /** + * Backup database in gzip compressed file. + * + * <b>Note: </b> Only works for h2 database. + * + * @param file file to write backup + * @param compress if true then use gzip to compress file + * @see org.nuiton.topia.TopiaContext#backup(java.io.File,boolean) + */ + public void backup(File file, boolean compress) throws TopiaException { + context.checkClosed("backup"); + try { + String options = ""; + if (compress) { + options += " COMPRESSION GZIP"; + } + + Query query = context.getEntityManager().createNativeQuery( + "SCRIPT TO '" + file.getAbsolutePath() + "'" + options); + query.getResultList(); + + } catch (Exception eee) { + throw new TopiaException( + "Unable to backup to file : " + eee.getMessage(), eee); + } + } + + /** + * Read database from gzip compressed file + * <p/> + * Only work for h2 database + * + * @see org.nuiton.topia.TopiaContext#restore(File) + */ + public void restore(File file) throws TopiaException { + // send event + context.getFiresSupport().firePreRestoreSchema(context); + context.checkClosed("restore"); + + String sql = null; + String options = ""; + try { + // decompresse file in temporary file + InputStream in = new BufferedInputStream(new FileInputStream(file)); + try { + in.mark(2); + + // read header to see if is compressed file + int b = in.read(); + // redundant cast : int magic = ((int) in.read() << 8) | b; + int magic = in.read() << 8 | b; + in.reset(); + + if (magic == GZIPInputStream.GZIP_MAGIC) { + options += " COMPRESSION GZIP"; + } + } finally { + + in.close(); + } + + Query query = context.getEntityManager().createNativeQuery( + "RUNSCRIPT FROM '" + file.getAbsolutePath() + "'" + options); + + query.executeUpdate(); + + // send event AFTER restore + context.getFiresSupport().firePostRestoreSchema(context); + } catch (Exception eee) { + throw new TopiaException( + "Unable to restore from file : " + eee.getMessage() + ". " + + "SQL is " + sql, eee); + } + } + + /** + * Only h2 supported for now + * + * @see org.nuiton.topia.TopiaContext#clear(boolean) + */ + public void clear(boolean dropDatabase) throws TopiaException { + try { + TopiaContextImpl root = (TopiaContextImpl) context.getRootContext(); + TopiaContextImpl tx = (TopiaContextImpl) root.beginTransaction(); + + String sql = "DROP ALL OBJECTS"; + if (dropDatabase) { + sql += " DELETE FILES"; + } + Query query = tx.getEntityManager().createNativeQuery(sql); + query.executeUpdate(); + tx.closeContext(); + root.finalize(); + } catch (Throwable eee) { + throw new TopiaException( + "Unable to perform clear operation : " + eee.getMessage(), eee); + } + } + +} Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaSpecificUtil.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaSpecificUtil.java 2012-05-23 09:18:09 UTC (rev 2497) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaSpecificUtil.java 2012-05-23 13:00:47 UTC (rev 2498) @@ -1,9 +1,12 @@ package org.nuiton.topia.framework; +import org.dom4j.Element; import org.nuiton.topia.TopiaContext; import org.nuiton.topia.persistence.TopiaEntity; +import java.util.List; + /** * Provides all non-JPA standard methods (specific to an implementation) needed * by ToPIA @@ -59,4 +62,27 @@ */ void receiveReplicatedEntity(TopiaContextImplementor context, Object entity); + /** + * Export the given queries result to XML + * + * @param context the context on which entities are exported + * @param queries the list of queries that will be fetched for export + * @return a list of XML elements + * @deprecated nobody uses it and probably not supported by the + * implementation, will be removed in future version + */ + @Deprecated + List<Element> exportXML(TopiaContextImplementor context, List<String> queries); + + /** + * Imports from a list of XML elements + * + * @param context the context on which entities are exported + * @param elements the list of elements to import + * @deprecated nobody uses it and probably not supported by the + * implementation, will be removed in future version + */ + @Deprecated + void importXML(TopiaContextImplementor context, List<Element> elements); + } Modified: trunk/topia-persistence/src/main/resources/i18n/topia-persistence_en_GB.properties =================================================================== --- trunk/topia-persistence/src/main/resources/i18n/topia-persistence_en_GB.properties 2012-05-23 09:18:09 UTC (rev 2497) +++ trunk/topia-persistence/src/main/resources/i18n/topia-persistence_en_GB.properties 2012-05-23 13:00:47 UTC (rev 2498) @@ -1 +0,0 @@ -topia.persistence.supported.classes.for.context=List of supported persistence classes \: %1$s Modified: trunk/topia-persistence/src/main/resources/i18n/topia-persistence_es_ES.properties =================================================================== --- trunk/topia-persistence/src/main/resources/i18n/topia-persistence_es_ES.properties 2012-05-23 09:18:09 UTC (rev 2497) +++ trunk/topia-persistence/src/main/resources/i18n/topia-persistence_es_ES.properties 2012-05-23 13:00:47 UTC (rev 2498) @@ -1 +0,0 @@ -topia.persistence.supported.classes.for.context=List of supported persistence classes \: %1$s Modified: trunk/topia-persistence/src/main/resources/i18n/topia-persistence_fr_FR.properties =================================================================== --- trunk/topia-persistence/src/main/resources/i18n/topia-persistence_fr_FR.properties 2012-05-23 09:18:09 UTC (rev 2497) +++ trunk/topia-persistence/src/main/resources/i18n/topia-persistence_fr_FR.properties 2012-05-23 13:00:47 UTC (rev 2498) @@ -1 +0,0 @@ -topia.persistence.supported.classes.for.context=Classes supportées par ce TopiaContext \: %1$s Modified: trunk/topia-persistence-hibernate/src/main/java/org/nuiton/topia/persistence/TopiaHibernateSpecificUtil.java =================================================================== --- trunk/topia-persistence-hibernate/src/main/java/org/nuiton/topia/persistence/TopiaHibernateSpecificUtil.java 2012-05-23 09:18:09 UTC (rev 2497) +++ trunk/topia-persistence-hibernate/src/main/java/org/nuiton/topia/persistence/TopiaHibernateSpecificUtil.java 2012-05-23 13:00:47 UTC (rev 2498) @@ -2,6 +2,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.dom4j.Element; import org.hibernate.ReplicationMode; import org.hibernate.Session; import org.hibernate.cfg.AvailableSettings; @@ -24,6 +25,7 @@ import java.sql.DriverManager; import java.sql.SQLException; import java.util.Iterator; +import java.util.List; /** * Hibernate implementation of the {@link TopiaSpecificUtil}. @@ -137,4 +139,57 @@ throw new TopiaRuntimeException("Unable to receive replicated entity", te); } } + + @Override + public List<Element> exportXML(TopiaContextImplementor context, + List<String> queries) { + + throw new UnsupportedOperationException("Not supported anymore in Hibernate : https://hibernate.onjira.com/browse/HHH-6330"); +// try { +// List<Element> elements = Lists.newArrayList(); +// +// EntityManager entityManager = context.getEntityManager(); +// if (entityManager instanceof EntityManagerImpl) { +// Session sessionDom4j = ((EntityManagerImpl) entityManager).getSession(EntityMode.DOM4J); +// for (String query : queries) { +// +// List<?> list = sessionDom4j.createQuery(query).list(); +// for (Object o : list) { +// elements.add((Element) o); +// } +// +// } +// } +// +// return elements; +// } catch (TopiaException te) { +// throw new TopiaRuntimeException("Unable to export elements to XML", te); +// } + } + + @Override + public void importXML(TopiaContextImplementor context, List<Element> elements) { + + throw new UnsupportedOperationException("Not supported anymore in Hibernate : https://hibernate.onjira.com/browse/HHH-6330"); +// try { +// +// EntityManager entityManager = context.getEntityManager(); +// if (entityManager instanceof EntityManagerImpl) { +// Session sessionDom4j = ((EntityManagerImpl) entityManager).getSession(EntityMode.DOM4J); +// for (Element entity : elements) { +// try { +// sessionDom4j.replicate(entity, ReplicationMode.EXCEPTION); +// } catch (PersistenceException he) { +// log.warn(String.format( +// "Could not replicate entity '%s' pour following reason : %s", +// entity, he.getMessage()), he); +// } +// } +// // must commit data, otherwise : no effects... +// sessionDom4j.flush(); +// } +// } catch (TopiaException te) { +// throw new TopiaRuntimeException("Unable to export elements to XML", te); +// } + } } Modified: trunk/topia-persistence-tck/src/test/java/org/nuiton/topia/framework/TopiaContextImplTest.java =================================================================== --- trunk/topia-persistence-tck/src/test/java/org/nuiton/topia/framework/TopiaContextImplTest.java 2012-05-23 09:18:09 UTC (rev 2497) +++ trunk/topia-persistence-tck/src/test/java/org/nuiton/topia/framework/TopiaContextImplTest.java 2012-05-23 13:00:47 UTC (rev 2498) @@ -151,7 +151,7 @@ if (log.isInfoEnabled()) { log.info("test 2 : test serviceEnabled method"); } - boolean test2 = child.serviceEnabled("test"); + boolean test2 = child.isServiceEnabled("test"); Assert.assertTrue(test2); if (log.isInfoEnabled()) { @@ -176,8 +176,8 @@ log.info("test 6 : test serviceEnabled error with class FakeService"); } // FakeService doesn't contains property SERVICE_NAME used by - // serviceEnabled method - // Even it's properly loaded the serviceEnabled method will return false + // isServiceEnabled method + // Even it's properly loaded the isServiceEnabled method will return false properties.clear(); properties.setProperty("topia.service.fake", FakeService.class.getName());
participants (1)
-
athimel@users.nuiton.org