KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > scriptella > execution > EtlExecutor


1 /*
2  * Copyright 2006-2007 The Scriptella Project Team.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package scriptella.execution;
17
18 import scriptella.configuration.ConfigurationEl;
19 import scriptella.configuration.ConfigurationFactory;
20 import scriptella.core.Session;
21 import scriptella.core.ThreadSafe;
22 import scriptella.interactive.ProgressCallback;
23 import scriptella.interactive.ProgressIndicator;
24 import scriptella.util.CollectionUtils;
25 import scriptella.util.IOUtils;
26
27 import java.io.File JavaDoc;
28 import java.net.MalformedURLException JavaDoc;
29 import java.net.URL JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.logging.Level JavaDoc;
32 import java.util.logging.Logger JavaDoc;
33
34
35 /**
36  * Executor for ETL files.
37  * <p>Use {@link ConfigurationFactory} to parse script files and to configure
38  * the executor.
39  * <p>The usage scenario of this class may be described using the following steps:
40  * <ul>
41  * <li>{@link #EtlExecutor(scriptella.configuration.ConfigurationEl)} Create an instance of this class
42  * and pass a {@link scriptella.configuration.ConfigurationFactory#createConfiguration() script file configuration}.
43  * <li>{@link #execute() Execute} the script
44  * </ul>
45  * </pre></code>
46  * <p>Additionally simplified helper methods are declared in this class:
47  * <ul>
48  * <li>{@link #newExecutor(java.io.File)}
49  * <li>{@link #newExecutor(java.net.URL)}
50  * <li>{@link #newExecutor(java.net.URL, java.util.Map)}
51  * </ul>
52  * <p/>
53  * <h3>ETL Cancellation</h3>
54  * Scriptella execution model relies on a standard Java {@link Thread#interrupt()} mechanism.
55  * <p>To interrupt the ETL execution invoke {@link Thread#interrupt()} on a thread
56  * which {@link #execute() started} ETL operation. As a part of interruption process
57  * the engine tries to roll back all changes made during the ETL operation.
58  * <p>{@link java.util.concurrent.ExecutorService} and {@link java.util.concurrent.Future}
59  * can also be used to control ETL execution.
60  *
61  * @author Fyodor Kupolov
62  * @version 1.0
63  */

