Source code: org/objectstyle/woproject/ant/ProjectFormat.java
1 /* ====================================================================
2 *
3 * The ObjectStyle Group Software License, Version 1.0
4 *
5 * Copyright (c) 2002 The ObjectStyle Group
6 * and individual authors of the software. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. The end-user documentation included with the redistribution, if
21 * any, must include the following acknowlegement:
22 * "This product includes software developed by the
23 * ObjectStyle Group (http://objectstyle.org/)."
24 * Alternately, this acknowlegement may appear in the software itself,
25 * if and wherever such third-party acknowlegements normally appear.
26 *
27 * 4. The names "ObjectStyle Group" and "Cayenne"
28 * must not be used to endorse or promote products derived
29 * from this software without prior written permission. For written
30 * permission, please contact andrus@objectstyle.org.
31 *
32 * 5. Products derived from this software may not be called "ObjectStyle"
33 * nor may "ObjectStyle" appear in their names without prior written
34 * permission of the ObjectStyle Group.
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This software consists of voluntary contributions made by many
51 * individuals on behalf of the ObjectStyle Group. For more
52 * information on the ObjectStyle Group, please see
53 * <http://objectstyle.org/>.
54 *
55 */
56 package org.objectstyle.woproject.ant;
57
58 import java.io.BufferedReader;
59 import java.io.BufferedWriter;
60 import java.io.File;
61 import java.io.FileOutputStream;
62 import java.io.FileWriter;
63 import java.io.IOException;
64 import java.io.InputStream;
65 import java.io.InputStreamReader;
66 import java.util.Iterator;
67
68 import org.apache.tools.ant.BuildException;
69 import org.apache.tools.ant.types.FilterSet;
70 import org.apache.tools.ant.types.FilterSetCollection;
71
72 /**
73 * Abstract helper class that defines the algorithm for
74 * autogeneration of standard project files needed for deployment
75 * of the applications and frameworks. In a way it "formats"
76 * deployed project.
77 *
78 * @author Andrei Adamchik
79 */
80 public abstract class ProjectFormat {
81 protected static final String endLine = System.getProperty("line.separator");
82
83 protected WOTask task;
84
85 /**
86 * Creates new TemplateFilter and initializes it with the name
87 * of the project being built.
88 */
89 public ProjectFormat(WOTask task) {
90 this.task = task;
91 }
92
93 /**
94 * Returns a name of WebObjects project being built.
95 */
96 public String getName() {
97 return task.getName();
98 }
99
100 /**
101 * Returns a name of the jar WebObjects project being built with ".jar" appended.
102 */
103 public String getJarName() {
104 return task.getJarName() + ".jar";
105 }
106
107 /**
108 * Creates all needed files based on WOProject templates.
109 * This is a main worker method.
110 */
111 public void processTemplates() throws BuildException {
112 Iterator it = fileIterator();
113
114 try {
115 while (it.hasNext()) {
116 String targetName = (String) it.next();
117 String templName = templateForTarget(targetName);
118 FilterSetCollection filters = filtersForTarget(targetName);
119
120 InputStream template =
121 this.getClass().getClassLoader().getResourceAsStream(templName);
122 File target = new File(targetName);
123 copyFile(template, target, filters);
124 }
125 } catch (IOException ioex) {
126 throw new BuildException("Error doing project formatting.", ioex);
127 }
128 }
129
130 /**
131 * Returns an iterator over String objects that
132 * specify paths of the files to be created during
133 * the build process.
134 */
135 public abstract Iterator fileIterator();
136
137 /**
138 * Returns a path to the template that should be used to
139 * build a target file.
140 */
141 public abstract String templateForTarget(String targetName) throws BuildException;
142
143 /**
144 * Returns a FilterSetCollection that should be applied when
145 * generating a target file.
146 */
147 public abstract FilterSetCollection filtersForTarget(String targetName)
148 throws BuildException;
149
150 /**
151 * Convienence method to copy a file from a source to a
152 * destination specifying if token filtering must be used.
153 *
154 * <p><i>This method is copied from Ant FileUtils with some changes
155 * and simplifications. FileUtils can't be used directly, since its
156 * API doesn't allow InputStreams for the source file.</i></p>
157 *
158 * @throws IOException
159 */
160 public void copyFile(InputStream src, File destFile, FilterSetCollection filters)
161 throws IOException {
162
163 if (destFile.exists() && destFile.isFile()) {
164 destFile.delete();
165 }
166
167 // ensure that parent dir of dest file exists!
168 // not using getParentFile method to stay 1.1 compat
169 File parent = new File(destFile.getParent());
170 if (!parent.exists()) {
171 parent.mkdirs();
172 }
173
174 if (filters != null && filters.hasFilters()) {
175 BufferedReader in = new BufferedReader(new InputStreamReader(src));
176 BufferedWriter out = new BufferedWriter(new FileWriter(destFile));
177
178 int length;
179 String newline = null;
180 String line = in.readLine();
181 while (line != null) {
182 if (line.length() == 0) {
183 out.newLine();
184 } else {
185 newline = filters.replaceTokens(line);
186 out.write(newline);
187 out.newLine();
188 }
189 line = in.readLine();
190 }
191
192 out.close();
193 in.close();
194 } else {
195 FileOutputStream out = new FileOutputStream(destFile);
196
197 byte[] buffer = new byte[8 * 1024];
198 int count = 0;
199 do {
200 out.write(buffer, 0, count);
201 count = src.read(buffer, 0, buffer.length);
202 } while (count != -1);
203
204 src.close();
205 out.close();
206 }
207 }
208
209 /**
210 * Returns a string that can be used in Info.plist
211 * file to indicate JARs required by the project.
212 */
213 private String libString(Iterator extLibs) {
214 StringBuffer buf = new StringBuffer();
215
216 buf.append("<array>");
217 if (task.hasClasses()) {
218 buf.append(endLine).append("\t\t<string>").append(getJarName()).append(
219 "</string>");
220 }
221
222 if (extLibs != null) {
223 while (extLibs.hasNext()) {
224 String libFile = (String) extLibs.next();
225 buf.append(endLine).append("\t\t<string>");
226 buf.append(libFile);
227 buf.append("</string>");
228 }
229 }
230 buf.append(endLine).append("\t</array>");
231 return buf.toString();
232 }
233 /**
234 * Returns a string that can be used in Info.plist
235 * file to indicate the principal class for the framework or app.
236 */
237 private String principalClassString() {
238 StringBuffer buf = new StringBuffer();
239 if (task.getPrincipalClass() != null && task.getPrincipalClass().length() > 0) {
240 buf.append("<key>NSPrincipalClass</key>").append(endLine);
241 buf.append("\t<string>").append(task.getPrincipalClass()).append(
242 "</string>").append(
243 endLine);
244 }
245 return buf.toString();
246 }
247 /**
248 * Returns a FilterSet that can be used to build Info.plist file.
249 */
250 public FilterSetCollection infoFilter(Iterator extLibs) {
251 FilterSet filter = new FilterSet();
252
253 filter.addFilter("PRINCIPAL_CLASS", principalClassString());
254 filter.addFilter("NAME", getName());
255 filter.addFilter("JAR_NAME", getJarName());
256 filter.addFilter("JAR_ARRAY", libString(extLibs));
257
258 return new FilterSetCollection(filter);
259 }
260
261 public void log(String msg) {
262 task.log(msg);
263 }
264
265 public void log(String msg, int msgLevel) {
266 task.log(msg, msgLevel);
267 }
268 }