001: /*
002: * Copyright 2006 Pentaho Corporation. All rights reserved.
003: * This software was developed by Pentaho Corporation and is provided under the terms
004: * of the Mozilla Public License, Version 1.1, or any later version. You may not use
005: * this file except in compliance with the license. If you need a copy of the license,
006: * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
007: * BI Platform. The Initial Developer is Pentaho Corporation.
008: *
009: * Software distributed under the Mozilla Public License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
011: * the license for the specific language governing your rights and limitations.
012: *
013: * @created Apr 15, 2005
014: * @author James Dixon
015: */
016: package org.pentaho.plugin;
017:
018: import java.io.FileNotFoundException;
019: import java.io.InputStream;
020: import java.io.OutputStream;
021: import java.util.HashMap;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Map;
025: import java.util.Set;
026: import java.util.regex.Matcher;
027:
028: import javax.activation.DataSource;
029:
030: import org.dom4j.Element;
031: import org.dom4j.Node;
032: import org.pentaho.actionsequence.dom.actions.ActionDefinition;
033: import org.pentaho.core.component.IComponent;
034: import org.pentaho.core.repository.IContentItem;
035: import org.pentaho.core.runtime.ActionParameter;
036: import org.pentaho.core.runtime.IActionParameter;
037: import org.pentaho.core.runtime.IRuntimeContext;
038: import org.pentaho.core.runtime.InvalidParameterException;
039: import org.pentaho.core.runtime.SelectionMapper;
040: import org.pentaho.core.session.IPentahoSession;
041: import org.pentaho.core.solution.IActionResource;
042: import org.pentaho.core.system.ISystemSettings;
043: import org.pentaho.core.system.PentahoMessenger;
044: import org.pentaho.core.system.PentahoSystem;
045: import org.pentaho.core.util.IParameterResolver;
046: import org.pentaho.messages.Messages;
047: import org.pentaho.plugin.core.StandardSettings;
048: import org.pentaho.repository.filebased.solution.SolutionRepositoryVfs;
049: import org.pentaho.util.logging.ILogger;
050:
051: /**
052: */
053: public abstract class ComponentBase extends PentahoMessenger implements
054: IComponent, IParameterResolver {
055:
056: protected static final String UNKNOWN_COMPONENT_ID = "unknown"; //$NON-NLS-1$
057:
058: public static final String MISSING_SESSION = "session missing"; //$NON-NLS-1$
059:
060: public static final String COMPONENT_EXECUTE_FAIL = "component failed"; //$NON-NLS-1$
061:
062: protected static final boolean debug = PentahoSystem.debug;
063:
064: private IRuntimeContext runtimeContext;
065:
066: private IPentahoSession sessionContext;
067:
068: private String processId;
069:
070: private String actionName;
071:
072: private String instanceId;
073:
074: private String id;
075:
076: private boolean baseInitOk;
077:
078: private boolean componentInitOk;
079:
080: // private int loggingLevel = UNKNOWN;
081: private String logId;
082:
083: private Node componentDefinition;
084:
085: private ActionDefinition actionDefinition;
086:
087: private HashMap settings = new HashMap();
088:
089: public void setInstanceId(String instanceId) {
090: this .instanceId = instanceId;
091: }
092:
093: public String getInstanceId() {
094: return instanceId;
095: }
096:
097: public void setActionName(String actionName) {
098: this .actionName = actionName;
099: }
100:
101: public String getActionName() {
102: return actionName;
103: }
104:
105: public void setProcessId(String processId) {
106: this .processId = processId;
107: }
108:
109: public String getProcessId() {
110: return processId;
111: }
112:
113: public void setComponentDefinition(Node componentDefinition) {
114: this .componentDefinition = componentDefinition;
115: }
116:
117: public Node getComponentDefinition() {
118: return getComponentDefinition(false);
119: }
120:
121: /**
122: * Return the xml Node containing the component's definition. If
123: * <code>process</code> is true, visit every child node in the tree, and
124: * if the child node's text is an action parameter convert it to it's
125: * value. (See doc for applyInputsToFormat())
126: *
127: * @param process if true, if the node's text represents a parameter, convert
128: * the parameter to it's value, and assign the value to the
129: * node's text.
130: *
131: * @return Node containing this component's definition.
132: */
133: public Node getComponentDefinition(boolean process) {
134: if (process) {
135: List nodes = componentDefinition.selectNodes("//*"); //$NON-NLS-1$
136: Iterator it = nodes.iterator();
137: while (it.hasNext()) {
138: Node node = (Node) it.next();
139: String txt = node.getText();
140: if (txt != null && !node.isReadOnly()) {
141: node.setText(applyInputsToFormat(txt));
142: }
143: }
144: }
145: return componentDefinition;
146: }
147:
148: public void setRuntimeContext(IRuntimeContext runtimeContext) {
149: this .runtimeContext = runtimeContext;
150: }
151:
152: public IRuntimeContext getRuntimeContext() {
153: return runtimeContext;
154: }
155:
156: public void setSession(IPentahoSession session) {
157: this .sessionContext = session;
158: }
159:
160: public IPentahoSession getSession() {
161: return sessionContext;
162: }
163:
164: protected void saveSetting(String name, Object value) {
165: settings.put(name, value);
166: }
167:
168: protected Object getSetting(String name) {
169: return settings.get(name);
170: }
171:
172: protected String getStringSetting(String name) {
173: Object value = settings.get(name);
174: if (value == null) {
175: return null;
176: } else if (value instanceof String) {
177: return (String) value;
178: } else {
179: return value.toString();
180: }
181: }
182:
183: protected abstract boolean validateAction();
184:
185: protected abstract boolean validateSystemSettings();
186:
187: public abstract void done();
188:
189: protected abstract boolean executeAction() throws Throwable;
190:
191: public abstract boolean init();
192:
193: public String getLogId() {
194: return logId;
195: }
196:
197: protected boolean isDefinedInput(String inputName) {
198:
199: if (runtimeContext.getInputNames().contains(inputName)) {
200: return true;
201: } else {
202: return getComponentSetting(inputName) != null;
203: }
204: }
205:
206: protected boolean isDefinedOutput(String outputName) {
207: return runtimeContext.getOutputNames().contains(outputName);
208: }
209:
210: protected boolean isDefinedResource(String resourceName) {
211: return runtimeContext.getResourceNames().contains(resourceName);
212: }
213:
214: public final int validate() {
215:
216: logId = Messages
217: .getString(
218: "Base.CODE_LOG_ID", instanceId, runtimeContext.getHandle(), actionName); //$NON-NLS-1$
219: if (debug)
220: debug(Messages.getString(
221: "Base.DEBUG_VALIDATING_COMPONENT", actionName)); //$NON-NLS-1$
222: // grab the parameters first
223:
224: id = Messages.getString(
225: "Base.CODE_COMPONENT_ID", processId, actionName); //$NON-NLS-1$
226:
227: // now get picky about values
228: baseInitOk = (instanceId != null && sessionContext != null
229: && processId != null && actionName != null);
230:
231: boolean systemSettingsValidate = validateSystemSettings();
232:
233: if (baseInitOk && systemSettingsValidate) {
234: try {
235: componentInitOk = validateAction();
236: } catch (Exception e) {
237: error(
238: Messages
239: .getErrorString("Base.ERROR_0004_VALIDATION_FAILED"), e); //$NON-NLS-1$
240: }
241: }
242: if (getInitOk()) {
243: return IRuntimeContext.RUNTIME_CONTEXT_VALIDATE_OK;
244: }
245: return IRuntimeContext.RUNTIME_CONTEXT_VALIDATE_FAIL;
246: }
247:
248: public int resolveParameter(String template, String parameterName,
249: Matcher parameterMatcher, int copyStart, StringBuffer result) {
250: // Overriding components should return non-negative value if they handle resolving the parameter
251: return -1;
252: }
253:
254: public boolean getInitOk() {
255: return baseInitOk && componentInitOk;
256: }
257:
258: protected Set getOutputNames() {
259: return runtimeContext.getOutputNames();
260: }
261:
262: protected Set getInputNames() {
263: return runtimeContext.getInputNames();
264: }
265:
266: protected Set getResourceNames() {
267: return runtimeContext.getResourceNames();
268: }
269:
270: protected boolean feedbackAllowed() {
271: return runtimeContext.feedbackAllowed();
272: }
273:
274: protected IActionResource getResource(String resourceName) {
275: return runtimeContext.getResourceDefintion(resourceName);
276: }
277:
278: protected InputStream getResourceInputStream(
279: IActionResource resource) throws FileNotFoundException {
280: return runtimeContext.getResourceInputStream(resource);
281: }
282:
283: protected InputStream getInputStream(String inputName) {
284: return runtimeContext.getInputStream(inputName);
285: }
286:
287: protected int getOutputPreference() {
288: return runtimeContext.getOutputPreference();
289: }
290:
291: protected void audit(String messageType, String message,
292: String value, int duration) {
293: runtimeContext.audit(messageType, message, value, duration);
294: }
295:
296: protected boolean getInputBooleanValue(String inputName,
297: boolean defaultValue) {
298: String strValue = getInputStringValue(inputName);
299: if (strValue == null) {
300: return defaultValue;
301: } else if ("true".equalsIgnoreCase(strValue)) { //$NON-NLS-1$
302: return true;
303: } else if ("false".equalsIgnoreCase(strValue)) { //$NON-NLS-1$
304: return false;
305: } else {
306: return defaultValue;
307: }
308:
309: }
310:
311: protected long getInputLongValue(String inputName, long defaultValue) {
312: String strValue = getInputStringValue(inputName);
313: if (strValue == null) {
314: return defaultValue;
315: }
316: try {
317: return Long.parseLong(strValue);
318: } catch (Exception e) {
319: return defaultValue;
320: }
321:
322: }
323:
324: protected String getInputStringValue(String inputName) {
325: return getInputStringValue(inputName, true);
326: }
327:
328: protected String getInputStringValue(String inputName,
329: boolean applyTemplates) {
330: // first check to see if we have an input parameter that we can use for
331: // this.
332: String value = null;
333: if (runtimeContext.getInputNames().contains(inputName)) {
334: value = runtimeContext
335: .getInputParameterStringValue(inputName);
336: } else {
337: // now check the component node from the action definition.
338: Node node = componentDefinition.selectSingleNode(inputName);
339: if (node == null) {
340: return null;
341: }
342: value = node.getText();
343: }
344: if (value != null) {
345: if (applyTemplates) {
346: // TODO make the format appliation configurable
347: value = this .applyInputsToFormat(value);
348: }
349: }
350: return value;
351: }
352:
353: protected Object getInputValue(String inputName) {
354: // first check to see if we have an input parameter that we can use for
355: // this.
356: if (runtimeContext.getInputNames().contains(inputName)) {
357: return runtimeContext.getInputParameterValue(inputName);
358: }
359: // now check the component node from the action definition.
360: Node node = componentDefinition.selectSingleNode(inputName);
361: if (node == null) {
362: return null;
363: }
364: return node.getText();
365: }
366:
367: private String getComponentSetting(String path) {
368: // first check to see if we have an input parameter that we can use for
369: // this.
370: if (runtimeContext.getInputNames().contains(path)) {
371: return runtimeContext.getInputParameterStringValue(path);
372: }
373: // now check the component node from the action definition.
374: Node node = componentDefinition.selectSingleNode(path);
375: if (node == null) {
376: return null;
377: }
378: return node.getText();
379: }
380:
381: public void promptNeeded() {
382: runtimeContext.promptNeeded();
383: }
384:
385: public void promptNow() {
386: runtimeContext.promptNow();
387: }
388:
389: public String getResourceAsString(IActionResource resource) {
390: try {
391: return runtimeContext.getResourceAsString(resource);
392: } catch (Exception e) {
393: return null;
394: }
395: }
396:
397: /*
398: * protected IRuntimeContext getRuntimeContextX() { return runtimeContext; }
399: */
400: public String getInitFailMessage() {
401: // TODO: return a meaningful message here
402: return null;
403: }
404:
405: public String createNewInstance(boolean persisted, Map parameters,
406: boolean forceImmediateWrite) {
407: return runtimeContext.createNewInstance(persisted, parameters,
408: forceImmediateWrite);
409: }
410:
411: public void inputMissingError(String paramName) {
412: error(Messages
413: .getErrorString(
414: "ComponentBase.ERROR_0003_INPUT_PARAM_MISSING", paramName)); //$NON-NLS-1$
415: }
416:
417: public void outputMissingError(String paramName) {
418: error(Messages
419: .getErrorString(
420: "ComponentBase.ERROR_0004_OUTPUT_PARAM_MISSING", paramName)); //$NON-NLS-1$
421: }
422:
423: public void resourceMissingError(String paramName) {
424: error(Messages
425: .getErrorString(
426: "ComponentBase.ERROR_0005_RESOURCE_PARAM_MISSING", paramName)); //$NON-NLS-1$
427: }
428:
429: public void resourceComponentSettingError(String paramName) {
430: error(Messages
431: .getErrorString(
432: "ComponentBase.ERROR_0006_COMPONENT_SETTING_PARAM_MISSING", paramName)); //$NON-NLS-1$
433: }
434:
435: public int execute() {
436:
437: // see if we have a custom XSL for the parameter page, if required
438: String xsl = getComponentSetting("xsl"); //$NON-NLS-1$
439: if (xsl != null) {
440: runtimeContext.setParameterXsl(xsl);
441: } else {
442: //Proposed fix for bug BISERVER-97 by Ezequiel Cuellar
443: //If the component-definition's action-definition does not have an xsl element it reuses the one already
444: //set by its previous component-definition's action-definition peer.
445: //If the xsl element is not present for the component-definition then reset to the default xsl value
446: //specified in the Pentaho.xml tag "default-parameter-xsl"
447:
448: //Proposed fix for bug BISERVER-238 by Ezequiel Cuellar
449: //Added a default value of DefaultParameterForm.xsl when getting the value of default-parameter-xsl
450: ISystemSettings systemSettings = PentahoSystem
451: .getSystemSettings();
452: String defaultParameterXsl = systemSettings
453: .getSystemSetting("default-parameter-xsl", null); //$NON-NLS-1$
454: if (defaultParameterXsl != null
455: && defaultParameterXsl.length() > 0) {
456: runtimeContext.setParameterXsl(defaultParameterXsl);
457: }
458: }
459:
460: // see if we have a target window for the output
461: String target = getComponentSetting("target"); //$NON-NLS-1$
462: if (target != null) {
463: runtimeContext.setParameterTarget(target);
464: }
465:
466: if (loggingLevel == UNKNOWN) {
467: warn(Messages
468: .getString("Base.WARNING_LOGGING_LEVEL_UNKNOWN")); //$NON-NLS-1$
469: loggingLevel = ILogger.DEBUG;
470: }
471: int result = IRuntimeContext.RUNTIME_STATUS_FAILURE;
472:
473: if (sessionContext == null) {
474: error(Messages
475: .getErrorString("Base.ERROR_0001_INVALID_SESSION")); //$NON-NLS-1$
476: return result;
477: }
478: SolutionRepositoryVfs.setSolutionRepository(PentahoSystem
479: .getSolutionRepository(sessionContext));
480:
481: if (debug)
482: debug(Messages.getString("Base.DEBUG_VALIDATION_RESULT") + getInitOk()); //$NON-NLS-1$
483: if (!getInitOk()) {
484: return result;
485: }
486:
487: try {
488: result = (executeAction() ? IRuntimeContext.RUNTIME_STATUS_SUCCESS
489: : IRuntimeContext.RUNTIME_STATUS_FAILURE);
490: if (result == IRuntimeContext.RUNTIME_STATUS_SUCCESS
491: && runtimeContext.isPromptPending()) {
492: // see if we need to prevent further components from executing
493: if (isDefinedInput(StandardSettings.HANDLE_ALL_PROMPTS)) {
494: runtimeContext.promptNow();
495: }
496: }
497: } catch (InvalidParameterException e) {
498: // No reason to do a stack trace
499: error(Messages
500: .getErrorString("Base.ERROR_0002_EXECUTION_FAILED")); //$NON-NLS-1$
501: } catch (Throwable e) {
502: error(
503: Messages
504: .getErrorString("Base.ERROR_0002_EXECUTION_FAILED"), e); //$NON-NLS-1$
505: }
506: return result;
507: }
508:
509: public String getObjectName() {
510: return this .getClass().getName();
511: }
512:
513: public String getId() {
514: return id;
515: }
516:
517: public String getActionTitle() {
518: return runtimeContext.getActionTitle();
519: }
520:
521: /**
522: * @deprecated
523: * @return
524: */
525: protected IContentItem getOutputContentItem(String mimeType) {
526: return runtimeContext.getOutputContentItem(mimeType);
527: }
528:
529: protected IContentItem getOutputContentItem(String outputName,
530: String mimeType) {
531: return runtimeContext
532: .getOutputContentItem(outputName, mimeType);
533: }
534:
535: protected IContentItem getOutputItem(String outputName,
536: String mimeType, String extension) {
537: return runtimeContext.getOutputItem(outputName, mimeType,
538: extension);
539: }
540:
541: protected void setOutputValue(String outputName, Object value) {
542: runtimeContext.setOutputValue(outputName, value);
543: }
544:
545: protected void addTempParameter(String name, IActionParameter param) {
546: runtimeContext.addTempParameter(name, param);
547: }
548:
549: protected void addTempParameterObject(String name,
550: Object paramObject) {
551: String pType = "object"; //$NON-NLS-1$
552: IActionParameter actionParameter = new ActionParameter(name,
553: pType, paramObject, null, null);
554: addTempParameter(name, actionParameter);
555: }
556:
557: /**
558: *
559: * @deprecated
560: * @return
561: */
562: protected OutputStream getDefaultOutputStream(String mimeType) {
563: IContentItem contentItem = runtimeContext
564: .getOutputContentItem(mimeType);
565: if (contentItem != null) {
566: try {
567: return contentItem.getOutputStream(getActionName());
568: } catch (Exception e) {
569: this .getLogger().error(e);
570: }
571: }
572: return null;
573: }
574:
575: protected String applyInputsToFormat(String format) {
576: return runtimeContext.applyInputsToFormat(format, this );
577: }
578:
579: protected IActionParameter getOutputItem(String outputName) {
580: return runtimeContext.getOutputParameter(outputName);
581: }
582:
583: protected String getSolutionName() {
584: return runtimeContext.getSolutionName();
585: }
586:
587: protected String getSolutionPath() {
588: return runtimeContext.getSolutionPath();
589: }
590:
591: protected IActionParameter getInputParameter(String parameterName) {
592: return runtimeContext.getInputParameter(parameterName);
593: }
594:
595: protected String getContentUrl(IContentItem contentItem) {
596: return runtimeContext.getContentUrl(contentItem);
597: }
598:
599: protected boolean isPromptPending() {
600: return runtimeContext.isPromptPending();
601: }
602:
603: protected void setFeedbackMimeType(String mimeType) {
604: IContentItem feedbackContentItem = runtimeContext
605: .getFeedbackContentItem();
606: feedbackContentItem.setMimeType(mimeType);
607: }
608:
609: /**
610: *
611: * @deprecated
612: * @return
613: */
614: protected void setOutputMimeType(String mimeType) {
615: IContentItem outputContentItem = runtimeContext
616: .getOutputContentItem(mimeType);
617: outputContentItem.setMimeType(mimeType);
618: }
619:
620: protected void setOutputMimeType(String outputName, String mimeType) {
621: IContentItem outputContentItem = runtimeContext
622: .getOutputContentItem(outputName);
623: outputContentItem.setMimeType(mimeType);
624: }
625:
626: protected OutputStream getFeedbackOutputStream() {
627: IContentItem feedbackContentItem = runtimeContext
628: .getFeedbackContentItem();
629: if (feedbackContentItem != null) {
630: try {
631: return feedbackContentItem
632: .getOutputStream(getActionName());
633: } catch (Exception e) {
634: }
635: }
636: return null;
637: }
638:
639: /**
640: * @deprecated
641: * @param actionParam
642: */
643: protected void createFeedbackParameter(IActionParameter actionParam) {
644: runtimeContext.createFeedbackParameter(actionParam);
645: runtimeContext.promptNeeded();
646: }
647:
648: protected void createFeedbackParameter(SelectionMapper selMap,
649: String fieldName, Object defaultValues) {
650: runtimeContext.createFeedbackParameter(selMap, fieldName,
651: defaultValues);
652: runtimeContext.promptNeeded();
653: }
654:
655: protected void createFeedbackParameter(SelectionMapper selMap,
656: String fieldName, Object defaultValues, boolean optional) {
657: runtimeContext.createFeedbackParameter(selMap, fieldName,
658: defaultValues, optional);
659: if (!optional) {
660: runtimeContext.promptNeeded();
661: }
662: }
663:
664: protected void createFeedbackParameter(String fieldName,
665: String displayName, String hint, String defaultValue,
666: boolean visible) {
667: runtimeContext.createFeedbackParameter(fieldName, displayName,
668: hint, defaultValue, visible);
669: runtimeContext.promptNeeded();
670: }
671:
672: protected void createFeedbackParameter(String fieldName,
673: String displayName, String hint, String defaultValue,
674: boolean visible, boolean optional) {
675: runtimeContext.createFeedbackParameter(fieldName, displayName,
676: hint, defaultValue, visible, optional);
677: if (!optional) {
678: runtimeContext.promptNeeded();
679: }
680: }
681:
682: public void createFeedbackParameter(String fieldName,
683: String displayName, String hint, Object defaultValues,
684: List values, Map dispNames, String displayStyle) {
685: runtimeContext.createFeedbackParameter(fieldName, displayName,
686: hint, defaultValues, values, dispNames, displayStyle);
687: runtimeContext.promptNeeded();
688: }
689:
690: public void createFeedbackParameter(String fieldName,
691: String displayName, String hint, Object defaultValues,
692: List values, Map dispNames, String displayStyle,
693: boolean optional) {
694: runtimeContext.createFeedbackParameter(fieldName, displayName,
695: hint, defaultValues, values, dispNames, displayStyle,
696: optional);
697: if (!optional) {
698: runtimeContext.promptNeeded();
699: }
700: }
701:
702: protected DataSource getDataSource(String parameterName) {
703: return runtimeContext.getDataSource(parameterName);
704: }
705:
706: protected DataSource getResourceDataSource(IActionResource resource)
707: throws FileNotFoundException {
708: return runtimeContext.getResourceDataSource(resource);
709: }
710:
711: public void setActionDefinition(ActionDefinition actionDefinition) {
712: this .actionDefinition = actionDefinition;
713: }
714:
715: public ActionDefinition getActionDefinition() {
716: return actionDefinition;
717: }
718: }
|