64 public class EtlExecutor {
65     private static final Logger JavaDoc LOG = Logger.getLogger(EtlExecutor.class.getName());
66     private ConfigurationEl configuration;
67     private boolean jmxEnabled;
68
69     /**
70      * Creates ETL executor.
71      */

72     public EtlExecutor() {
73     }
74
75     /**
76      * Creates an ETL executor for specified configuration file.
77      *
78      * @param configuration ETL configuration.
79      */

80     public EtlExecutor(ConfigurationEl configuration) {
81         this.configuration = configuration;
82     }
83
84     /**
85      * Returns ETL configuration for this executor.
86      *
87      * @return ETL configuration.
88      */

89     public ConfigurationEl getConfiguration() {
90         return configuration;
91     }
92
93     /**
94      * Sets ETL configuration.
95      *
96      * @param configuration ETL configuration.
97      */

98     public void setConfiguration(final ConfigurationEl configuration) {
99         this.configuration = configuration;
100     }
101
102
103     /**
104      * Returns true if monitoring/management via JMX is enabled.
105      * <p>If jmxEnabled=true the executor registers MBeans for executed ETL files.
106      * The object names of the mbeans have the following form:
107      * <code>scriptella: type=etl,url="ETL_FILE_URL"</code>
108      *
109      * @return true if monitoring/management via JMX is enabled.
110      */

111     public boolean isJmxEnabled() {
112         return jmxEnabled;
113     }
114
115     /**
116      * Enables or disables ETL monitoring/management via JMX.
117      * <p>If jmxEnabled=true the executor registers MBeans for executed ETL files.
118      * The object names of the mbeans have the following form:
119      * <code>scriptella: type=etl,url="ETL_FILE_URL"</code>
120      *
121      * @param jmxEnabled true if monitoring/management via JMX is enabled.
122      * @see scriptella.execution.JmxEtlManagerMBean
123      */

124     public void setJmxEnabled(boolean jmxEnabled) {
125         this.jmxEnabled = jmxEnabled;
126     }
127
128     /**
129      * Executes ETL based on a specified configuration.
130      */

131     @ThreadSafe
132     public ExecutionStatistics execute() throws EtlExecutorException {
133         return execute((ProgressIndicator) null);
134     }
135
136     /**
137      * Executes ETL based on a specified configuration.
138      *
139      * @param indicator progress indicator to use.
140      */

141     @ThreadSafe
142     public ExecutionStatistics execute(final ProgressIndicator indicator)
143             throws EtlExecutorException {
144         EtlContext ctx = null;
145         JmxEtlManager etlManager = null;
146
147         try {
148             ctx = prepare(indicator);
149             if (jmxEnabled) {
150                 etlManager = new JmxEtlManager(ctx);
151                 etlManager.register();
152             }
153             execute(ctx);
154             ctx.getProgressCallback().step(5, "Commiting transactions");
155             commitAll(ctx);
156         } catch (Throwable JavaDoc e) {
157             if (ctx != null) {
158                 rollbackAll(ctx);
159             }
160             throw new EtlExecutorException(e);
161         } finally {
162             if (ctx != null) {
163                 closeAll(ctx);
164                 ctx.getStatisticsBuilder().etlComplete();
165                 ctx.getProgressCallback().complete();
166             }
167             if (etlManager != null) {
168                 etlManager.unregister();
169             }
170         }
171
172         return ctx.getStatisticsBuilder().getStatistics();
173     }
174
175     void rollbackAll(final EtlContext ctx) {
176         try {
177             ctx.session.rollback();
178         } catch (Exception JavaDoc e) {
179             LOG.log(Level.SEVERE, "Unable to rollback script", e);
180         }
181     }
182
183     void commitAll(final EtlContext ctx) {
184         ctx.session.commit();
185     }
186
187     void closeAll(final EtlContext ctx) {
188         ctx.session.close();
189     }
190
191     private void execute(final EtlContext ctx) {
192         final ProgressCallback oldProgress = ctx.getProgressCallback();
193
194         final ProgressCallback p = oldProgress.fork(85, 100);
195         final ProgressCallback p2 = p.fork(100);
196         ctx.setProgressCallback(p2);
197         ctx.session.execute(ctx);
198         p.complete();
199         ctx.setProgressCallback(oldProgress);
200     }
201
202     /**
203      * Prepares the scripts context.
204      *
205      * @param indicator progress indicator to use.
206      * @return prepared scripts context.
207      */

208     protected EtlContext prepare(final ProgressIndicator indicator) {
209         EtlContext ctx = new EtlContext();
210         ctx.getStatisticsBuilder().etlStarted();
211         ctx.setBaseURL(configuration.getDocumentUrl());
212         ctx.setProgressCallback(new ProgressCallback(100, indicator));
213
214         final ProgressCallback progress = ctx.getProgressCallback();
215         progress.step(1, "Initializing properties");
216         ctx.setProperties(configuration.getProperties());
217         ctx.setProgressCallback(progress.fork(9, 100));
218         ctx.session = new Session(configuration, ctx);
219         ctx.getProgressCallback().complete();
220         ctx.setProgressCallback(progress); //Restoring
221

222         return ctx;
223     }
224
225     /**
226      * Converts file to URL and invokes {@link #newExecutor(java.net.URL)}.
227      *
228      * @param scriptFile ETL file.
229      * @return configured instance of script executor.
230      * @see #newExecutor(java.net.URL)
231      */

232     public static EtlExecutor newExecutor(final File JavaDoc scriptFile) {
233         try {
234             return newExecutor(IOUtils.toUrl(scriptFile));
235         } catch (MalformedURLException JavaDoc e) {
236             throw new IllegalArgumentException JavaDoc(e.getMessage(), e);
237         }
238     }
239
240     /**
241      * Helper method to create a new ScriptExecutor for specified script URL.
242      * <p>Calls {@link #newExecutor(java.net.URL, java.util.Map)} and passes {@link System#getProperties() System properties}
243      * as external properties.
244      *
245      * @param scriptFileUrl URL of script file.
246      * @return configured instance of script executor.
247      */

248     @ThreadSafe
249     public static EtlExecutor newExecutor(final URL JavaDoc scriptFileUrl) {
250         return newExecutor(scriptFileUrl, CollectionUtils.asMap(System.getProperties()));
251     }
252
253     /**
254      * Helper method to create a new ScriptExecutor for specified script URL.
255      *
256      * @param scriptFileUrl URL of script file.
257      * @param externalProperties see {@link ConfigurationFactory#setExternalProperties(java.util.Map)}
258      * @return configured instance of script executor.
259      * @see ConfigurationFactory
260      */

261     @ThreadSafe
262     public static EtlExecutor newExecutor(final URL JavaDoc scriptFileUrl, final Map JavaDoc<String JavaDoc, ?> externalProperties) {
263         ConfigurationFactory cf = new ConfigurationFactory();
264         cf.setResourceURL(scriptFileUrl);
265         if (externalProperties != null) {
266             cf.setExternalProperties(externalProperties);
267         }
268         return new EtlExecutor(cf.createConfiguration());
269     }
270
271 }
272
Popular Tags