/* * Copyright 2001-2008 Geert Bevin (gbevin[remove] at uwyn dot com) * Licensed under the Apache License, Version 2.0 (the "License") * $Id: com_mysql_jdbc_Driver.java 3918 2008-04-14 17:35:35Z gbevin $ */ package com.uwyn.rife.cmf.dam.contentmanagers.databasedrivers; import com.uwyn.rife.cmf.Content; import com.uwyn.rife.cmf.ContentRepository; import com.uwyn.rife.cmf.dam.ContentStore; import com.uwyn.rife.cmf.dam.contentmanagers.DatabaseContentInfo; import com.uwyn.rife.cmf.dam.contentmanagers.exceptions.InstallContentErrorException; import com.uwyn.rife.cmf.dam.contentmanagers.exceptions.RemoveContentErrorException; import com.uwyn.rife.cmf.dam.contentmanagers.exceptions.UnknownContentRepositoryException; import com.uwyn.rife.cmf.dam.contentmanagers.exceptions.UnsupportedMimeTypeException; import com.uwyn.rife.cmf.dam.exceptions.ContentManagerException; import com.uwyn.rife.cmf.transform.ContentTransformer; import com.uwyn.rife.config.RifeConfig; import com.uwyn.rife.database.*; import com.uwyn.rife.database.exceptions.DatabaseException; import com.uwyn.rife.database.queries.CreateTable; import com.uwyn.rife.database.queries.Insert; import com.uwyn.rife.database.queries.Query; import com.uwyn.rife.datastructures.Pair; import com.uwyn.rife.tools.exceptions.InnerClassException; import java.sql.Statement; import java.sql.Types; import java.util.Map; public class com_mysql_jdbc_Driver extends generic { private static final Object sVersionMonitor = new Object(); public com_mysql_jdbc_Driver(Datasource datasource) { super(datasource); mCreateTableContentRepository = new CreateTable(getDatasource()) .table(RifeConfig.Cmf.getTableContentRepository()) .columns(ContentRepository.class) .column("repositoryId", int.class) .customAttribute("repositoryId", "AUTO_INCREMENT") .primaryKey("PK_"+RifeConfig.Cmf.getTableContentRepository(), "repositoryId"); mCreateTableContentInfo = new CreateTable(getDatasource()) .table(RifeConfig.Cmf.getTableContentInfo()) .columns(DatabaseContentInfo.class) .column("repositoryId", int.class, CreateTable.NOTNULL) .customAttribute("contentId", "AUTO_INCREMENT") .unique(("UQ_"+RifeConfig.Cmf.getTableContentInfo()).toUpperCase(), new String[] {"repositoryId", "path", "version"}) .foreignKey("FK_"+RifeConfig.Cmf.getTableContentInfo()+"_REPOSITORYID", RifeConfig.Cmf.getTableContentRepository(), "repositoryId", "repositoryId"); mDropContentInfoPathIndex = "DROP INDEX "+RifeConfig.Cmf.getTableContentInfo()+"_path ON "+RifeConfig.Cmf.getTableContentInfo(); mDropContentInfoPathNameIndex = "DROP INDEX "+RifeConfig.Cmf.getTableContentInfo()+"_pathname ON "+RifeConfig.Cmf.getTableContentInfo(); mStoreContentRepository = new Insert(getDatasource()) .into(RifeConfig.Cmf.getTableContentRepository()) .fieldsParameters(ContentRepository.class); mStoreContentInfo = new Insert(getDatasource()) .into(RifeConfig.Cmf.getTableContentInfo()) .fieldsParametersExcluded(DatabaseContentInfo.class, new String[] {"contentId"}) .fieldParameter("repositoryId") .fieldParameter("version") .fieldParameter("created"); } public boolean install() throws ContentManagerException { try { executeUpdate(mCreateTableContentRepository); executeUpdate(mCreateTableContentInfo); executeUpdate(mCreateTableContentAttribute); executeUpdate(mCreateTableContentProperty); createRepository(ContentRepository.DEFAULT); for (ContentStore store : mStores) { store.install(); } executeUpdate(mCreateContentInfoPathIndex); executeUpdate(mCreateContentInfoPathNameIndex); } catch (DatabaseException e) { throw new InstallContentErrorException(e); } return true; } public boolean remove() throws ContentManagerException { try { executeUpdate(mDropContentInfoPathNameIndex); executeUpdate(mDropContentInfoPathIndex); for (ContentStore store : mStores) { store.remove(); } executeUpdate(mDropTableContentProperties); executeUpdate(mDropTableContentAttribute); executeUpdate(mDropTableContentInfo); executeUpdate(mDropTableContentRepository); } catch (DatabaseException e) { throw new RemoveContentErrorException(e); } return true; } public boolean createRepository(final String name) throws ContentManagerException { if (null == name) throw new IllegalArgumentException("name can't be null"); if (0 == name.length()) throw new IllegalArgumentException("name can't be empty"); Boolean result = null; try { result = inTransaction(new DbTransactionUser() { public Boolean useTransaction() throws InnerClassException { // store the content return executeUpdate(mStoreContentRepository, new DbPreparedStatementHandler() { public void setParameters(DbPreparedStatement statement) { statement .setString("name", name); } }) > 0; } }); } catch (InnerClassException e) { throw (ContentManagerException)e.getCause(); } return result != null && result.booleanValue(); } public boolean storeContent(String location, final Content content, final ContentTransformer transformer) throws ContentManagerException { if (null == content) throw new IllegalArgumentException("content can't be null"); final Pair<String, String> split_location = splitLocation(location); final ContentStore store = mMimeMapping.get(content.getMimeType()); if (null == store) { throw new UnsupportedMimeTypeException(content.getMimeType()); } // ensure that all version number increases are handled in a serial fashion // relying on database locks is error prone and does offer any advantages synchronized (sVersionMonitor) { // get repository id final int repository_id = executeGetFirstInt(mGetContentRepositoryId, new DbPreparedStatementHandler() { public void setParameters(DbPreparedStatement statement) { statement .setString("repository", split_location.getFirst()); } }); // verify the existance of the repository if (-1 == repository_id) { throw new UnknownContentRepositoryException(split_location.getFirst()); } // get version final int version = executeGetFirstInt(mGetVersion, new DbPreparedStatementHandler() { public void setParameters(DbPreparedStatement statement) { statement .setInt("repositoryId", repository_id) .setString("path", split_location.getSecond()); } }); // store the content final int[] ids_array = new int[1]; if (executeUpdate(mStoreContentInfo, new DbPreparedStatementHandler() { public DbPreparedStatement getPreparedStatement(Query query, DbConnection connection) { return connection.getPreparedStatement(query, Statement.RETURN_GENERATED_KEYS); } public int performUpdate(DbPreparedStatement statement) { statement .setString("path", split_location.getSecond()) .setString("mimeType", content.getMimeType().toString()) .setBoolean("fragment", content.isFragment()) .setDate("created", new java.sql.Date(System.currentTimeMillis())) .setInt("repositoryId", repository_id) .setInt("version", version); if (content.hasName()) { statement .setString("name", content.getName()); } else { statement .setNull("name", Types.VARCHAR); } int query_result = statement.executeUpdate(); ids_array[0] = statement.getFirstGeneratedIntKey(); return query_result; } }) > 0) { // store the attributes if there are some if (content.hasAttributes()) { for (Map.Entry<String, String> attribute : content.getAttributes().entrySet()) { final String name = attribute.getKey(); final String value = attribute.getValue(); executeUpdate(mStoreContentAttribute, new DbPreparedStatementHandler() { public void setParameters(DbPreparedStatement statement) { statement .setInt("contentId", ids_array[0]) .setString("name", name) .setString(getValueColumnName(), value); } }); } } // put the actual content data in the content store if (!store.storeContentData(ids_array[0], content, transformer)) { return false; } // store the content data properties if there are some if (content.hasProperties()) { for (Map.Entry<String, String> property : content.getProperties().entrySet()) { final String name = property.getKey(); final String value = property.getValue(); executeUpdate(mStoreContentProperty, new DbPreparedStatementHandler() { public void setParameters(DbPreparedStatement statement) { statement .setInt("contentId", ids_array[0]) .setString("name", name) .setString(getValueColumnName(), value); } }); } } return true; } return false; } } }