KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > content > transform > RuntimeExecutableContentTransformer


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.repo.content.transform;
18
19 import java.io.File JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Map JavaDoc;
23
24 import org.alfresco.error.AlfrescoRuntimeException;
25 import org.alfresco.repo.content.transform.ContentTransformerRegistry.TransformationKey;
26 import org.alfresco.service.cmr.repository.ContentIOException;
27 import org.alfresco.service.cmr.repository.ContentReader;
28 import org.alfresco.service.cmr.repository.ContentWriter;
29 import org.alfresco.util.TempFileProvider;
30 import org.alfresco.util.exec.RuntimeExec;
31 import org.alfresco.util.exec.RuntimeExec.ExecutionResult;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34
35 /**
36  * This configurable wrapper is able to execute any command line transformation that
37  * accepts an input and an output file on the command line.
38  * <p>
39  * The following parameters are use:
40  * <ul>
41  * <li><b>{@link #VAR_SOURCE target}</b> - full path to the source file</li>
42  * <li><b>{@link #VAR_TARGET source}</b> - full path to the target file</li>
43  * </ul>
44  * Provided that the command executed ultimately transforms the source file
45  * and leaves the result in the target file, the transformation should be
46  * successful.
47  * <p>
48  * <b>NOTE</b>: It is only the contents of the files that can be transformed.
49  * Any attempt to modify the source or target file metadata will, at best, have
50  * no effect, but may ultimately lead to the transformation failing. This is
51  * because the files provided are both temporary files that reside in a location
52  * outside the system's content store.
53  * <p>
54  * This transformer <b>requires</b> the setting of the <b>explicitTransformations</b>
55  * property.
56  *
57  * @see org.alfresco.util.exec.RuntimeExec
58  *
59  * @since 1.1
60  * @author Derek Hulley
61  */

