001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.etl.ui.view.cookies;
042:
043: import java.io.File;
044: import java.util.ArrayList;
045: import java.util.Iterator;
046: import java.util.List;
047: import java.util.ListIterator;
048: import javax.swing.SwingUtilities;
049: import org.netbeans.modules.etl.codegen.ETLProcessFlowGenerator;
050: import org.netbeans.modules.etl.codegen.ETLProcessFlowGeneratorFactory;
051: import org.netbeans.modules.etl.codegen.ETLScriptBuilderModel;
052: import org.netbeans.modules.etl.model.ETLDefinition;
053: import org.netbeans.modules.etl.ui.DataObjectHelper;
054: import org.netbeans.modules.etl.ui.DataObjectProvider;
055: import org.netbeans.modules.etl.ui.model.impl.ETLCollaborationModel;
056: import org.netbeans.modules.etl.ui.view.ETLCollaborationTopPanel;
057: import org.netbeans.modules.sql.framework.model.ValidationInfo;
058: import org.netbeans.modules.sql.framework.ui.SwingWorker;
059: import org.netbeans.modules.sql.framework.ui.utils.UIUtil;
060: import org.netbeans.modules.sql.framework.ui.output.SQLLogView;
061: import org.openide.DialogDisplayer;
062: import org.openide.NotifyDescriptor;
063: import org.openide.nodes.Node;
064: import com.sun.etl.engine.ETLEngine;
065: import com.sun.etl.engine.ETLEngineExecEvent;
066: import com.sun.etl.engine.ETLEngineListener;
067: import com.sun.etl.engine.ETLEngineLogEvent;
068: import com.sun.sql.framework.exception.BaseException;
069: import net.java.hulp.i18n.Logger;
070: import com.sun.sql.framework.utils.StringUtil;
071: import org.netbeans.modules.etl.logger.Localizer;
072: import org.netbeans.modules.etl.logger.LogUtil;
073:
074: /**
075: * Encapsulates access control and execution of test eTL process on a selected
076: * SQLDefinition.
077: *
078: * @author Jonathan Giron
079: * @version $Revision$
080: */
081: public class ExecuteTestCookie implements Node.Cookie {
082:
083: private static final String NL = System.getProperty(
084: "line.separator", "\n");
085: private final String logCategory = ExecuteTestCookie.class
086: .getName();
087: private ETLEngine engine;
088: private ETLCollaborationTopPanel topPanel;
089: private SQLLogView logView;
090: private long startTime;
091: private long endTime;
092: private static transient final Logger mLogger = LogUtil
093: .getLogger(ExecuteTestCookie.class.getName());
094: private static transient final Localizer mLoc = Localizer.get();
095:
096: /**
097: * Creates a new instance of ETLEditorSaveAction associated with the given
098: * data object.
099: *
100: * @param mObj etldataobject to associate with this cookie.
101: */
102: public ExecuteTestCookie() {
103: }
104:
105: /** Executes the test process for the associated SQLDefinition. */
106: public void start() {
107: try {
108: topPanel = DataObjectProvider.getProvider()
109: .getActiveDataObject().getETLEditorTopPanel();
110: } catch (Exception ex) {
111: // ignore
112: }
113: if (topPanel != null) {
114: logView = topPanel.showLog();
115: }
116:
117: try {
118: ETLCollaborationModel collabModel = DataObjectProvider
119: .getProvider().getActiveDataObject().getModel();
120: if (collabModel == null) {
121: throw new BaseException("Collaboration model is null");
122: }
123:
124: ETLDefinition execModel = collabModel.getETLDefinition();
125: if (execModel == null) {
126: throw new BaseException("Repository model is null");
127: }
128:
129: // WT #67452: Validate collab prior to executing engine.
130: List invalidObjectList = execModel.validate();
131: if (!invalidObjectList.isEmpty()) {
132: String errMsg = "";
133:
134: Iterator iter = invalidObjectList.iterator();
135: boolean validationErr = false;
136: while (iter.hasNext()) {
137: ValidationInfo invalidObj = (ValidationInfo) iter
138: .next();
139: if (invalidObj.getValidationType() == ValidationInfo.VALIDATION_ERROR) {
140: errMsg += invalidObj.getDescription();
141: errMsg += NL;
142: validationErr = true;
143: }
144: }
145:
146: if (validationErr) {
147: throw new BaseException(
148: "Invalid eTL Collaboration." + NL + errMsg);
149: }
150: logView.appendToView(errMsg + NL);
151: }
152:
153: String nbBundle1 = mLoc.t("PRSR001: Execution started.");
154: logView.appendToView(Localizer.parse(nbBundle1));
155:
156: startTime = System.currentTimeMillis();
157: RunEngineWorkerThread runEThread = new RunEngineWorkerThread(
158: execModel);
159: DataObjectHelper.setWaitCursor();
160:
161: String nbBundle2 = mLoc.t("PRSR001: Executing");
162: String title = Localizer.parse(nbBundle2);
163: String nbBundle3 = mLoc
164: .t("PRSR001: Executing, please wait...");
165: String msg = Localizer.parse(nbBundle3);
166: UIUtil.startProgressDialog(title, msg);
167: runEThread.start();
168: } catch (Exception e) {
169: String nbBundle4 = mLoc.t("PRSR001: Execution failed:{0}",
170: e.getMessage());
171: String msg = Localizer.parse(nbBundle4);
172: // Ensure progress bar dialog box is removed from display even if listener
173: // never gets the message that engine is done.
174: SwingUtilities.invokeLater(new CloseProgressBarTask());
175:
176: logView.appendToView(msg);
177: DialogDisplayer.getDefault().notify(
178: new NotifyDescriptor.Message(msg,
179: NotifyDescriptor.WARNING_MESSAGE));
180: mLogger.errorNoloc(mLoc
181: .t("PRSR011: Problem in executing engine."), e);
182: }
183: }
184:
185: private final class CloseProgressBarTask implements Runnable {
186:
187: public void run() {
188: UIUtil.stopProgressDialog();
189: DataObjectHelper.setDefaultCursor();
190: }
191: }
192:
193: private class UIEngineListener implements ETLEngineListener {
194:
195: /**
196: * This method will be called at the end of execution of the workflow.
197: * @param event Event associated with Execution of ETL.
198: */
199: public synchronized void executionPerformed(
200: ETLEngineExecEvent event) {
201: if ((event.getStatus() == ETLEngine.STATUS_COLLAB_COMPLETED)
202: || (event.getStatus() == ETLEngine.STATUS_COLLAB_EXCEPTION)) {
203: mLogger
204: .infoNoloc(mLoc
205: .t("PRSR012: eTL engine execution completed..."));
206: // Ensure GUI change occurs in the event-dispatch thread.
207: SwingUtilities.invokeLater(new CloseProgressBarTask());
208: try {
209: endTime = System.currentTimeMillis();
210: StringBuilder msgBuf = new StringBuilder(100);
211: String nbBundle5 = mLoc
212: .t(
213: "PRSR001: Execution completed successfully.{0}",
214: NL);
215: String msg = (event.getStatus() == ETLEngine.STATUS_COLLAB_COMPLETED) ? Localizer
216: .parse(nbBundle5)
217: : "MSG_executed_errors"; // No I18N
218: String nbBundle11 = mLoc
219: .t("PRSR001: Execution completed with {0,choice,0#unknown error|1#error|1<errors}:{1}");
220: String nbBundle20 = mLoc.t("PRSR001: {0}", msg);
221: msgBuf.append(Localizer.parse(nbBundle20));
222: String nbBundle6 = mLoc
223: .t(
224: "PRSR001: Execution time: {0}.{1} seconds.{2}",
225: new Long(
226: (endTime - startTime) / 1000),
227: new Long(
228: (endTime - startTime) % 1000),
229: NL);
230: msgBuf.append(Localizer.parse(nbBundle6));
231: logView.appendToView(msgBuf.toString());
232: if (event.getStatus() == ETLEngine.STATUS_COLLAB_COMPLETED) {
233: int rowsProcessed = 0;
234: Iterator it = engine.getContext()
235: .getStatistics().getKnownTableNames()
236: .iterator();
237: while (it.hasNext()) {
238: rowsProcessed += engine.getContext()
239: .getStatistics()
240: .getRowsInsertedCount(
241: (String) it.next());
242: }
243: msgBuf.append("Rows Processed: "
244: + String.valueOf(rowsProcessed));
245: DialogDisplayer
246: .getDefault()
247: .notify(
248: new NotifyDescriptor.Message(
249: msgBuf.toString(),
250: NotifyDescriptor.INFORMATION_MESSAGE));
251: }
252: } catch (Exception ex) {
253: mLogger
254: .errorNoloc(
255: mLoc
256: .t("PRSR013: Problem while handling ETLEngineExecEvent for current execution."),
257: ex);
258: } finally {
259: // Ensure dialog box is removed from display - should be harmless if called twice.
260: SwingUtilities
261: .invokeLater(new CloseProgressBarTask());
262: engine.stopETLEngine();
263: notifyAll();
264: }
265: }
266: }
267:
268: public void updateOutputMessage(ETLEngineLogEvent evt) {
269: if (evt != null && logView != null) {
270: String nbBundle7 = mLoc.t("PRSR001: {0}: {1}", evt
271: .getSourceName(), evt.getLogMessage());
272: String msg = Localizer.parse(nbBundle7);
273: logView.appendToView(msg);
274: mLogger.infoNoloc(mLoc.t(
275: "PRSR014: evt.getLogLevel(){0}", msg));
276: }
277: }
278: }
279:
280: private class RunEngineWorkerThread extends SwingWorker {
281:
282: private ETLDefinition execModel;
283: private List throwableList = new ArrayList();
284:
285: public RunEngineWorkerThread(ETLDefinition execModel) {
286: this .execModel = execModel;
287: }
288:
289: @SuppressWarnings(value="unchecked")
290: public Object construct() {
291: if (execModel != null) {
292: ClassLoader origLoader = Thread.currentThread()
293: .getContextClassLoader();
294: try {
295: ETLProcessFlowGenerator flowGen = ETLProcessFlowGeneratorFactory
296: .getCollabFlowGenerator(execModel
297: .getSQLDefinition(), false);
298: flowGen.applyConnectionDefinitions();
299: engine = flowGen.getScript();
300:
301: //RIT print out the content of etl engine file
302: //System.out.println("printing etl engine file content: \n" + engine.toXMLString());
303:
304: UIEngineListener listener = new UIEngineListener();
305:
306: // WT #67399: Ensure we use the class loader associated with
307: // SQLFramework moudle, to avoid instantiating Axion classes which are
308: // associated with eBAM.
309: Thread.currentThread().setContextClassLoader(
310: this .getClass().getClassLoader());
311:
312: engine.exec(listener);
313: synchronized (listener) {
314: listener.wait();
315: }
316: throwableList = engine.getContext()
317: .getThrowableList();
318: } catch (Exception ex) {
319: mLogger.errorNoloc(mLoc.t("PRSR015: Exception: "),
320: ex);
321: throwableList.add(ex);
322: } finally {
323: Thread.currentThread().setContextClassLoader(
324: origLoader);
325: removeInstanceDBFolder();
326: }
327: } else {
328: throwableList.add(new BaseException(
329: "No eTL collaboration model to execute"));
330: String nbBundle8 = mLoc
331: .t("PRSR001: Execution failed: ");
332: logView.appendToView(Localizer.parse(nbBundle8));
333: }
334:
335: return "";
336: }
337:
338: // Runs on the event-dispatching thread.
339: @Override
340: public void finished() {
341: if (throwableList.size() != 0) {
342: new CloseProgressBarTask().run();
343:
344: writeToAppLog(throwableList);
345:
346: StringBuilder msgBuf = new StringBuilder(100);
347: ListIterator iter = throwableList.listIterator();
348: while (iter.hasNext()) {
349: Throwable t = (Throwable) iter.next();
350: String detailMsg = t.getMessage();
351: if (StringUtil.isNullString(detailMsg)) {
352: String nbBundle9 = mLoc
353: .t("PRSR001: Execution with unknown error. Please review messages.log under netbeans user home directory for more details. completed with unknown error. Please review messages.log under netbeans user home directory for more details.");
354: detailMsg = Localizer.parse(nbBundle9);
355: }
356:
357: detailMsg.trim();
358: msgBuf.append(iter.nextIndex()).append(". ")
359: .append(detailMsg).append(NL);
360: }
361:
362: String nbBundle10 = mLoc
363: .t(
364: "PRSR001: Execution completed with {0,choice,0#unknown error|1#error|1<errors}:{1}",
365: new Integer(throwableList.size()),
366: msgBuf.toString());
367: String msg = Localizer.parse(nbBundle10);
368: logView.appendToView(msg);
369: DialogDisplayer.getDefault().notify(
370: new NotifyDescriptor.Message(msg,
371: NotifyDescriptor.WARNING_MESSAGE));
372: }
373: }
374:
375: /**
376: * Logs all Throwables, if any, encountered during an execution run to the system
377: * log.
378: *
379: * @param throwableList List of Throwables to be logged
380: */
381: private void writeToAppLog(List throwables) {
382: if (throwables.size() != 0) {
383: ListIterator iter = throwables.listIterator();
384: mLogger
385: .infoNoloc(mLoc
386: .t(
387: "PRSR016: Exceptions caught during engine execution:{0}",
388: logCategory));
389: while (iter.hasNext()) {
390: Throwable t = (Throwable) iter.next();
391: mLogger.errorNoloc(mLoc.t(
392: "PRSR017: > Exception{0}", Integer
393: .toString(iter.nextIndex())), t);
394: }
395: }
396: }
397:
398: private boolean deleteFile(File file) throws Exception {
399: if (!file.exists()) {
400: return true;
401: }
402: if (file.isDirectory()) {
403: File[] files = file.listFiles();
404: for (int i = 0; i < files.length; i++) {
405: deleteFile(files[i]);
406: }
407: }
408: return file.delete();
409: }
410:
411: private void removeInstanceDBFolder() {
412: try {
413: File workingFolder = new File(
414: ETLScriptBuilderModel.ETL_DESIGN_WORK_FOLDER);
415: deleteFile(workingFolder);
416: } catch (Exception ex) {
417: mLogger.errorNoloc(mLoc.t(
418: "PRSR018: Error deleting working folder.{0}",
419: logCategory), ex);
420: }
421: }
422: }
423: }
|