1 package org.apache.torque.generator.control.existingtargetstrategy;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.io.File;
23 import java.io.IOException;
24
25 import org.apache.commons.io.FileUtils;
26 import org.apache.commons.io.FilenameUtils;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.torque.generator.GeneratorException;
30 import org.apache.torque.generator.configuration.UnitConfiguration;
31 import org.apache.torque.generator.control.ControllerException;
32 import org.apache.torque.generator.control.ControllerHelper;
33 import org.apache.torque.generator.merge.ThreeWayMerger;
34 import org.apache.torque.generator.outlet.OutletResult;
35
36 /**
37 * A handler which implements the strategy to replace existing target files.
38 *
39 * @version $Id: MergeTargetFileStrategy.java 1368426 2012-08-02 11:46:37Z tfischer $
40 */
41 public class MergeTargetFileStrategy implements ExistingTargetStrategy
42 {
43 /** The strategy name "replace". */
44 public static final String STRATEGY_NAME = "merge";
45
46 /** The subdirectory in the work directory<. */
47 public static final String WORK_SUBDIR = "raw-generated";
48
49 /** The classlogger. */
50 private static Log log = LogFactory.getLog(MergeTargetFileStrategy.class);
51
52 /** The merger. */
53 private final ThreeWayMerger merger = new ThreeWayMerger();
54
55 /**
56 * Will be called before the generation is started and decides whether
57 * the generation process for this file should proceed.
58 *
59 * @param outputDirKey the key for the output directory
60 * into which the generated file should be written,
61 * null for the default output directory.
62 * @param outputPath the path to which the output should be written,
63 * relative to the output base directory.
64 * @param encoding The character encoding of the generated file,
65 * or null for the platform default encoding.
66 * @param unitConfiguration the configuration of the current configuration
67 * unit, not null.
68 *
69 * @return true always.
70 */
71 public boolean beforeGeneration(
72 String outputDirKey,
73 String outputPath,
74 String encoding,
75 UnitConfiguration unitConfiguration)
76 {
77 return true;
78 }
79
80 /**
81 * Processes the results of the generation.
82 *
83 * @param outputDirKey the key for the output directory
84 * into which the generated file should be written,
85 * null for the default output directory.
86 * @param outputFile the location to which the output should be written.
87 * @param encoding The character encoding of the generated file,
88 * or null for the platform default encoding.
89 * @param generationResult the result of the generation, not null.
90 * @param unitConfiguration the configuration of the current configuration
91 * unit, not null.
92 * @throws GeneratorException on an error.
93 */
94 public void afterGeneration(
95 String outputDirKey,
96 String outputPath,
97 String encoding,
98 OutletResult generationResult,
99 UnitConfiguration unitConfiguration)
100 throws GeneratorException
101 {
102 File generationStorageDir
103 = new File(unitConfiguration.getWorkDirectory(), WORK_SUBDIR);
104 File generationStorageFile;
105 if (outputDirKey == null)
106 {
107 generationStorageFile
108 = new File(generationStorageDir,
109 FilenameUtils.concat("default", outputPath));
110 }
111 else
112 {
113 generationStorageFile
114 = new File(generationStorageDir,
115 FilenameUtils.concat("other",
116 FilenameUtils.concat(outputDirKey, outputPath)));
117 }
118 String oldGenerationContent = readFileToString(
119 generationStorageFile,
120 encoding);
121
122 File targetFile = ControllerHelper.getOutputFile(
123 outputDirKey,
124 outputPath,
125 unitConfiguration);
126 String oldTargetContent = readFileToString(
127 targetFile,
128 encoding);
129
130 if (!generationResult.isStringResult())
131 {
132 throw new GeneratorException(
133 "The merge target file strategy onlys works"
134 + " for String generation results (target file="
135 + targetFile.getAbsolutePath() + ")");
136 }
137
138 String newTargetContent = null;
139 if (oldTargetContent == null)
140 {
141 log.debug("no old target content found, using generation result");
142 newTargetContent = generationResult.getStringResult();
143 }
144 else if (oldGenerationContent == null)
145 {
146 log.info("no old generation content found,"
147 + "using old target content."
148 + " This is a bit unusual, but may be ok"
149 + " depending on the circumstances");
150 newTargetContent = generationResult.getStringResult();
151 }
152 else
153 {
154 log.debug("merging generation result and old target content");
155 newTargetContent = merger.merge(
156 oldGenerationContent,
157 generationResult.getStringResult(),
158 oldTargetContent,
159 encoding);
160 }
161 writeStringToFile(targetFile, newTargetContent, encoding);
162 writeStringToFile(
163 generationStorageFile,
164 generationResult.getStringResult(),
165 encoding);
166 }
167
168 /**
169 * Returns the name of the existing target strategy.
170 *
171 * @return "merge"
172 */
173 public String getStrategyName()
174 {
175 return STRATEGY_NAME;
176 }
177
178 /**
179 * Reads a String to a file.
180 *
181 * @param file the file to read, not null.
182 * @param charset the character set to use for reading the file,
183 * or null for platform default.
184 * @return the file's contents, or null if the file does not exist.
185 *
186 * @throws ControllerException if an error occurs while reading the file.
187 */
188 private String readFileToString(
189 File file,
190 String charset)
191 throws ControllerException
192 {
193 String result = null;
194 if (file.exists())
195 {
196 try
197 {
198 result = FileUtils.readFileToString(
199 file,
200 charset);
201 }
202 catch (IOException e)
203 {
204 throw new ControllerException(
205 "Could not read file \""
206 + file.getAbsolutePath()
207 + "\"",
208 e);
209 }
210 }
211 return result;
212 }
213
214 /**
215 * Writes a String to a file.
216 *
217 * @param file the location to write to, not null.
218 * @param content the content of the file, not null.
219 * @param charset the character set to use for writing the file,
220 * or null for platform default.
221 *
222 * @throws ControllerException if writing the file fails.
223 */
224 private void writeStringToFile(
225 File file,
226 String content,
227 String charset)
228 throws ControllerException
229 {
230 try
231 {
232 FileUtils.writeStringToFile(file, content, charset);
233 }
234 catch (IOException e)
235 {
236 throw new ControllerException(
237 "Could not write file \""
238 + file.getAbsolutePath()
239 + "\"",
240 e);
241 }
242 }
243 }