1 package org.apache.torque.task;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache Turbine" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache Turbine", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import java.io.File;
58
59 import java.util.ArrayList;
60 import java.util.Hashtable;
61 import java.util.Iterator;
62 import java.util.List;
63
64 import org.apache.commons.lang.StringUtils;
65
66 import org.apache.tools.ant.BuildException;
67 import org.apache.tools.ant.DirectoryScanner;
68 import org.apache.tools.ant.types.FileSet;
69
70 import org.apache.torque.engine.EngineException;
71 import org.apache.torque.engine.database.model.AppData;
72 import org.apache.torque.engine.database.model.Database;
73 import org.apache.torque.engine.database.transform.XmlToAppData;
74
75 import org.apache.velocity.VelocityContext;
76 import org.apache.velocity.context.Context;
77 import org.apache.velocity.texen.ant.TexenTask;
78
79 /***
80 * A base torque task that uses either a single XML schema
81 * representing a data model, or a <fileset> of XML schemas.
82 * We are making the assumption that an XML schema representing
83 * a data model contains tables for a <strong>single</strong>
84 * database.
85 *
86 * @author <a href="mailto:jvanzyl@zenplex.com">Jason van Zyl</a>
87 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
88 */
89 public class TorqueDataModelTask extends TexenTask
90 {
91 /***
92 * XML that describes the database model, this is transformed
93 * into the application model object.
94 */
95 protected String xmlFile;
96
97 /***
98 * Fileset of XML schemas which represent our data models.
99 */
100 protected List filesets = new ArrayList();
101
102 /***
103 * Data models that we collect. One from each XML schema file.
104 */
105 protected List dataModels = new ArrayList();
106
107 /***
108 * Velocity context which exposes our objects
109 * in the templates.
110 */
111 protected Context context;
112
113 /***
114 * Map of data model name to database name.
115 * Should probably stick to the convention
116 * of them being the same but I know right now
117 * in a lot of cases they won't be.
118 */
119 protected Hashtable dataModelDbMap;
120
121 /***
122 * Hashtable containing the names of all the databases
123 * in our collection of schemas.
124 */
125 protected Hashtable databaseNames;
126
127 //!! This is probably a crappy idea having the sql file -> db map
128 // here. I can't remember why I put it here at the moment ...
129 // maybe I was going to map something else. It can probably
130 // move into the SQL task.
131
132 /***
133 * Name of the properties file that maps an SQL file
134 * to a particular database.
135 */
136 protected String sqldbmap;
137
138 /***
139 * The path to properties file containing db idiosyncrasies is
140 * constructed by appending the "getTargetDatabase()/db.props
141 * to this path.
142 */
143 private String basePathToDbProps;
144
145 /***
146 * The target database(s) we are generating SQL
147 * for. Right now we can only deal with a single
148 * target, but we will support multiple targets
149 * soon.
150 */
151 private String targetDatabase;
152
153 /***
154 * Target Java package to place the generated files in.
155 */
156 private String targetPackage;
157
158
159 /***
160 * Set the sqldbmap.
161 *
162 * @param sqldbmap th db map
163 */
164 public void setSqlDbMap(String sqldbmap)
165 {
166 //!! Make all these references files not strings.
167 this.sqldbmap = project.resolveFile(sqldbmap).toString();
168 }
169
170 /***
171 * Get the sqldbmap.
172 *
173 * @return String sqldbmap.
174 */
175 public String getSqlDbMap()
176 {
177 return sqldbmap;
178 }
179
180 /***
181 * Return the data models that have been
182 * processed.
183 *
184 * @return List data models
185 */
186 public List getDataModels()
187 {
188 return dataModels;
189 }
190
191 /***
192 * Return the data model to database name map.
193 *
194 * @return Hashtable data model name to database name map.
195 */
196 public Hashtable getDataModelDbMap()
197 {
198 return dataModelDbMap;
199 }
200
201 /***
202 * Get the xml schema describing the application model.
203 *
204 * @return String xml schema file.
205 */
206 public String getXmlFile()
207 {
208 return xmlFile;
209 }
210
211 /***
212 * Set the xml schema describing the application model.
213 *
214 * @param xmlFile The new XmlFile value
215 */
216 public void setXmlFile(String xmlFile)
217 {
218 this.xmlFile = project.resolveFile(xmlFile).toString();
219 }
220
221 /***
222 * Adds a set of xml schema files (nested fileset attribute).
223 *
224 * @param set a Set of xml schema files
225 */
226 public void addFileset(FileSet set)
227 {
228 filesets.add(set);
229 }
230
231 /***
232 * Get the current target database.
233 *
234 * @return String target database(s)
235 */
236 public String getTargetDatabase()
237 {
238 return targetDatabase;
239 }
240
241 /***
242 * Set the current target database. (e.g. mysql, oracle, ..)
243 *
244 * @param v target database(s)
245 */
246 public void setTargetDatabase(String v)
247 {
248 targetDatabase = v;
249 }
250
251 /***
252 * Get the current target package.
253 *
254 * @return return target java package.
255 */
256 public String getTargetPackage()
257 {
258 return targetPackage;
259 }
260
261 /***
262 * Set the current target package. This is where generated java classes will
263 * live.
264 *
265 * @param v target java package.
266 */
267 public void setTargetPackage(String v)
268 {
269 targetPackage = v;
270 }
271
272 /***
273 * The path to properties file containing db idiosyncrasies is
274 * constructed by appending the "getTargetDatabase()/db.props to this path.
275 *
276 * @return basepath to db.props
277 */
278 public String getBasePathToDbProps()
279 {
280 return basePathToDbProps;
281 }
282
283 /***
284 * The path to properties file containing db idiosyncrasies is
285 * constructed by appending the "getTargetDatabase()/db.props
286 * to this path.
287 *
288 * @param v basepath to db.props
289 */
290 public void setBasePathToDbProps(String v)
291 {
292 this.basePathToDbProps = v;
293 }
294
295 /***
296 * Set up the initial context for generating the SQL from the XML schema.
297 *
298 * @return the context
299 * @throws Exception
300 */
301 public Context initControlContext() throws Exception
302 {
303 XmlToAppData xmlParser;
304
305 if (xmlFile == null && filesets.isEmpty())
306 {
307 throw new BuildException("You must specify an XML schema or "
308 + "fileset of XML schemas!");
309 }
310
311 try
312 {
313 if (xmlFile != null)
314 {
315 // Transform the XML database schema into
316 // data model object.
317 xmlParser = new XmlToAppData(getTargetDatabase(),
318 getTargetPackage(), getBasePathToDbProps());
319 AppData ad = xmlParser.parseFile(xmlFile);
320 ad.setName(grokName(xmlFile));
321 dataModels.add(ad);
322 }
323 else
324 {
325 // Deal with the filesets.
326 for (int i = 0; i < filesets.size(); i++)
327 {
328 FileSet fs = (FileSet) filesets.get(i);
329 DirectoryScanner ds = fs.getDirectoryScanner(project);
330 File srcDir = fs.getDir(project);
331
332 String[] dataModelFiles = ds.getIncludedFiles();
333
334 // Make a transaction for each file
335 for (int j = 0; j < dataModelFiles.length; j++)
336 {
337 File f = new File(srcDir, dataModelFiles[j]);
338 xmlParser = new XmlToAppData(getTargetDatabase(),
339 getTargetPackage(),
340 getBasePathToDbProps());
341 AppData ad = xmlParser.parseFile(f.toString());
342 ad.setName(grokName(f.toString()));
343 dataModels.add(ad);
344 }
345 }
346 }
347
348 Iterator i = dataModels.iterator();
349 databaseNames = new Hashtable();
350 dataModelDbMap = new Hashtable();
351
352 // Different datamodels may state the same database
353 // names, we just want the unique names of databases.
354 while (i.hasNext())
355 {
356 AppData ad = (AppData) i.next();
357 Database database = ad.getDatabase();
358 databaseNames.put(database.getName(), database.getName());
359 dataModelDbMap.put(ad.getName(), database.getName());
360 }
361 }
362 catch (EngineException ee)
363 {
364 throw new BuildException(ee);
365 }
366
367 context = new VelocityContext();
368
369 // Place our set of data models into the context along
370 // with the names of the databases as a convenience for now.
371 context.put("dataModels", dataModels);
372 context.put("databaseNames", databaseNames);
373 context.put("targetDatabase", targetDatabase);
374 context.put("targetPackage", targetPackage);
375
376 return context;
377 }
378
379 /***
380 * Gets a name to use for the application's data model.
381 *
382 * @param xmlFile The path to the XML file housing the data model.
383 * @return The name to use for the <code>AppData</code>.
384 */
385 private String grokName(String xmlFile)
386 {
387 // This can't be set from the file name as it is an unreliable
388 // method of naming the descriptor. Not everyone uses the same
389 // method as I do in the TDK. jvz.
390
391 String name = "data-model";
392 int i = xmlFile.lastIndexOf(System.getProperty("file.separator"));
393 if (i != -1)
394 {
395 // Creep forward to the start of the file name.
396 i++;
397
398 int j = xmlFile.lastIndexOf('.');
399 if (i < j)
400 {
401 name = xmlFile.substring(i, j);
402 }
403 else
404 {
405 // Weirdo
406 name = xmlFile.substring(i);
407 }
408 }
409 return name;
410 }
411
412 /***
413 * Override Texen's context properties to map the
414 * torque.xxx properties (including defaults set by the
415 * org/apache/torque/defaults.properties) to just xxx.
416 *
417 * <p>
418 * Also, move xxx.yyy properties to xxxYyy as Velocity
419 * doesn't like the xxx.yyy syntax.
420 * </p>
421 *
422 * @param file the file to read the properties from
423 */
424 public void setContextProperties(String file)
425 {
426 super.setContextProperties(file);
427
428 // Map the torque.xxx elements from the env to the contextProperties
429 Hashtable env = super.getProject().getProperties();
430 for (Iterator i = env.keySet().iterator(); i.hasNext();)
431 {
432 String key = (String) i.next();
433 if (key.startsWith("torque."))
434 {
435 String newKey = key.substring("torque.".length());
436 int j = newKey.indexOf(".");
437 while (j != -1)
438 {
439 newKey =
440 newKey.substring(0, j)
441 + StringUtils.capitalise(newKey.substring(j + 1));
442 j = newKey.indexOf(".");
443 }
444
445 contextProperties.setProperty(newKey, env.get(key));
446 }
447 }
448 }
449 }
This page was automatically generated by Maven