62 public class RuntimeExecutableContentTransformer extends AbstractContentTransformer
63 {
64     public static final String JavaDoc VAR_SOURCE = "source";
65     public static final String JavaDoc VAR_TARGET = "target";
66
67     private static Log logger = LogFactory.getLog(RuntimeExecutableContentTransformer.class);
68     
69     private boolean available;
70     private RuntimeExec checkCommand;
71     private RuntimeExec transformCommand;
72
73     public RuntimeExecutableContentTransformer()
74     {
75     }
76     
77     @Override JavaDoc
78     public String JavaDoc toString()
79     {
80         StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
81         sb.append(this.getClass().getSimpleName())
82           .append("[ transform=").append(transformCommand).append("\n")
83           .append("]");
84         return sb.toString();
85     }
86     
87     /**
88      * Set the runtime executer that will be called as part of the initialisation
89      * to determine if the transformer is able to function. This is optional, but allows
90      * the transformer registry to detect and avoid using this instance if it is not working.
91      * <p>
92      * The command will be considered to have failed if the
93      *
94      * @param checkCommand the initialisation check command
95      */

96     public void setCheckCommand(RuntimeExec checkCommand)
97     {
98         this.checkCommand = checkCommand;
99     }
100
101     /**
102      * Set the runtime executer that will called to perform the actual transformation.
103      *
104      * @param transformCommand the runtime transform command
105      */

106     public void setTransformCommand(RuntimeExec transformCommand)
107     {
108         this.transformCommand = transformCommand;
109     }
110     
111     /**
112      * A comma or space separated list of values that, if returned by the executed command,
113      * indicate an error value. This defaults to <b>"1, 2"</b>.
114      *
115      * @param erroCodesStr
116      */

117     public void setErrorCodes(String JavaDoc errCodesStr)
118     {
119         throw new AlfrescoRuntimeException("content.runtime_exec.property_moved");
120     }
121     
122     /**
123      * Executes the check command, if present. Any errors will result in this component
124      * being rendered unusable within the transformer registry, but may still be called
125      * directly.
126      */

127     @Override JavaDoc
128     public void register()
129     {
130         if (transformCommand == null)
131         {
132             throw new AlfrescoRuntimeException("Mandatory property 'transformCommand' not set");
133         }
134         
135         // execute the command
136
if (checkCommand != null)
137         {
138             ExecutionResult result = checkCommand.execute();
139             // check the return code
140
available = result.getSuccess();
141         }
142         else
143         {
144             // no check - just assume it is available
145
available = true;
146         }
147         // call the base class to make sure that it gets registered
148
super.register();
149     }
150
151     /**
152      * If the {@link #init() initialization} failed, then it returns 0.0.
153      * Otherwise the explicit transformations are checked for the reliability.
154      *
155      * @return Returns 1.0 if initialization succeeded, otherwise 0.0.
156      *
157      * @see AbstractContentTransformer#setExplicitTransformations(List)
158      */

159     public double getReliability(String JavaDoc sourceMimetype, String JavaDoc targetMimetype)
160     {
161         if (!available)
162         {
163             return 0.0;
164         }
165         // check whether the transformation was one of the explicit transformations
166
TransformationKey transformationKey = new TransformationKey(sourceMimetype, targetMimetype);
167         List JavaDoc<TransformationKey> explicitTransformations = getExplicitTransformations();
168         if (explicitTransformations.size() == 0)
169         {
170             logger.warn(
171                     "Property 'explicitTransformations' should be set to enable this transformer: \n" +
172                     " transformer: " + this);
173         }
174         if (explicitTransformations.contains(transformationKey))
175         {
176             return 1.0;
177         }
178         else
179         {
180             return 0.0;
181         }
182     }
183     
184     /**
185      * Converts the source and target content to temporary files with the
186      * correct extensions for the mimetype that they map to.
187      *
188      * @see #transformInternal(File, File)
189      */

190     protected final void transformInternal(
191             ContentReader reader,
192             ContentWriter writer,
193             Map JavaDoc<String JavaDoc, Object JavaDoc> options) throws Exception JavaDoc
194     {
195         // get mimetypes
196
String JavaDoc sourceMimetype = getMimetype(reader);
197         String JavaDoc targetMimetype = getMimetype(writer);
198         
199         // get the extensions to use
200
String JavaDoc sourceExtension = getMimetypeService().getExtension(sourceMimetype);
201         String JavaDoc targetExtension = getMimetypeService().getExtension(targetMimetype);
202         if (sourceExtension == null || targetExtension == null)
203         {
204             throw new AlfrescoRuntimeException("Unknown extensions for mimetypes: \n" +
205                     " source mimetype: " + sourceMimetype + "\n" +
206                     " source extension: " + sourceExtension + "\n" +
207                     " target mimetype: " + targetMimetype + "\n" +
208                     " target extension: " + targetExtension);
209         }
210         
211         // create required temp files
212
File JavaDoc sourceFile = TempFileProvider.createTempFile(
213                 getClass().getSimpleName() + "_source_",
214                 "." + sourceExtension);
215         File JavaDoc targetFile = TempFileProvider.createTempFile(
216                 getClass().getSimpleName() + "_target_",
217                 "." + targetExtension);
218         
219         Map JavaDoc<String JavaDoc, String JavaDoc> properties = new HashMap JavaDoc<String JavaDoc, String JavaDoc>(5);
220         // copy options over
221
for (Map.Entry JavaDoc<String JavaDoc, Object JavaDoc> entry : options.entrySet())
222         {
223             String JavaDoc key = entry.getKey();
224             Object JavaDoc value = entry.getValue();
225             properties.put(key, (value == null ? null : value.toString()));
226         }
227         // add the source and target properties
228
properties.put(VAR_SOURCE, sourceFile.getAbsolutePath());
229         properties.put(VAR_TARGET, targetFile.getAbsolutePath());
230         
231         // pull reader file into source temp file
232
reader.getContent(sourceFile);
233
234         // execute the transformation command
235
ExecutionResult result = null;
236         try
237         {
238             result = transformCommand.execute(properties);
239         }
240         catch (Throwable JavaDoc e)
241         {
242             throw new ContentIOException("Transformation failed during command execution: \n" + transformCommand, e);
243         }
244         
245         // check
246
if (!result.getSuccess())
247         {
248             throw new ContentIOException("Transformation failed - status indicates an error: \n" + result);
249         }
250         
251         // check that the file was created
252
if (!targetFile.exists())
253         {
254             throw new ContentIOException("Transformation failed - target file doesn't exist: \n" + result);
255         }
256         // copy the target file back into the repo
257
writer.putContent(targetFile);
258         
259         // done
260
if (logger.isDebugEnabled())
261         {
262             logger.debug("Transformation completed: \n" +
263                     " source: " + reader + "\n" +
264                     " target: " + writer + "\n" +
265                     " options: " + options + "\n" +
266                     " result: \n" + result);
267         }
268     }
269 }
270
Popular Tags