// Save the attributes of this job entry // public void saveRep(Repository rep, IMetaStore metaStore, ObjectId id_job) throws KettleException { try { rep.saveJobEntryAttribute(id_job, getObjectId(), "file_name", filename); rep.saveJobEntryAttribute(id_job, getObjectId(), "work_directory", workDirectory); rep.saveJobEntryAttribute(id_job, getObjectId(), "arg_from_previous", argFromPrevious); rep.saveJobEntryAttribute(id_job, getObjectId(), "exec_per_row", execPerRow); rep.saveJobEntryAttribute(id_job, getObjectId(), "set_logfile", setLogfile); rep.saveJobEntryAttribute(id_job, getObjectId(), "set_append_logfile", setAppendLogfile); rep.saveJobEntryAttribute(id_job, getObjectId(), "add_date", addDate); rep.saveJobEntryAttribute(id_job, getObjectId(), "add_time", addTime); rep.saveJobEntryAttribute(id_job, getObjectId(), "logfile", logfile); rep.saveJobEntryAttribute(id_job, getObjectId(), "logext", logext); rep.saveJobEntryAttribute( id_job, getObjectId(), "loglevel", logFileLevel == null ? LogLevel.NOTHING.getCode() : logFileLevel.getCode()); rep.saveJobEntryAttribute(id_job, getObjectId(), "insertScript", insertScript); rep.saveJobEntryAttribute(id_job, getObjectId(), "script", script); // save the arguments... if (arguments != null) { for (int i = 0; i < arguments.length; i++) { rep.saveJobEntryAttribute(id_job, getObjectId(), i, "argument", arguments[i]); } } } catch (KettleDatabaseException dbe) { throw new KettleException("Unable to save job entry of type 'shell' to the repository", dbe); } }
public String getXML() { StringBuffer retval = new StringBuffer(300); retval.append(super.getXML()); retval.append(" ").append(XMLHandler.addTagValue("filename", filename)); retval.append(" ").append(XMLHandler.addTagValue("work_directory", workDirectory)); retval.append(" ").append(XMLHandler.addTagValue("arg_from_previous", argFromPrevious)); retval.append(" ").append(XMLHandler.addTagValue("exec_per_row", execPerRow)); retval.append(" ").append(XMLHandler.addTagValue("set_logfile", setLogfile)); retval.append(" ").append(XMLHandler.addTagValue("logfile", logfile)); retval.append(" ").append(XMLHandler.addTagValue("set_append_logfile", setAppendLogfile)); retval.append(" ").append(XMLHandler.addTagValue("logext", logext)); retval.append(" ").append(XMLHandler.addTagValue("add_date", addDate)); retval.append(" ").append(XMLHandler.addTagValue("add_time", addTime)); retval.append(" ").append(XMLHandler.addTagValue("insertScript", insertScript)); retval.append(" ").append(XMLHandler.addTagValue("script", script)); retval .append(" ") .append( XMLHandler.addTagValue( "loglevel", (logFileLevel == null) ? null : logFileLevel.getCode())); if (arguments != null) { for (int i = 0; i < arguments.length; i++) { // THIS IS A VERY BAD WAY OF READING/SAVING AS IT MAKES // THE XML "DUBIOUS". DON'T REUSE IT. (Sven B) retval.append(" ").append(XMLHandler.addTagValue("argument" + i, arguments[i])); } } return retval.toString(); }
public void getInfo() { try { configuration.setExecutingLocally(wExecLocal.getSelection()); configuration.setExecutingRemotely(wExecRemote.getSelection()); // Remote data // if (wExecRemote.getSelection()) { String serverName = wRemoteHost.getText(); configuration.setRemoteServer(abstractMeta.findSlaveServer(serverName)); } configuration.setPassingExport(wPassExport.getSelection()); getConfiguration().setExpandingRemoteJob(wExpandRemote.getSelection()); // various settings // configuration.setReplayDate(null); configuration.setSafeModeEnabled(wSafeMode.getSelection()); configuration.setClearingLog(wClearLog.getSelection()); configuration.setLogLevel(LogLevel.values()[wLogLevel.getSelectionIndex()]); String startCopyName = null; int startCopyNr = 0; if (!Const.isEmpty(wStartCopy.getText())) { if (wStartCopy.getSelectionIndex() >= 0) { JobEntryCopy copy = ((JobMeta) abstractMeta).getJobCopies().get(wStartCopy.getSelectionIndex()); startCopyName = copy.getName(); startCopyNr = copy.getNr(); } } getConfiguration().setStartCopyName(startCopyName); getConfiguration().setStartCopyNr(startCopyNr); // The lower part of the dialog... getInfoParameters(); getInfoVariables(); // Metrics configuration.setGatheringMetrics(wGatherMetrics.getSelection()); } catch (Exception e) { new ErrorDialog(shell, "Error in settings", "There is an error in the dialog settings", e); } }
public void loadXML( Node entrynode, List<DatabaseMeta> databases, List<SlaveServer> slaveServers, Repository rep, IMetaStore metaStore) throws KettleXMLException { try { super.loadXML(entrynode, databases, slaveServers); setFileName(XMLHandler.getTagValue(entrynode, "filename")); setWorkDirectory(XMLHandler.getTagValue(entrynode, "work_directory")); argFromPrevious = "Y".equalsIgnoreCase(XMLHandler.getTagValue(entrynode, "arg_from_previous")); execPerRow = "Y".equalsIgnoreCase(XMLHandler.getTagValue(entrynode, "exec_per_row")); setLogfile = "Y".equalsIgnoreCase(XMLHandler.getTagValue(entrynode, "set_logfile")); setAppendLogfile = "Y".equalsIgnoreCase(XMLHandler.getTagValue(entrynode, "set_append_logfile")); addDate = "Y".equalsIgnoreCase(XMLHandler.getTagValue(entrynode, "add_date")); addTime = "Y".equalsIgnoreCase(XMLHandler.getTagValue(entrynode, "add_time")); logfile = XMLHandler.getTagValue(entrynode, "logfile"); logext = XMLHandler.getTagValue(entrynode, "logext"); logFileLevel = LogLevel.getLogLevelForCode(XMLHandler.getTagValue(entrynode, "loglevel")); insertScript = "Y".equalsIgnoreCase(XMLHandler.getTagValue(entrynode, "insertScript")); script = XMLHandler.getTagValue(entrynode, "script"); // How many arguments? int argnr = 0; while (XMLHandler.getTagValue(entrynode, "argument" + argnr) != null) { argnr++; } arguments = new String[argnr]; // Read them all... // THIS IS A VERY BAD WAY OF READING/SAVING AS IT MAKES // THE XML "DUBIOUS". DON'T REUSE IT. for (int a = 0; a < argnr; a++) { arguments[a] = XMLHandler.getTagValue(entrynode, "argument" + a); } } catch (KettleException e) { throw new KettleXMLException("Unable to load job entry of type 'shell' from XML node", e); } }
// Load the jobentry from repository public void loadRep( Repository rep, IMetaStore metaStore, ObjectId id_jobentry, List<DatabaseMeta> databases, List<SlaveServer> slaveServers) throws KettleException { try { setFileName(rep.getJobEntryAttributeString(id_jobentry, "file_name")); setWorkDirectory(rep.getJobEntryAttributeString(id_jobentry, "work_directory")); argFromPrevious = rep.getJobEntryAttributeBoolean(id_jobentry, "arg_from_previous"); execPerRow = rep.getJobEntryAttributeBoolean(id_jobentry, "exec_per_row"); setLogfile = rep.getJobEntryAttributeBoolean(id_jobentry, "set_logfile"); setAppendLogfile = rep.getJobEntryAttributeBoolean(id_jobentry, "set_append_logfile"); addDate = rep.getJobEntryAttributeBoolean(id_jobentry, "add_date"); addTime = rep.getJobEntryAttributeBoolean(id_jobentry, "add_time"); logfile = rep.getJobEntryAttributeString(id_jobentry, "logfile"); logext = rep.getJobEntryAttributeString(id_jobentry, "logext"); logFileLevel = LogLevel.getLogLevelForCode(rep.getJobEntryAttributeString(id_jobentry, "loglevel")); insertScript = rep.getJobEntryAttributeBoolean(id_jobentry, "insertScript"); script = rep.getJobEntryAttributeString(id_jobentry, "script"); // How many arguments? int argnr = rep.countNrJobEntryAttributes(id_jobentry, "argument"); arguments = new String[argnr]; // Read them all... for (int a = 0; a < argnr; a++) { arguments[a] = rep.getJobEntryAttributeString(id_jobentry, a, "argument"); } } catch (KettleDatabaseException dbe) { throw new KettleException( "Unable to load job entry of type 'shell' from the repository with id_jobentry=" + id_jobentry, dbe); } }
private void getInfo(JobEntryTrans jet) throws KettleException { jet.setName(wName.getText()); if (rep != null) { specificationMethod = ObjectLocationSpecificationMethod.REPOSITORY_BY_NAME; } else { specificationMethod = ObjectLocationSpecificationMethod.FILENAME; } jet.setSpecificationMethod(specificationMethod); switch (specificationMethod) { case FILENAME: jet.setFileName(wPath.getText()); if (jet.getFilename().isEmpty()) { throw new KettleException( BaseMessages.getString(PKG, "JobTrans.Dialog.Exception.NoValidMappingDetailsFound")); } jet.setDirectory(null); jet.setTransname(null); jet.setTransObjectId(null); break; case REPOSITORY_BY_NAME: String transPath = wPath.getText(); String transName = transPath; String directory = ""; int index = transPath.lastIndexOf("/"); if (index != -1) { transName = transPath.substring(index + 1); directory = transPath.substring(0, index); } jet.setDirectory(directory); if (jet.getDirectory().isEmpty()) { throw new KettleException( BaseMessages.getString( PKG, "JobTrans.Dialog.Exception.UnableToFindRepositoryDirectory")); } jet.setTransname(transName); jet.setFileName(null); jet.setTransObjectId(null); break; default: break; } int nritems = wFields.nrNonEmpty(); int nr = 0; for (int i = 0; i < nritems; i++) { String arg = wFields.getNonEmpty(i).getText(1); if (arg != null && arg.length() != 0) { nr++; } } jet.arguments = new String[nr]; nr = 0; for (int i = 0; i < nritems; i++) { String arg = wFields.getNonEmpty(i).getText(1); if (arg != null && arg.length() != 0) { jet.arguments[nr] = arg; nr++; } } // Do the parameters nritems = wParameters.nrNonEmpty(); nr = 0; for (int i = 0; i < nritems; i++) { String param = wParameters.getNonEmpty(i).getText(1); if (param != null && param.length() != 0) { nr++; } } jet.parameters = new String[nr]; jet.parameterFieldNames = new String[nr]; jet.parameterValues = new String[nr]; nr = 0; for (int i = 0; i < nritems; i++) { String param = wParameters.getNonEmpty(i).getText(1); String fieldName = wParameters.getNonEmpty(i).getText(2); String value = wParameters.getNonEmpty(i).getText(3); jet.parameters[nr] = param; if (!Utils.isEmpty(Const.trim(fieldName))) { jet.parameterFieldNames[nr] = fieldName; } else { jet.parameterFieldNames[nr] = ""; } if (!Utils.isEmpty(Const.trim(value))) { jet.parameterValues[nr] = value; } else { jet.parameterValues[nr] = ""; } nr++; } jet.setPassingAllParameters(wPassParams.getSelection()); jet.logfile = wLogfile.getText(); jet.logext = wLogext.getText(); if (wLoglevel.getSelectionIndex() >= 0) { jet.logFileLevel = LogLevel.values()[wLoglevel.getSelectionIndex()]; } else { jet.logFileLevel = LogLevel.BASIC; } jet.argFromPrevious = wPrevious.getSelection(); jet.paramsFromPrevious = wPrevToParams.getSelection(); jet.execPerRow = wEveryRow.getSelection(); jet.setLogfile = wSetLogfile.getSelection(); jet.addDate = wAddDate.getSelection(); jet.addTime = wAddTime.getSelection(); jet.clearResultRows = wClearRows.getSelection(); jet.clearResultFiles = wClearFiles.getSelection(); jet.setClustering(wCluster.getSelection()); jet.setLoggingRemoteWork(wLogRemoteWork.getSelection()); jet.createParentFolder = wCreateParentFolder.getSelection(); jet.setRemoteSlaveServerName(wSlaveServer.getText()); jet.setAppendLogfile = wAppendLogfile.getSelection(); jet.setWaitingToFinish(wWaitingToFinish.getSelection()); jet.setFollowingAbortRemotely(wFollowingAbortRemotely.getSelection()); }
protected void optionsSectionControls() { wSafeMode = new Button(gDetails, SWT.CHECK); wSafeMode.setText( BaseMessages.getString(PKG, "JobExecutionConfigurationDialog.SafeMode.Label")); wSafeMode.setToolTipText( BaseMessages.getString(PKG, "JobExecutionConfigurationDialog.SafeMode.Tooltip")); props.setLook(wSafeMode); FormData fdSafeMode = new FormData(); fdSafeMode.right = new FormAttachment(0, 186); fdSafeMode.top = new FormAttachment(0, 30); fdSafeMode.left = new FormAttachment(0, 10); wSafeMode.setLayoutData(fdSafeMode); wGatherMetrics = new Button(gDetails, SWT.CHECK); wGatherMetrics.setText( BaseMessages.getString(PKG, "JobExecutionConfigurationDialog.GatherMetrics.Label")); wGatherMetrics.setToolTipText( BaseMessages.getString(PKG, "JobExecutionConfigurationDialog.GatherMetrics.Tooltip")); props.setLook(wGatherMetrics); FormData fdGatherMetrics = new FormData(); fdGatherMetrics.right = new FormAttachment(0, 230); fdGatherMetrics.top = new FormAttachment(0, 55); fdGatherMetrics.left = new FormAttachment(0, 10); wGatherMetrics.setLayoutData(fdGatherMetrics); wClearLog = new Button(gDetails, SWT.CHECK); wClearLog.setText( BaseMessages.getString(PKG, "JobExecutionConfigurationDialog.ClearLog.Label")); wClearLog.setToolTipText( BaseMessages.getString(PKG, "JobExecutionConfigurationDialog.ClearLog.Tooltip")); props.setLook(wClearLog); FormData fdClearLog = new FormData(); fdClearLog.right = new FormAttachment(0, 200); fdClearLog.top = new FormAttachment(0, 5); fdClearLog.left = new FormAttachment(0, 10); wClearLog.setLayoutData(fdClearLog); wlLogLevel = new Label(gDetails, SWT.RIGHT); props.setLook(wlLogLevel); wlLogLevel.setText( BaseMessages.getString(PKG, "JobExecutionConfigurationDialog.LogLevel.Label")); wlLogLevel.setToolTipText( BaseMessages.getString(PKG, "JobExecutionConfigurationDialog.LogLevel.Tooltip")); FormData fdlLogLevel = new FormData(); fdlLogLevel.right = new FormAttachment(0, 333); fdlLogLevel.top = new FormAttachment(0, 7); fdlLogLevel.left = new FormAttachment(0, 260); wlLogLevel.setLayoutData(fdlLogLevel); wLogLevel = new CCombo(gDetails, SWT.READ_ONLY | SWT.BORDER); wLogLevel.setToolTipText( BaseMessages.getString(PKG, "JobExecutionConfigurationDialog.LogLevel.Tooltip")); props.setLook(wLogLevel); FormData fdLogLevel = new FormData(); fdLogLevel.left = new FormAttachment(wlLogLevel, 6); fdLogLevel.width = 200; if (Const.isOSX()) { fdLogLevel.top = new FormAttachment(wClearLog, 2, SWT.TOP); } else { fdLogLevel.top = new FormAttachment(wClearLog, -2, SWT.TOP); } fdLogLevel.right = new FormAttachment(0, 500); wLogLevel.setLayoutData(fdLogLevel); wLogLevel.setItems(LogLevel.getLogLevelDescriptions()); wStartCopy = new CCombo(gDetails, SWT.READ_ONLY | SWT.BORDER); props.setLook(wStartCopy); wStartCopy.setToolTipText( BaseMessages.getString(PKG, "JobExecutionConfigurationDialog.StartCopy.Tooltip")); FormData fd_startJobCombo = new FormData(); fd_startJobCombo.right = new FormAttachment(wLogLevel, 0, SWT.RIGHT); if (Const.isOSX()) { fd_startJobCombo.top = new FormAttachment(wLogLevel, 8); } else { fd_startJobCombo.top = new FormAttachment(wLogLevel, 10); } wStartCopy.setLayoutData(fd_startJobCombo); JobMeta jobMeta = (JobMeta) super.abstractMeta; String[] names = new String[jobMeta.getJobCopies().size()]; for (int i = 0; i < names.length; i++) { JobEntryCopy copy = jobMeta.getJobCopies().get(i); names[i] = getJobEntryCopyName(copy); } wStartCopy.setItems(names); Label lblStartJob = new Label(gDetails, SWT.NONE); props.setLook(lblStartJob); fd_startJobCombo.left = new FormAttachment(lblStartJob, 6); FormData fd_lblStartJob = new FormData(); if (Const.isOSX()) { fd_lblStartJob.top = new FormAttachment(wlLogLevel, 8); } else { fd_lblStartJob.top = new FormAttachment(wlLogLevel, 18); } fd_lblStartJob.right = new FormAttachment(wlLogLevel, 0, SWT.RIGHT); lblStartJob.setLayoutData(fd_lblStartJob); lblStartJob.setText( BaseMessages.getString(PKG, "JobExecutionConfigurationDialog.StartCopy.Label")); lblStartJob.setToolTipText( BaseMessages.getString(PKG, "JobExecutionConfigurationDialog.StartCopy.Tooltip")); }
public JobExecutionConfiguration(Node trecNode) throws KettleException { this(); executingLocally = "Y".equalsIgnoreCase(XMLHandler.getTagValue(trecNode, "exec_local")); executingRemotely = "Y".equalsIgnoreCase(XMLHandler.getTagValue(trecNode, "exec_remote")); Node remoteHostNode = XMLHandler.getSubNode(trecNode, SlaveServer.XML_TAG); if (remoteHostNode != null) { remoteServer = new SlaveServer(remoteHostNode); } passingExport = "Y".equalsIgnoreCase(XMLHandler.getTagValue(trecNode, "pass_export")); expandingRemoteJob = "Y".equalsIgnoreCase(XMLHandler.getTagValue(trecNode, "expand_remote_job")); // Read the variables... // Node varsNode = XMLHandler.getSubNode(trecNode, "variables"); int nrVariables = XMLHandler.countNodes(varsNode, "variable"); for (int i = 0; i < nrVariables; i++) { Node argNode = XMLHandler.getSubNodeByNr(varsNode, "variable", i); String name = XMLHandler.getTagValue(argNode, "name"); String value = XMLHandler.getTagValue(argNode, "value"); if (!Utils.isEmpty(name) && !Utils.isEmpty(value)) { variables.put(name, value); } } // Read the arguments... // Node argsNode = XMLHandler.getSubNode(trecNode, "arguments"); int nrArguments = XMLHandler.countNodes(argsNode, "argument"); for (int i = 0; i < nrArguments; i++) { Node argNode = XMLHandler.getSubNodeByNr(argsNode, "argument", i); String name = XMLHandler.getTagValue(argNode, "name"); String value = XMLHandler.getTagValue(argNode, "value"); if (!Utils.isEmpty(name) && !Utils.isEmpty(value)) { arguments.put(name, value); } } // Read the parameters... // Node parmsNode = XMLHandler.getSubNode(trecNode, "parameters"); int nrParams = XMLHandler.countNodes(parmsNode, "parameter"); for (int i = 0; i < nrParams; i++) { Node parmNode = XMLHandler.getSubNodeByNr(parmsNode, "parameter", i); String name = XMLHandler.getTagValue(parmNode, "name"); String value = XMLHandler.getTagValue(parmNode, "value"); if (!Utils.isEmpty(name)) { params.put(name, value); } } replayDate = XMLHandler.stringToDate(XMLHandler.getTagValue(trecNode, "replay_date")); safeModeEnabled = "Y".equalsIgnoreCase(XMLHandler.getTagValue(trecNode, "safe_mode")); logLevel = LogLevel.getLogLevelForCode(XMLHandler.getTagValue(trecNode, "log_level")); clearingLog = "Y".equalsIgnoreCase(XMLHandler.getTagValue(trecNode, "clear_log")); startCopyName = XMLHandler.getTagValue(trecNode, "start_copy_name"); startCopyNr = Const.toInt(XMLHandler.getTagValue(trecNode, "start_copy_nr"), 0); gatheringMetrics = "Y".equalsIgnoreCase(XMLHandler.getTagValue(trecNode, "gather_metrics")); String sPassedBatchId = XMLHandler.getTagValue(trecNode, "passedBatchId"); if (!StringUtils.isEmpty(sPassedBatchId)) { passedBatchId = Long.parseLong(sPassedBatchId); } Node resultNode = XMLHandler.getSubNode(trecNode, Result.XML_TAG); if (resultNode != null) { try { previousResult = new Result(resultNode); } catch (KettleException e) { throw new KettleException("Unable to hydrate previous result", e); } } // Try to get a handle to the repository from here... // Node repNode = XMLHandler.getSubNode(trecNode, "repository"); if (repNode != null) { String repositoryName = XMLHandler.getTagValue(repNode, "name"); String username = XMLHandler.getTagValue(repNode, "login"); String password = Encr.decryptPassword(XMLHandler.getTagValue(repNode, "password")); connectRepository(repositoryName, username, password); } }
public String getXML() throws IOException { StringBuilder xml = new StringBuilder(160); xml.append(" <" + XML_TAG + ">").append(Const.CR); xml.append(" ").append(XMLHandler.addTagValue("exec_local", executingLocally)); xml.append(" ").append(XMLHandler.addTagValue("exec_remote", executingRemotely)); if (remoteServer != null) { xml.append(" ").append(remoteServer.getXML()).append(Const.CR); } xml.append(" ").append(XMLHandler.addTagValue("pass_export", passingExport)); // Serialize the parameters... // xml.append(" <parameters>").append(Const.CR); List<String> paramNames = new ArrayList<String>(params.keySet()); Collections.sort(paramNames); for (String name : paramNames) { String value = params.get(name); xml.append(" <parameter>"); xml.append(XMLHandler.addTagValue("name", name, false)); xml.append(XMLHandler.addTagValue("value", value, false)); xml.append("</parameter>").append(Const.CR); } xml.append(" </parameters>").append(Const.CR); // Serialize the variables... // xml.append(" <variables>").append(Const.CR); List<String> variableNames = new ArrayList<String>(variables.keySet()); Collections.sort(variableNames); for (String name : variableNames) { String value = variables.get(name); xml.append(" <variable>"); xml.append(XMLHandler.addTagValue("name", name, false)); xml.append(XMLHandler.addTagValue("value", value, false)); xml.append("</variable>").append(Const.CR); } xml.append(" </variables>").append(Const.CR); // Serialize the variables... // xml.append(" <arguments>").append(Const.CR); List<String> argumentNames = new ArrayList<String>(arguments.keySet()); Collections.sort(argumentNames); for (String name : argumentNames) { String value = arguments.get(name); xml.append(" <argument>"); xml.append(XMLHandler.addTagValue("name", name, false)); xml.append(XMLHandler.addTagValue("value", value, false)); xml.append("</argument>").append(Const.CR); } xml.append(" </arguments>").append(Const.CR); xml.append(" ").append(XMLHandler.addTagValue("replay_date", replayDate)); xml.append(" ").append(XMLHandler.addTagValue("safe_mode", safeModeEnabled)); xml.append(" ").append(XMLHandler.addTagValue("log_level", logLevel.getCode())); xml.append(" ").append(XMLHandler.addTagValue("clear_log", clearingLog)); xml.append(" ").append(XMLHandler.addTagValue("start_copy_name", startCopyName)); xml.append(" ").append(XMLHandler.addTagValue("start_copy_nr", startCopyNr)); xml.append(" ").append(XMLHandler.addTagValue("gather_metrics", gatheringMetrics)); xml.append(" ").append(XMLHandler.addTagValue("expand_remote_job", expandingRemoteJob)); if (passedBatchId != null) { xml.append(" ").append(XMLHandler.addTagValue("passedBatchId", passedBatchId)); } // The source rows... // if (previousResult != null) { xml.append(previousResult.getXML()); } // Send the repository name and user to the remote site... // if (repository != null) { xml.append(XMLHandler.openTag("repository")); xml.append(XMLHandler.addTagValue("name", repository.getName())); // File base repositories doesn't have user info if (repository.getUserInfo() != null) { xml.append(XMLHandler.addTagValue("login", repository.getUserInfo().getLogin())); xml.append( XMLHandler.addTagValue( "password", Encr.encryptPassword(repository.getUserInfo().getPassword()))); } xml.append(XMLHandler.closeTag("repository")); } xml.append("</" + XML_TAG + ">").append(Const.CR); return xml.toString(); }