/**
* Speedo: an implementation of JDO compliant personality on top of JORM generic
* I/O sub-system.
* Copyright (C) 2001-2005 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
*
* Contact: speedo@objectweb.org
*
*/
package org.objectweb.speedo.ant;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.UpToDate;
import org.objectweb.jorm.mapper.rdb.lib.PMapperRdb;
import org.objectweb.jorm.util.lib.AntScriptGenerator;
import org.objectweb.speedo.api.SpeedoRuntimeException;
import org.objectweb.speedo.mapper.lib.Object2StringSerializer;
import org.objectweb.speedo.metadata.SpeedoIndex;
import org.objectweb.speedo.mim.api.HomeItf;
import org.objectweb.speedo.sequence.api.SpeedoSequenceItf;
import org.objectweb.speedo.sequence.lib.SpeedoSequence;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;
/**
* This ant task extends the AntScriptGenerator ant task provided by JORM.
* It enables to generate sql statements related to sequences and indexes.
*
* @author Y.Bersihand
*/
public class AntSpeedoScriptGenerator extends AntScriptGenerator {
//the list of SpeedoSequence(s)
protected List sequences = new ArrayList(1);
//the list of SpeedoIndexe(s)
protected List indexes = new ArrayList(1);
public static void main(String[] args) {
new AntScriptGenerator().execute(args);
}
public void execute() {
log("[INFO] Generating script for database creation...", Project.MSG_INFO);
long timeSpent = System.currentTimeMillis();
//execute the jorm ant task
super.execute();
UpToDate u = new UpToDate();
u.setProject(getProject());
u.addSrcfiles(fileset);
u.setTargetFile(destFile);
if (u.eval()) {
return;
}
//then the speedo part
//1- sequence (if any)
try {
//get the class loader
ClassLoader classLoader = getClass().getClassLoader();
//list of jmi files already deserialized
List fileNames = new ArrayList(1);
//for each class to process selected by the super.execute() method
for (int i=0; i<classesToProcess.size(); i++) {
try {
//get the class name
String classMapping = (String)classesToProcess.get(i);
//get the class properties
Properties classProperties = getClassProperties(classMapping, classLoader);
//get the file to deserialize
String fileName = classProperties.getProperty(Object2StringSerializer.DESC_FILE_NAME_PROP);
//if the file has not already been processed
if (!fileNames.contains(fileName)) {
//add it to the list
fileNames.add(fileName);
//and get the sequences and indexes defined
addSequencesAndIndexes(fileName, classProperties, classLoader);
}
} catch(Exception pe) {
pe.printStackTrace();
log("[ERROR] Cannot generate sequence statements : " + pe.getMessage(),
Project.MSG_ERR);
}
}
//get the index sql statements
writeIndexesStatements();
//then the sequence sql statements
writeSequencesStatements();
//then close the file writer
if (msm != null) {
msm.getFileWriter().close();
}
log("[INFO] File generated: " + destFile.getAbsolutePath(), Project.MSG_INFO);
} catch (Exception e) {
e.printStackTrace();
}
timeSpent = System.currentTimeMillis() - timeSpent;
log("[INFO] All done in " + duration2str(timeSpent), Project.MSG_INFO);
}
/**
* Write the sequences sql statements to add to the script.
*/
private void writeSequencesStatements() throws IOException {
if (!sequences.isEmpty()) {
PMapperRdb mapper = (PMapperRdb) msm.getPMapper();
msm.getFileWriter().write("----------- SEQUENCES ---------\n");
for (Iterator it = sequences.iterator(); it.hasNext();) {
SpeedoSequence s = (SpeedoSequence) it.next();
log("[DEBUG] Sequence " + s.datastoreName, Project.MSG_DEBUG);
//just write the sql sequences
if (s.datastoreName != null && s.datastoreName != "") {
if (isGenerateDrop()) {
msm.getFileWriter().write(
mapper.getRdbAdapter().getDropSequence(s.datastoreName) + "\n");
}
if (isGenerateCreate()) {
msm.getFileWriter().write(
mapper.getRdbAdapter().getCreateSequence(s.datastoreName, s.start, s.increment, s.cache)
+ "\n");
}
}
}
}
}
/**
* Write the indexes sql statements to add to the script.
*/
private void writeIndexesStatements() throws IOException {
if (!indexes.isEmpty()) {
PMapperRdb mapper = (PMapperRdb) msm.getPMapper();
msm.getFileWriter().write("----------- INDEXES ---------\n");
for (Iterator it = indexes.iterator(); it.hasNext();) {
SpeedoIndex si = (SpeedoIndex) it.next();
log("[DEBUG] SpeedoIndex " + si.name, Project.MSG_DEBUG);
if (isGenerateDrop()) {
msm.getFileWriter().write(
mapper.getRdbAdapter().getDropIndex(si.name, si.table) + "\n");
}
if (isGenerateCreate()) {
if (si.columnNames != null && si.columnNames.size() != 0) {
msm.getFileWriter().write(
mapper.getRdbAdapter().getCreateIndex(si.name, si.table, si.columnNames, si.unique)
+ "\n");
} else {
log("[INFO] Index " + si.name + " has not been processed.", Project.MSG_INFO);
}
}
}
}
}
/**
* Get the class properties.
*/
private Properties getClassProperties(String className, ClassLoader classLoader) {
try {
//load the PClassMapping
java.lang.Class currentClass = classLoader.loadClass(className);
//create a new instance
Object o = currentClass.newInstance();
return ((HomeItf)o).getClassProperties();
} catch (ClassNotFoundException e) {
log("[ERROR] Impossible to load the persistent class '"
+ className + "' from the classpath: " + e.getMessage(), Project.MSG_ERR);
} catch (IllegalAccessException iae) {
log("[ERROR] Impossible to have access to a new instance of the class '"
+ className + ": " + iae.getMessage(), Project.MSG_ERR);
} catch (InstantiationException ie) {
log("[ERROR] Impossible to get a new instance of the class '"
+ className + ": " + ie.getMessage(), Project.MSG_ERR);
}
return null;
}
/**
* Complete the list of sequences and indexes deserialized from the fn file.
*/
private void addSequencesAndIndexes(String fileName, Properties classProperties, ClassLoader classLoader) {
// deserialize the JMI from the file
Set mos = null;
try {
mos = (Set) Object2StringSerializer.deserialize(fileName, classLoader, null);
} catch (Exception e) {
throw new SpeedoRuntimeException("Impossible to load the jorm meta " +
"information from the file " + fileName + "' (You must use the same Speedo version for the"
+ " enhancement and for the runtime): ", e);
}
//select only the sequences and indexes and deserialize them
for (Iterator it = mos.iterator(); it.hasNext();) {
Object o = it.next();
if (o instanceof SpeedoSequenceItf) {
// add the sequence to the list of sequences
sequences.add(o);
} else if (o instanceof SpeedoIndex) {
// add the index to the list of indexes
indexes.add(o);
}
}
}
//---------------- UTIL METHOD ---------------------------//
public static String duration2str(final long t) {
long time = t;
StringBuffer sb = new StringBuffer();
sb.insert(0, "ms");
sb.insert(0, time % 1000);
time = time / 1000;
if (time > 0) {
sb.insert(0, "s ");
sb.insert(0, time % 60);
time = time / 60;
if (time > 0) {
sb.insert(0, "m ");
sb.insert(0, time % 60);
}
}
return sb.toString();
}
}