001: /**
002: * Speedo: an implementation of JDO compliant personality on top of JORM generic
003: * I/O sub-system.
004: * Copyright (C) 2001-2004 France Telecom R&D
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: *
021: *
022: * Contact: speedo@objectweb.org
023: *
024: * Authors: S.Chassande-Barrioz.
025: *
026: */package org.objectweb.speedo.generation.generator;
027:
028: import org.apache.velocity.app.Velocity;
029: import org.apache.velocity.app.VelocityEngine;
030: import org.objectweb.speedo.api.SpeedoException;
031: import org.objectweb.speedo.api.SpeedoProperties;
032: import org.objectweb.speedo.generation.generator.fields.FieldsGenerator;
033: import org.objectweb.speedo.generation.generator.home.HomeGenerator;
034: import org.objectweb.speedo.generation.generator.lib.AbstractVelocityGenerator;
035: import org.objectweb.speedo.generation.generator.objectid.ObjectIdGenerator;
036: import org.objectweb.speedo.generation.lib.AbstractGeneratorComponent;
037: import org.objectweb.speedo.generation.lib.NamingRules;
038: import org.objectweb.speedo.lib.Personality;
039: import org.objectweb.speedo.metadata.SpeedoClass;
040: import org.objectweb.speedo.metadata.SpeedoPackage;
041: import org.objectweb.speedo.metadata.SpeedoXMLDescriptor;
042: import org.objectweb.util.monolog.api.BasicLevel;
043: import org.objectweb.util.monolog.api.Logger;
044: import org.objectweb.util.monolog.wrapper.velocity.VelocityLogger;
045:
046: import java.io.File;
047: import java.util.Collection;
048: import java.util.Iterator;
049:
050: /**
051: * This class generates files "po", "manager" and "fields" for persistence capable classes.
052: * @author S. Chassande-Barrioz
053: */
054: public abstract class AbstractGenerator extends
055: AbstractGeneratorComponent {
056: public final static String LOGGER_NAME = SpeedoProperties.LOGGER_NAME
057: + ".generation.generator";
058: private static final String CLASS_RESOURCE_LOADER_DESCRIPTION_PROP = "class.resource.loader.description";
059: private static final String CLASS_RESOURCE_LOADER_DESCRIPTION_VALUE = "Velocity Classpath Resource Loader";
060: private static final String CLASS_RESOURCE_LOADER_CLASS_PROP = "class.resource.loader.class";
061: private static final String CLASS_RESOURCE_LOADER_CLASS_VALUE = "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader";
062: int generatedFiles;
063:
064: /**
065: * Provides the list of generators to be used in the code generation for
066: * a particular persistent class.
067: *
068: * @return The list as an array of generators.
069: */
070: protected abstract AbstractVelocityGenerator[] getGenerators();
071:
072: public AbstractGenerator(Personality p) {
073: super (p);
074: }
075:
076: // IMPLEMENTATION OF THE GeneratorComponent INTERFACE //
077: //----------------------------------------------------//
078:
079: public boolean init() {
080: logger = scp.loggerFactory.getLogger(LOGGER_NAME);
081: generatedFiles = 0;
082: return !scp.getXmldescriptor().isEmpty();
083: }
084:
085: public String getTitle() {
086: return "Generating Speedo files...";
087: }
088:
089: public String getSummary() {
090: return generatedFiles + " generates files";
091: }
092:
093: /**
094: * Generation all files <className>, and <className>Fields.
095: * If a previous task on a class has failed, the methods doesn't create
096: * files for this class.
097: *
098: * @exception SpeedoException if there is a problem during writing
099: * the new files and the boolean failsonerror is set on true.
100: */
101: public void process() throws SpeedoException {
102: if (scp.getXmldescriptor().isEmpty())
103: return;
104: //separator for file names
105: char fs = File.separatorChar;
106: //for each package
107:
108: VelocityLogger vl = new VelocityLogger(logger);
109: VelocityEngine ve = new VelocityEngine();
110: ve.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM, vl);
111:
112: AbstractVelocityGenerator[] vgs = getGenerators();
113:
114: Logger[] loggers = new Logger[vgs.length];
115: String strlibs = "";
116: boolean first = true;
117: for (int i = 0; i < vgs.length; i++) {
118: vgs[i].setSpeedoCompilerParameter(scp);
119: vgs[i].init();
120: Collection col = vgs[i].getExternalsTemplate();
121: if (col != null && col.size() > 0) {
122: for (Iterator it = col.iterator(); it.hasNext();) {
123: strlibs += (first ? "" : ",") + it.next();
124: first = false;
125: }
126: }
127: vgs[i].setVelocityEngine(ve);
128: loggers[i] = scp.loggerFactory.getLogger(vgs[i].getLogger()
129: .getName()
130: + ".velocity");
131: }
132: ve.setProperty(Velocity.RESOURCE_LOADER, "class");
133: ve.setProperty(CLASS_RESOURCE_LOADER_DESCRIPTION_PROP,
134: CLASS_RESOURCE_LOADER_DESCRIPTION_VALUE);
135: ve.setProperty(CLASS_RESOURCE_LOADER_CLASS_PROP,
136: CLASS_RESOURCE_LOADER_CLASS_VALUE);
137: ve.setProperty(Velocity.VM_LIBRARY, strlibs);
138: try {
139: ve.init();
140: } catch (Exception e) {
141: throw new SpeedoException(
142: "Impossible to initialize the VelocityEngine", e);
143: }
144:
145: for (Iterator itDesc = scp.getXmldescriptor().values()
146: .iterator(); itDesc.hasNext();) {
147: SpeedoXMLDescriptor desc = (SpeedoXMLDescriptor) itDesc
148: .next();
149: for (Iterator itPack = desc.packages.values().iterator(); itPack
150: .hasNext();) {
151: SpeedoPackage sp = (SpeedoPackage) itPack.next();
152: //base directory for new files
153: String baseDir = scp.output + fs
154: + sp.name.replace('.', fs) + fs;
155: for (Iterator itclass = sp.classes.values().iterator(); itclass
156: .hasNext();) {
157: SpeedoClass sClass = (SpeedoClass) itclass.next();
158:
159: //asm has not failed on this class
160: if (sClass.enhancementFailed())
161: continue;
162: String[] filenames = {
163: baseDir
164: + NamingRules
165: .fieldsName(sClass.name)
166: + ".java",
167: baseDir + NamingRules.homeName(sClass.name)
168: + ".class",
169: baseDir + sClass.identity.objectidClass
170: + ".java" };
171: try {
172: //fields
173: vl.setLog(loggers[0]);
174: vgs[0].generate(sClass, filenames[0]);
175: generatedFiles++;
176: //home
177: vl.setLog(loggers[1]);
178: vgs[1].generate(sClass, filenames[1]);
179: generatedFiles++;
180: //oid
181: if (sClass.identity.oidClassAutoCalculated) {
182: vl.setLog(loggers[2]);
183: vgs[2].generate(sClass, filenames[2]);
184: generatedFiles++;
185: logger
186: .log(
187: BasicLevel.WARN,
188: "No object id class defined for the class '"
189: + sClass
190: .getFQName()
191: + "': use the generated class: '"
192: + NamingRules
193: .generatedObjectIdName(sClass
194: .getFQName())
195: + "'");
196: }
197: logger.log(BasicLevel.INFO,
198: "Classes generated for "
199: + sClass.getFQName());
200: } catch (SpeedoException e) {
201: logger.log(BasicLevel.ERROR,
202: "ERROR during the speedo generation of files "
203: + filenames[0] + ", "
204: + filenames[1] + " or "
205: + filenames[2], e);
206: throw e;
207: }
208: }
209:
210: }
211: }
212: }
213: }
|