0001: /*
0002: * Copyright 2006 Pentaho Corporation. All rights reserved.
0003: * This software was developed by Pentaho Corporation and is provided under the terms
0004: * of the Mozilla Public License, Version 1.1, or any later version. You may not use
0005: * this file except in compliance with the license. If you need a copy of the license,
0006: * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
0007: * BI Platform. The Initial Developer is Pentaho Corporation.
0008: *
0009: * Software distributed under the Mozilla Public License is distributed on an "AS IS"
0010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
0011: * the license for the specific language governing your rights and limitations.
0012: *
0013: * @created Jul 12, 2005
0014: * @author James Dixon, Angelo Rodriguez, Steven Barkdull
0015: *
0016: */
0017:
0018: package org.pentaho.ui.servlet;
0019:
0020: import java.io.ByteArrayInputStream;
0021: import java.io.ByteArrayOutputStream;
0022: import java.io.IOException;
0023: import java.io.InputStream;
0024: import java.io.OutputStream;
0025: import java.util.ArrayList;
0026: import java.util.Enumeration;
0027: import java.util.HashMap;
0028: import java.util.Iterator;
0029: import java.util.LinkedList;
0030: import java.util.List;
0031: import java.util.Locale;
0032: import java.util.Map;
0033: import java.util.TreeSet;
0034: import java.util.regex.Matcher;
0035: import java.util.regex.Pattern;
0036:
0037: import javax.servlet.ServletException;
0038: import javax.servlet.http.HttpServletRequest;
0039: import javax.servlet.http.HttpServletResponse;
0040:
0041: import org.apache.commons.lang.StringEscapeUtils;
0042: import org.apache.commons.lang.StringUtils;
0043: import org.apache.commons.logging.Log;
0044: import org.apache.commons.logging.LogFactory;
0045: import org.dom4j.Attribute;
0046: import org.dom4j.Document;
0047: import org.dom4j.DocumentHelper;
0048: import org.dom4j.Element;
0049: import org.dom4j.Node;
0050: import org.dom4j.dom.DOMDocumentFactory;
0051: import org.dom4j.io.OutputFormat;
0052: import org.dom4j.io.XMLWriter;
0053: import org.pentaho.core.cache.CacheManager;
0054: import org.pentaho.commons.connection.IPentahoResultSet;
0055: import org.pentaho.core.repository.ISolutionRepository;
0056: import org.pentaho.core.repository.SolutionRepositoryBase;
0057: import org.pentaho.core.runtime.IActionParameter;
0058: import org.pentaho.core.runtime.IRuntimeContext;
0059: import org.pentaho.core.session.IPentahoSession;
0060: import org.pentaho.core.solution.HttpRequestParameterProvider;
0061: import org.pentaho.core.solution.IParameterProvider;
0062: import org.pentaho.core.solution.ISolutionEngine;
0063: import org.pentaho.core.solution.ISolutionFile;
0064: import org.pentaho.core.solution.SimpleOutputHandler;
0065: import org.pentaho.core.solution.SimpleParameterProvider;
0066: import org.pentaho.core.solution.SolutionReposUtil;
0067: import org.pentaho.core.system.PentahoSystem;
0068: import org.pentaho.core.system.StandaloneApplicationContext;
0069: import org.pentaho.core.ui.IPentahoUrlFactory;
0070: import org.pentaho.core.ui.SimpleUrlFactory;
0071: import org.pentaho.core.util.CleanXmlHelper;
0072: import org.pentaho.core.util.MimeHelper;
0073: import org.pentaho.core.util.SoapUtil;
0074: import org.pentaho.core.util.UIUtil;
0075: import org.pentaho.core.util.XmlHelper;
0076: import org.pentaho.jfreereport.castormodel.jfree.types.PageFormats;
0077: import org.pentaho.jfreereport.castormodel.reportspec.Field;
0078: import org.pentaho.jfreereport.castormodel.reportspec.ReportSpec;
0079: import org.pentaho.jfreereport.wizard.utility.CastorUtility;
0080: import org.pentaho.jfreereport.wizard.utility.report.ReportGenerationUtility;
0081: import org.pentaho.jfreereport.wizard.utility.report.ReportSpecUtility;
0082: import org.pentaho.messages.Messages;
0083: import org.pentaho.messages.util.LocaleHelper;
0084: import org.pentaho.plugin.mql.MetadataPublisher;
0085: import org.pentaho.pms.core.exception.PentahoMetadataException;
0086: import org.pentaho.pms.factory.CwmSchemaFactoryInterface;
0087: import org.pentaho.pms.mql.MQLQuery;
0088: import org.pentaho.pms.mql.MQLQueryFactory;
0089: import org.pentaho.pms.schema.BusinessColumn;
0090: import org.pentaho.pms.schema.BusinessModel;
0091: import org.pentaho.pms.schema.concept.ConceptInterface;
0092: import org.pentaho.pms.schema.concept.ConceptPropertyInterface;
0093: import org.pentaho.pms.schema.concept.DefaultPropertyID;
0094: import org.pentaho.pms.schema.concept.types.alignment.AlignmentSettings;
0095: import org.pentaho.pms.schema.concept.types.color.ColorSettings;
0096: import org.pentaho.pms.schema.concept.types.datatype.DataTypeSettings;
0097: import org.pentaho.pms.schema.concept.types.font.FontSettings;
0098: import org.pentaho.ui.component.PMDUIComponent;
0099: import org.pentaho.util.StringUtil;
0100: import org.pentaho.util.logging.ILogger;
0101:
0102: /*
0103: * Refactoring notes:
0104: * Break out code into facade classes for SolutionRepository, WaqrRepository
0105: * For each of the methods in the switch statement in the dispatch method,
0106: * create a method that takes the parameter provider. These methods will
0107: * break the parameters out of the parameter provider, and call methods by
0108: * the same name
0109: */
0110: /**
0111: * Servlet Class
0112: *
0113: * web.servlet name="ViewAction" display-name="Name for ViewAction" description="Description for ViewAction" web.servlet-mapping url-pattern="/ViewAction" web.servlet-init-param name="A parameter" value="A value"
0114: */
0115: public class AdhocWebService extends ServletBase {
0116:
0117: /**
0118: *
0119: */
0120: private static final long serialVersionUID = -2011812808062152707L;
0121:
0122: private static final Log logger = LogFactory
0123: .getLog(AdhocWebService.class);
0124:
0125: private static final String WAQR_EXTENSION = "waqr"; //$NON-NLS-1$
0126: private static final Field DEFAULT_FIELD_PROPS = new Field();
0127:
0128: // for the string bart.waqr.xreportspec, return "bart"
0129: private static final String RE_GET_BASE_WAQR_FILENAME = "^(.*)\\.waqr\\.xreportspec$"; //$NON-NLS-1$
0130: private static final Pattern BASE_WAQR_FILENAME_PATTERN = Pattern
0131: .compile(AdhocWebService.RE_GET_BASE_WAQR_FILENAME);
0132:
0133: private static String SOLUTION_NAVIGATION_DOCUMENT_MAP = "AdhocWebService.SOLUTION_NAVIGATION_DOCUMENT_MAP"; //$NON-NLS-1$
0134: private static String FULL_SOLUTION_DOC = "AdhocWebService.FULL_SOLUTION_DOC"; //$NON-NLS-1$
0135: // attributes received from the waqr UI that have their values set to "not-set"
0136: // will be overridden by the metadata, the template, or the default value
0137: // see the javascript variable WaqrWizard.NOT_SET_VALUE for the client instance of this value
0138: private static final String NOT_SET_VALUE = "not-set"; //$NON-NLS-1$
0139: private static String METADATA_PROPERTY_ID_VERTICAL_ALIGNMENT = "vertical-alignment"; //$NON-NLS-1$
0140: private static final String WAQR_REPOSITORY_PATH = "/system/waqr"; //$NON-NLS-1$
0141:
0142: public Log getLogger() {
0143: return logger;
0144: }
0145:
0146: /**
0147: *
0148: */
0149: public AdhocWebService() {
0150: super ();
0151: }
0152:
0153: public String getPayloadAsString(HttpServletRequest request)
0154: throws IOException {
0155: InputStream is = request.getInputStream();
0156: ByteArrayOutputStream os = new ByteArrayOutputStream();
0157: String content = null;
0158:
0159: byte buffer[] = new byte[2048];
0160: int b = is.read(buffer);
0161: while (b > 0) {
0162: os.write(buffer, 0, b);
0163: b = is.read(buffer);
0164: }
0165: content = os.toString(LocaleHelper.getSystemEncoding());
0166:
0167: return content;
0168: }
0169:
0170: protected void doGet(HttpServletRequest request,
0171: HttpServletResponse response) throws ServletException,
0172: IOException {
0173:
0174: PentahoSystem.systemEntryPoint();
0175: OutputStream outputStream = response.getOutputStream();
0176: try {
0177:
0178: boolean isAjax = "true".equals(request.getParameter("ajax")); //$NON-NLS-1$ //$NON-NLS-2$
0179: String solutionName = request.getParameter("solution"); //$NON-NLS-1$
0180: String actionPath = request.getParameter("path"); //$NON-NLS-1$
0181: String actionName = request.getParameter("action"); //$NON-NLS-1$
0182: String component = request.getParameter("component"); //$NON-NLS-1$
0183: String content = null;
0184: try {
0185: content = getPayloadAsString(request);
0186: } catch (IOException ioEx) {
0187: String msg = Messages
0188: .getErrorString("AdhocWebService.ERROR_0006_FAILED_TO_GET_PAYLOAD_FROM_REQUEST"); //$NON-NLS-1$
0189: error(msg, ioEx);
0190: writeStringAsSoapResponse(
0191: outputStream,
0192: AdhocWebService.getErrorXml(msg
0193: + " " + ioEx.getLocalizedMessage()), true); //$NON-NLS-1$
0194: }
0195: IParameterProvider parameterProvider = null;
0196: HashMap parameters = new HashMap();
0197:
0198: if (!StringUtils.isEmpty(content)) {
0199: Document doc = org.pentaho.core.util.XmlHelper
0200: .getDocFromString(content);
0201: List parameterNodes = doc
0202: .selectNodes("//SOAP-ENV:Body/*/*"); //$NON-NLS-1$
0203: for (int i = 0; i < parameterNodes.size(); i++) {
0204: Node parameterNode = (Node) parameterNodes.get(i);
0205: String parameterName = parameterNode.getName();
0206: String parameterValue = parameterNode.getText();
0207: // String type = parameterNode.selectSingleNode( "@type" );
0208: // if( "xml-data".equalsIgnoreCase( ) )
0209: if ("action".equals(parameterName)) { //$NON-NLS-1$
0210: PentahoSystem.ActionInfo info = PentahoSystem
0211: .parseActionString(parameterValue);
0212: solutionName = info.getSolutionName();
0213: actionPath = info.getPath();
0214: actionName = info.getActionName();
0215: parameters.put("solution", solutionName); //$NON-NLS-1$
0216: parameters.put("path", actionPath); //$NON-NLS-1$
0217: parameters.put("name", actionName); //$NON-NLS-1$
0218: } else if ("component".equals(parameterName)) { //$NON-NLS-1$
0219: component = parameterValue;
0220: } else {
0221: parameters.put(parameterName, parameterValue);
0222: }
0223: }
0224: parameterProvider = new SimpleParameterProvider(
0225: parameters);
0226: } else {
0227: parameterProvider = new HttpRequestParameterProvider(
0228: request);
0229: }
0230:
0231: if (!"generatePreview".equals(component)) { //$NON-NLS-1$
0232: response.setContentType("text/xml"); //$NON-NLS-1$
0233: response.setCharacterEncoding(LocaleHelper
0234: .getSystemEncoding());
0235: }
0236:
0237: // PentahoHttpSession userSession = new PentahoHttpSession(
0238: // request.getRemoteUser(), request.getSession(),
0239: // request.getLocale() );
0240: IPentahoSession userSession = getPentahoSession(request);
0241:
0242: // send the header of the message to prevent time-outs while we are working
0243: response.setHeader("expires", "0"); //$NON-NLS-1$ //$NON-NLS-2$
0244:
0245: dispatch(request, response, component, parameterProvider,
0246: outputStream, userSession, isAjax);
0247:
0248: } catch (IOException ioEx) {
0249: String msg = Messages
0250: .getErrorString("HttpWebService.ERROR_0001_ERROR_DURING_WEB_SERVICE"); //$NON-NLS-1$
0251: error(msg, ioEx);
0252: writeStringAsSoapResponse(outputStream, AdhocWebService
0253: .getErrorXml(msg), true);
0254: } catch (AdhocWebServiceException ex) {
0255: String msg = ex.getLocalizedMessage();
0256: error(msg, ex);
0257: writeStringAsSoapResponse(outputStream, AdhocWebService
0258: .getErrorXml(msg), true);
0259: } catch (PentahoMetadataException ex) {
0260: String msg = ex.getLocalizedMessage();
0261: error(msg, ex);
0262: writeStringAsSoapResponse(outputStream, AdhocWebService
0263: .getErrorXml(msg), true);
0264: } finally {
0265: PentahoSystem.systemExitPoint();
0266: }
0267: if (debug) {
0268: debug(Messages
0269: .getString("HttpWebService.DEBUG_WEB_SERVICE_END")); //$NON-NLS-1$
0270: }
0271: }
0272:
0273: protected void dispatch(HttpServletRequest request,
0274: HttpServletResponse response, String component,
0275: IParameterProvider parameterProvider,
0276: OutputStream outputStream, IPentahoSession userSession,
0277: boolean isAjax) throws IOException,
0278: AdhocWebServiceException, PentahoMetadataException {
0279: if ("listbusinessmodels".equals(component)) { //$NON-NLS-1$
0280: listBusinessModels(parameterProvider, outputStream,
0281: userSession, isAjax);
0282: } else if ("getbusinessmodel".equals(component)) { //$NON-NLS-1$
0283: getBusinessModel(parameterProvider, outputStream,
0284: userSession, isAjax);
0285: } else if ("generatePreview".equals(component)) { //$NON-NLS-1$
0286: generatePreview(request, response, parameterProvider,
0287: outputStream, userSession, isAjax);
0288:
0289: } else if ("saveFile".equals(component)) { //$NON-NLS-1$
0290: saveFile(parameterProvider, outputStream, userSession,
0291: isAjax);
0292: } else if ("searchTable".equals(component)) { //$NON-NLS-1$
0293: searchTable(parameterProvider, outputStream, userSession,
0294: isAjax);
0295:
0296: } else if ("getWaqrReportSpecDoc".equals(component)) { //$NON-NLS-1$
0297: getWaqrReportSpecDoc(parameterProvider, outputStream,
0298: userSession, isAjax);
0299:
0300: } else if ("getTemplateReportSpec".equals(component)) { //$NON-NLS-1$
0301: getTemplateReportSpec(parameterProvider, outputStream,
0302: userSession, isAjax);
0303:
0304: } else if ("getSolutionRepositoryDoc".equals(component)) { //$NON-NLS-1$
0305: String path = parameterProvider.getStringParameter(
0306: "path", null); //$NON-NLS-1$
0307: //path = StringUtils.isEmpty( path ) ? null : path;
0308: String solutionName = parameterProvider.getStringParameter(
0309: "solution", null); //$NON-NLS-1$
0310: //solutionName = StringUtils.isEmpty( solutionName ) ? null : solutionName;
0311: Document doc = getSolutionRepositoryDoc(solutionName, path,
0312: userSession);
0313: writeDocumentAsSoapResponse(outputStream, doc, isAjax);
0314:
0315: } else if ("getWaqrRepositoryDoc".equals(component)) { //$NON-NLS-1$
0316: String folderPath = parameterProvider.getStringParameter(
0317: "folderPath", null); //$NON-NLS-1$
0318: Document doc = getWaqrRepositoryDoc(folderPath, userSession);
0319: writeDocumentAsSoapResponse(outputStream, doc, isAjax);
0320:
0321: } else if ("getWaqrRepositoryIndexDoc".equals(component)) { //$NON-NLS-1$
0322: getWaqrRepositoryIndexDoc(parameterProvider, outputStream,
0323: userSession, isAjax);
0324: } else if ("deleteWaqrReport".equals(component)) { //$NON-NLS-1$
0325: deleteWaqrReport(parameterProvider, outputStream,
0326: userSession, isAjax);
0327: } else if ("getJFreePaperSizes".equals(component)) { //$NON-NLS-1$
0328: getJFreePaperSizes(parameterProvider, outputStream,
0329: userSession, isAjax);
0330: } else {
0331: throw new RuntimeException(
0332: Messages
0333: .getErrorString(
0334: "HttpWebService.UNRECOGNIZED_COMPONENT_REQUEST", component)); //$NON-NLS-1$
0335: }
0336: }
0337:
0338: protected void doPost(HttpServletRequest request,
0339: HttpServletResponse response) throws ServletException,
0340: IOException {
0341:
0342: doGet(request, response);
0343:
0344: }
0345:
0346: public void writeDocumentAsSoapResponse(OutputStream outputStream,
0347: Document doc, boolean isAjax) throws IOException {
0348: writeStringAsSoapResponse(outputStream, doc.asXML(), isAjax);
0349: }
0350:
0351: public void writeDocumentAsSoapResponse(OutputStream outputStream,
0352: Document doc) throws IOException {
0353: writeStringAsSoapResponse(outputStream, doc.asXML(), false);
0354: }
0355:
0356: public void writeStringAsSoapResponse(OutputStream outputStream,
0357: String doc) throws IOException {
0358: writeStringAsSoapResponse(outputStream, doc, false);
0359: }
0360:
0361: public void writeStringAsSoapResponse(OutputStream outputStream,
0362: String doc, boolean isAjax) throws IOException {
0363: int headerPos = doc.indexOf("?>"); //$NON-NLS-1$
0364: if (headerPos > -1) {
0365: doc = doc.substring(headerPos + 2);
0366: }
0367: if (!isAjax) {
0368: outputStream.write(SoapUtil.getSoapHeader().getBytes(
0369: LocaleHelper.getSystemEncoding()));
0370: outputStream.write(SoapUtil.openSoapResponse().getBytes(
0371: LocaleHelper.getSystemEncoding()));
0372: outputStream
0373: .write("<content>".getBytes(LocaleHelper.getSystemEncoding())); //$NON-NLS-1$
0374: }
0375: outputStream.write(doc.getBytes(LocaleHelper
0376: .getSystemEncoding()));
0377: if (!isAjax) {
0378: outputStream
0379: .write("</content>".getBytes(LocaleHelper.getSystemEncoding())); //$NON-NLS-1$
0380: outputStream.write(SoapUtil.closeSoapResponse().getBytes(
0381: LocaleHelper.getSystemEncoding()));
0382: outputStream.write(SoapUtil.getSoapFooter().getBytes(
0383: LocaleHelper.getSystemEncoding()));
0384: }
0385: }
0386:
0387: /**
0388: * Creates an XML string containing a list of the supported JFree paper sizes.
0389: * The attribute accessed by the XPath: /pageFormats/pageFormat[@name] contains the
0390: * friendly name of the paper size
0391: * The attribute accessed by the XPath: /pageFormats/pageFormat[@name] contains the
0392: * name of the paper size used by the JFree engine.
0393: * The XML String is written to the outputStream, which is typically the response.outputStream.
0394: *
0395: * @param parameterProvider
0396: * @param outputStream
0397: * @param userSession
0398: * @param isAjax
0399: * @throws IOException
0400: */
0401: private void getJFreePaperSizes(
0402: IParameterProvider parameterProvider,
0403: OutputStream outputStream, IPentahoSession userSession,
0404: boolean isAjax) throws IOException {
0405: StringBuffer xmlStr = new StringBuffer();
0406: Enumeration pageFormatsEnum = PageFormats.enumerate();
0407: xmlStr.append("<pageFormats>\n"); //$NON-NLS-1$
0408: while (pageFormatsEnum.hasMoreElements()) {
0409: PageFormats pf = (PageFormats) pageFormatsEnum
0410: .nextElement();
0411: xmlStr.append("\t<pageFormat name='" //$NON-NLS-1$
0412: + toFriendlyName(pf.toString())
0413: + "' value='" + pf.toString() + "'/>\n"); //$NON-NLS-1$//$NON-NLS-2$
0414: }
0415: xmlStr.append("</pageFormats>\n"); //$NON-NLS-1$
0416:
0417: writeStringAsSoapResponse(outputStream, xmlStr.toString(),
0418: isAjax);
0419: }
0420:
0421: // for a really friendly name, see:
0422: // http://bonsai.igalia.com/cgi-bin/bonsai/cvsblame.cgi?file=gtk%2B/gtk/paper_names.c&rev=&root=/var/publiccvs
0423: /**
0424: * Simply split the string on "_", and replace "_" with " ".
0425: * @param name String the string to convert into a "friendly" name
0426: * @return String the friendly name
0427: */
0428: private static String toFriendlyName(String name) {
0429: StringBuffer friendlyName = new StringBuffer();
0430: String[] components = name.split("_"); //$NON-NLS-1$
0431: for (int ii = 0; ii < components.length; ++ii) {
0432: String component = components[ii];
0433: friendlyName.append(component);
0434: if (ii < components.length - 1) {
0435: friendlyName.append(" "); //$NON-NLS-1$
0436: }
0437: }
0438: return friendlyName.toString();
0439: }
0440:
0441: private void generatePreview(HttpServletRequest request,
0442: HttpServletResponse response,
0443: IParameterProvider parameterProvider,
0444: OutputStream outputStream, IPentahoSession userSession,
0445: boolean isAjax) throws IOException {
0446: String outputType = parameterProvider.getStringParameter(
0447: "outputType", null); //$NON-NLS-1$
0448: String mimeType = MimeHelper
0449: .getMimeTypeFromExtension("." + outputType); //$NON-NLS-1$
0450: HttpMimeTypeListener listener = new HttpMimeTypeListener(
0451: request,
0452: response,
0453: Messages
0454: .getString("AdhocWebService.USER_REPORT_PREVIEW")); //$NON-NLS-1$
0455: listener.setMimeType(mimeType);
0456: String reportXML = parameterProvider.getStringParameter(
0457: "reportXml", null); //$NON-NLS-1$
0458: String templatePath = parameterProvider.getStringParameter(
0459: "templatePath", null); //$NON-NLS-1$
0460: try {
0461: createJFreeReportAsStream(reportXML, templatePath,
0462: outputType, outputStream, userSession, "debug",
0463: isAjax);
0464: } catch (Exception e) {
0465: response.setContentType("text/html"); //$NON-NLS-1$
0466: String msg = Messages
0467: .getString("AdhocWebService.ERROR_0012_FAILED_TO_GENERATE_PREVIEW"); //$NON-NLS-1$
0468: outputStream.write(getErrorHtml(e, msg).getBytes());
0469: error(msg, e);
0470: }
0471: }
0472:
0473: /**
0474: * TODO sbarkdull, method is poorly named and needs to be refactored, execution of action
0475: * resource should happen outside the method.
0476: *
0477: * @param reportXML
0478: * @param templatePath
0479: * @param outputType
0480: * @param outputStream OutputStream (output parameter) the preview report's output will be written
0481: * to this stream.
0482: * @param userSession
0483: * @param isAjax
0484: * @throws AdhocWebServiceException
0485: * @throws IOException
0486: * @throws PentahoMetadataException
0487: */
0488: private void createJFreeReportAsStream(String reportXML,
0489: String templatePath, String outputType,
0490: OutputStream outputStream, IPentahoSession userSession,
0491: String loggingLevel, boolean isAjax)
0492: throws AdhocWebServiceException, IOException,
0493: PentahoMetadataException {
0494:
0495: if (StringUtil.doesPathContainParentPathSegment(templatePath)) {
0496: String msg = Messages
0497: .getString("AdhocWebService.ERROR_0008_MISSING_OR_INVALID_REPORT_NAME"); //$NON-NLS-1$
0498: throw new AdhocWebServiceException(msg);
0499: }
0500:
0501: Document reportSpecDoc = XmlHelper.getDocFromString(reportXML);
0502: Element mqlNode = (Element) reportSpecDoc
0503: .selectSingleNode("/report-spec/query/mql"); //$NON-NLS-1$
0504: mqlNode.detach();
0505:
0506: Node reportNameNd = reportSpecDoc
0507: .selectSingleNode("/report-spec/report-name"); //$NON-NLS-1$
0508: String reportName = null != reportNameNd ? reportNameNd
0509: .getText() : ""; //$NON-NLS-1$
0510: Node reportDescNd = reportSpecDoc
0511: .selectSingleNode("/report-spec/report-desc"); //$NON-NLS-1$
0512: String reportDesc = reportDescNd.getText();
0513:
0514: String[] outputTypeList = { outputType };
0515:
0516: ISolutionRepository repository = PentahoSystem
0517: .getSolutionRepository(userSession);
0518:
0519: String xactionFilename = userSession.getId()
0520: + "_wqr_preview.xaction"; //$NON-NLS-1$
0521:
0522: ByteArrayOutputStream jfreeOutputStream = createJFreeReportDefinitionAsStream(
0523: reportXML, templatePath, mqlNode, repository,
0524: userSession);
0525:
0526: // create .xaction to run
0527: ByteArrayOutputStream xactionOutputStream = createMQLReportActionSequenceAsStream(
0528: reportName, reportDesc, mqlNode, outputTypeList,
0529: xactionFilename, jfreeOutputStream
0530: .toString(LocaleHelper.getSystemEncoding()),
0531: /*jfreeReportFileName*/null, loggingLevel, userSession);
0532: SimpleParameterProvider actionSequenceParameterProvider = new SimpleParameterProvider();
0533: actionSequenceParameterProvider
0534: .setParameter("type", outputType); //$NON-NLS-1$
0535: actionSequenceParameterProvider.setParameter(
0536: "logging-level", "error"); //$NON-NLS-1$ //$NON-NLS-2$
0537: actionSequenceParameterProvider.setParameter("level", "error"); //$NON-NLS-1$ //$NON-NLS-2$
0538: IRuntimeContext runtimeContext = executeActionSequence(
0539: xactionOutputStream.toString(LocaleHelper
0540: .getSystemEncoding()),
0541: "preview.xaction", actionSequenceParameterProvider, userSession, outputStream); //$NON-NLS-1$
0542:
0543: if (runtimeContext != null) {
0544: runtimeContext.dispose();
0545: }
0546: }
0547:
0548: // TODO, isn't there a utility class or something this method can be moved to?
0549: private static String getJFreeColorString(ColorSettings color) {
0550: if (color == null) {
0551: return "#FF0000"; //$NON-NLS-1$
0552: }
0553: String r = Integer.toHexString(color.getRed());
0554: if (r.length() == 1) {
0555: r = "0" + r; //$NON-NLS-1$
0556: }
0557: String g = Integer.toHexString(color.getGreen());
0558: if (g.length() == 1) {
0559: g = "0" + g; //$NON-NLS-1$
0560: }
0561: String b = Integer.toHexString(color.getBlue());
0562: if (b.length() == 1) {
0563: b = "0" + b; //$NON-NLS-1$
0564: }
0565: return "#" + r + g + b; //$NON-NLS-1$
0566: }
0567:
0568: public static void startup(String solutionRootPath, String baseURL) {
0569:
0570: LocaleHelper.setLocale(Locale.getDefault());
0571:
0572: PentahoSystem.loggingLevel = ILogger.ERROR;
0573:
0574: if (PentahoSystem.getApplicationContext() == null) {
0575:
0576: StandaloneApplicationContext applicationContext = new StandaloneApplicationContext(
0577: solutionRootPath, ""); //$NON-NLS-1$
0578:
0579: // set the base url assuming there is a running server on port 8080
0580: applicationContext.setBaseUrl(baseURL);
0581:
0582: // Setup simple-jndi for datasources
0583: System
0584: .setProperty(
0585: "java.naming.factory.initial", "org.osjava.sj.SimpleContextFactory"); //$NON-NLS-1$ //$NON-NLS-2$
0586: System
0587: .setProperty(
0588: "org.osjava.sj.root", solutionRootPath + "/system/simple-jndi"); //$NON-NLS-1$ //$NON-NLS-2$
0589: System.setProperty("org.osjava.sj.delimiter", "/"); //$NON-NLS-1$ //$NON-NLS-2$
0590: PentahoSystem.init(applicationContext);
0591: }
0592: }
0593:
0594: public static IRuntimeContext executeActionSequence(
0595: String xactionStr, String xActionName,
0596: IParameterProvider parameterProvider,
0597: IPentahoSession session, OutputStream outputStream) {
0598: IRuntimeContext runtimeContext = null;
0599:
0600: startup(null, null);
0601: List messages = new ArrayList();
0602: String instanceId = null;
0603: ISolutionEngine solutionEngine = PentahoSystem
0604: .getSolutionEngineInstance(session);
0605: solutionEngine.setLoggingLevel(ILogger.ERROR);
0606: solutionEngine.init(session);
0607: String baseUrl = PentahoSystem.getApplicationContext()
0608: .getBaseUrl();
0609: HashMap parameterProviderMap = new HashMap();
0610: parameterProviderMap.put(
0611: HttpRequestParameterProvider.SCOPE_REQUEST,
0612: parameterProvider);
0613: IPentahoUrlFactory urlFactory = new SimpleUrlFactory(baseUrl);
0614: SimpleOutputHandler outputHandler = new SimpleOutputHandler(
0615: outputStream, false);
0616:
0617: solutionEngine.setSession(session);
0618: runtimeContext = solutionEngine
0619: .execute(
0620: xactionStr,
0621: "preview.xaction", "Adhoc Reporting", false, true, instanceId, false, parameterProviderMap, outputHandler, null, urlFactory, messages); //$NON-NLS-1$ //$NON-NLS-2$
0622:
0623: return runtimeContext;
0624: }
0625:
0626: private static final Map METADATA_TYPE_TO_REPORT_SPEC_TYPE = new HashMap();
0627: static {
0628: METADATA_TYPE_TO_REPORT_SPEC_TYPE.put(new Integer(
0629: DataTypeSettings.DATA_TYPE_NUMERIC),
0630: ReportSpecUtility.NUMBER_FIELD);
0631: METADATA_TYPE_TO_REPORT_SPEC_TYPE.put(new Integer(
0632: DataTypeSettings.DATA_TYPE_DATE),
0633: ReportSpecUtility.DATE_FIELD);
0634: METADATA_TYPE_TO_REPORT_SPEC_TYPE.put(new Integer(
0635: DataTypeSettings.DATA_TYPE_STRING),
0636: ReportSpecUtility.STRING_FIELD);
0637: }
0638:
0639: private static boolean isDefaultStringProperty(String property) {
0640: return StringUtils.isEmpty(property);
0641: }
0642:
0643: private static boolean isNotSetStringProperty(String property) {
0644: return NOT_SET_VALUE.equals(property);
0645: }
0646:
0647: /**
0648: * Create the JFreeReport file.
0649: *
0650: * NOTE on the merge precedence: this method should use properties set by the
0651: * WAQR UI. If the waqr UI did not set the property, then the property
0652: * should be set by the metadata. If the metadata did not set a property,
0653: * then the property should be set by the template. If the template
0654: * did not set the property, then use the default.
0655: *
0656: * NOTE on the merge algorithm:
0657: * For each of the attributes in the fields (aka columns) of the reportspec,
0658: * if the attribute is present in the reportspec that comes in from the client
0659: * (ie reportXML param), and the attribute has a non-default value, do not change it.
0660: * If the attribute is not present or has a default value, and if there is metadata
0661: * for that attribute, merge the metadata attribute. This take place inline in the
0662: * main loop of this method. If after the metadata merge the attribute
0663: * still does not have a value, merge the template value. This takes place
0664: * in the AdhocWebService.applyTemplate() method.
0665: * If the template does not have a value, do nothing (the default will be used).
0666: *
0667: * @param reportDoc
0668: * @param reportXML
0669: * @param templatePath
0670: * @param mqlNode
0671: * @param repository
0672: * @param userSession
0673: * @return
0674: * @throws IOException
0675: * @throws AdhocWebServiceException
0676: * @throws PentahoMetadataException
0677: */
0678: public ByteArrayOutputStream createJFreeReportDefinitionAsStream(
0679: String reportXML, String templatePath, Element mqlNode,
0680: ISolutionRepository repository, IPentahoSession userSession)
0681: throws IOException, AdhocWebServiceException,
0682: PentahoMetadataException {
0683:
0684: Map reportSpecTypeToElement = null;
0685: Document templateDoc = null;
0686: Element templateItems = null;
0687: boolean bUseTemplate = !StringUtils.isEmpty(templatePath);
0688:
0689: if (bUseTemplate) {
0690: templatePath = WAQR_REPOSITORY_PATH + templatePath;
0691: templateDoc = repository
0692: .getResourceAsDocument(templatePath);
0693:
0694: templateItems = (Element) templateDoc
0695: .selectSingleNode("/report/items"); //$NON-NLS-1$
0696: List nodes = templateItems.elements();
0697: Iterator it = nodes.iterator();
0698: reportSpecTypeToElement = new HashMap();
0699: while (it.hasNext()) {
0700: Element element = (Element) it.next();
0701: reportSpecTypeToElement.put(element.getName(), element);
0702: }
0703: }
0704: MetadataPublisher.loadAllMetadata(userSession, false);
0705: CwmSchemaFactoryInterface cwmSchemaFactory = (CwmSchemaFactoryInterface) PentahoSystem
0706: .getObject(userSession, "ICwmSchemaFactory"); //$NON-NLS-1$
0707:
0708: MQLQuery mql = MQLQueryFactory.getMQLQuery(mqlNode.asXML(),
0709: null, LocaleHelper.getLocale().toString(),
0710: cwmSchemaFactory);
0711:
0712: String reportXMLEncoding = CleanXmlHelper
0713: .getEncoding(reportXML);
0714: ByteArrayInputStream reportSpecInputStream = new ByteArrayInputStream(
0715: reportXML.getBytes(reportXMLEncoding));
0716: ReportSpec reportSpec = (ReportSpec) CastorUtility
0717: .getInstance().readCastorObject(reportSpecInputStream,
0718: ReportSpec.class, reportXMLEncoding);
0719: if (reportSpec == null) {
0720: throw new AdhocWebServiceException(
0721: Messages
0722: .getErrorString("AdhocWebService.ERROR_0002_REPORT_INVALID")); //$NON-NLS-1$
0723: }
0724:
0725: BusinessModel model = mql.getModel();
0726: if (model == null) {
0727: throw new AdhocWebServiceException(
0728: Messages
0729: .getErrorString("AdhocWebService.ERROR_0003_BUSINESS_MODEL_INVALID")); //$NON-NLS-1$
0730: }
0731:
0732: for (int i = 0; i < reportSpec.getField().length; i++) {
0733: Field field = reportSpec.getField()[i];
0734: String name = field.getName();
0735: BusinessColumn column = model.findBusinessColumn(name);
0736:
0737: AdhocWebService.applyMetadata(field, column);
0738:
0739: // Template properties have the lowest priority, merge them last
0740: if (bUseTemplate) {
0741: Element templateDefaults = (Element) reportSpecTypeToElement
0742: .get(METADATA_TYPE_TO_REPORT_SPEC_TYPE
0743: .get(new Integer(column.getDataType()
0744: .getType()))); // sorry, this is ugly as hell
0745: /*
0746: * NOTE: this merge of the template with the node's properties only sets the following properties:
0747: * format, fontname, fontsize, color, alignment, vertical-alignment,
0748: */
0749: AdhocWebService.applyTemplate(field, templateDefaults);
0750: }
0751: AdhocWebService.applyDefaults(field);
0752: } // end for
0753:
0754: /*
0755: * Create the xml document (generatedJFreeDoc) containing the jfreereport definition using
0756: * the reportSpec as input. generatedJFreeDoc will have the metadata merged with it,
0757: * and some of the template.
0758: */
0759: ByteArrayOutputStream jfreeOutputStream = ReportGenerationUtility
0760: .createJFreeReportXMLAsStream(reportSpec,
0761: reportXMLEncoding);
0762: String jfreeXml = jfreeOutputStream.toString(reportXMLEncoding);
0763: Document generatedJFreeDoc = XmlHelper
0764: .getDocFromString(jfreeXml);
0765:
0766: /*
0767: * Merge template's /report/items element's attributes into the
0768: * generated document's /report/items element's attributes. There should not be any
0769: * conflict with the metadata, or the xreportspec in the reportXML param
0770: */
0771: ByteArrayOutputStream jfreeMergedOutputStream = null;
0772: if (bUseTemplate) {
0773: Element reportItems = (Element) generatedJFreeDoc
0774: .selectSingleNode("/report/items"); //$NON-NLS-1$
0775: List templateAttrs = templateItems.attributes(); // from the template's /report/items element
0776: Iterator templateAttrsIt = templateAttrs.iterator();
0777:
0778: while (templateAttrsIt.hasNext()) {
0779: Attribute attr = (Attribute) templateAttrsIt.next();
0780: String name = attr.getName();
0781: String value = attr.getText();
0782:
0783: Node node = reportItems.selectSingleNode("@" + name); //$NON-NLS-1$
0784: if (node != null) {
0785: node.setText(value);
0786: } else {
0787: reportItems.addAttribute(name, value);
0788: }
0789: }
0790: List templateElements = templateItems.elements();
0791: Iterator templateElementsIt = templateElements.iterator();
0792: while (templateElementsIt.hasNext()) {
0793: Element element = (Element) templateElementsIt.next();
0794: element.detach();
0795: reportItems.add(element);
0796: }
0797: /*
0798: * NOTE: this merging of the template (ReportGenerationUtility.mergeTemplate())
0799: * with the generated document can wait until last because none of the
0800: * properties involved in this merge are settable by the metadata or the WAQR UI
0801: */
0802: jfreeMergedOutputStream = ReportGenerationUtility
0803: .mergeTemplateAsStream(templateDoc,
0804: generatedJFreeDoc);
0805: } else {
0806: jfreeMergedOutputStream = new ByteArrayOutputStream();
0807: OutputFormat format = OutputFormat.createPrettyPrint();
0808: format.setEncoding(reportXMLEncoding);
0809: XMLWriter writer = new XMLWriter(jfreeMergedOutputStream,
0810: format);
0811: writer.write(generatedJFreeDoc);
0812: writer.close();
0813: }
0814:
0815: return jfreeMergedOutputStream;
0816: }
0817:
0818: /**
0819: * If the property has not been set by the UI, the metadata, or the template, then
0820: * set it with the default value, where the default value is defined in the
0821: * report-spec.xsd.
0822: * For the alignment attribute, if the template document's /report/items node
0823: * has an alignment attribute, then this attribute will be used for the default
0824: * horizontal-alignment property for children of /report/items. In this
0825: * case, do not set the attribute to the default, but set it to the empty string
0826: * so that the report processor can use the default from the /report/items/@alignment
0827: *
0828: * @param targetField
0829: * @param templateItemsElement Element the element in the template document
0830: * identified by the xpath /report/items
0831: */
0832: private static void applyDefaults(Field targetField) {
0833: if (AdhocWebService.isNotSetStringProperty(targetField
0834: .getHorizontalAlignment())) {
0835: targetField.setHorizontalAlignment(DEFAULT_FIELD_PROPS
0836: .getHorizontalAlignment());
0837: }
0838: if (AdhocWebService.isNotSetStringProperty(targetField
0839: .getVerticalAlignment())) {
0840: targetField.setVerticalAlignment(DEFAULT_FIELD_PROPS
0841: .getVerticalAlignment());
0842: }
0843: }
0844:
0845: private static void applyMetadata(Field field, BusinessColumn column) {
0846: ConceptInterface metadataConcept = column.getConcept();
0847: // WAQR doesn't set font properties, so if metadata font properties are available, they win
0848: FontSettings font = null;
0849: if (metadataConcept.getProperty(DefaultPropertyID.FONT.getId()) != null) {
0850: font = (FontSettings) metadataConcept.getProperty(
0851: DefaultPropertyID.FONT.getId()).getValue();
0852: }
0853:
0854: // set font size, name, and style
0855: if (font != null) {
0856: if (font.getHeight() > 0) {
0857: field.setFontSize(font.getHeight());
0858: }
0859: field.setFontName(font.getName());
0860: int fontStyle = 0;
0861: if (font.isBold()) {
0862: fontStyle += 1;
0863: }
0864: if (font.isItalic()) {
0865: fontStyle += 2;
0866: }
0867: field.setFontStyle(fontStyle);
0868: }
0869: // else use the default values in the Field class
0870:
0871: if (AdhocWebService.isNotSetStringProperty(field
0872: .getHorizontalAlignment())) {
0873: AlignmentSettings alignment = null;
0874: ConceptPropertyInterface horizontalAlignProp = metadataConcept
0875: .getProperty(DefaultPropertyID.ALIGNMENT.getId());
0876: if (horizontalAlignProp != null) {
0877: alignment = (AlignmentSettings) horizontalAlignProp
0878: .getValue();
0879:
0880: if (alignment != null) {
0881: if (alignment.getType() == AlignmentSettings.TYPE_ALIGNMENT_LEFT) {
0882: field.setHorizontalAlignment("left"); //$NON-NLS-1$
0883: } else if (alignment.getType() == AlignmentSettings.TYPE_ALIGNMENT_RIGHT) {
0884: field.setHorizontalAlignment("right"); //$NON-NLS-1$
0885: } else if (alignment.getType() == AlignmentSettings.TYPE_ALIGNMENT_CENTERED) {
0886: field.setHorizontalAlignment("center"); //$NON-NLS-1$
0887: }
0888: }
0889: }
0890: }
0891: if (AdhocWebService.isNotSetStringProperty(field
0892: .getVerticalAlignment())) {
0893: String valignSetting = null;
0894: ConceptPropertyInterface valignProp = metadataConcept
0895: .getProperty(METADATA_PROPERTY_ID_VERTICAL_ALIGNMENT);
0896: if (valignProp != null) {
0897: valignSetting = (String) valignProp.getValue();
0898: field.setVerticalAlignment(valignSetting);
0899: }
0900: }
0901:
0902: // WAQR doesn't set color properties, so if metadata font properties are available, they win
0903: ColorSettings color = null;
0904: if (metadataConcept.getProperty(DefaultPropertyID.COLOR_BG
0905: .getId()) != null) {
0906: color = (ColorSettings) metadataConcept.getProperty(
0907: DefaultPropertyID.COLOR_BG.getId()).getValue();
0908: }
0909:
0910: if (color != null) {
0911: String htmlColor = getJFreeColorString(color);
0912: field.setBackgroundColor(htmlColor);
0913: field.setUseBackgroundColor(true);
0914: }
0915:
0916: color = null;
0917: if (metadataConcept.getProperty(DefaultPropertyID.COLOR_FG
0918: .getId()) != null) {
0919: color = (ColorSettings) metadataConcept.getProperty(
0920: DefaultPropertyID.COLOR_FG.getId()).getValue();
0921: }
0922:
0923: if (color != null) {
0924: String htmlColor = getJFreeColorString(color);
0925: field.setFontColor(htmlColor);
0926: }
0927:
0928: String metaDataDisplayName = column.getDisplayName(LocaleHelper
0929: .getLocale().toString());
0930:
0931: if (field.getIsDetail()) {
0932: field.setDisplayName(metaDataDisplayName);
0933: } else {
0934: String reportSpecDisplayName = field.getDisplayName();
0935: if (AdhocWebService
0936: .isDefaultStringProperty(reportSpecDisplayName)) {
0937: String displayName = column.getDisplayName(LocaleHelper
0938: .getLocale().toString());
0939: field.setDisplayName(displayName
0940: + ": $(" + field.getName() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
0941: }
0942: }
0943: if (AdhocWebService.isDefaultStringProperty(field.getFormat())) {
0944: ConceptPropertyInterface cpi = metadataConcept
0945: .getProperty(DefaultPropertyID.MASK.getId());
0946: if (cpi != null) {
0947: String format = (String) cpi.getValue();
0948: if (!StringUtils.isEmpty(format)) {
0949: field.setFormat(format);
0950: }
0951: }
0952: }
0953: }
0954:
0955: private static void applyTemplate(Field field,
0956: Element templateDefaults) {
0957: if (templateDefaults != null) {
0958: Node node = null;
0959: if (AdhocWebService.isNotSetStringProperty(field
0960: .getHorizontalAlignment())) {
0961: node = templateDefaults.selectSingleNode("@alignment"); //$NON-NLS-1$
0962: if (node != null) {
0963: field.setHorizontalAlignment(node.getText());
0964: }
0965: }
0966: if (AdhocWebService.isNotSetStringProperty(field
0967: .getVerticalAlignment())) {
0968: node = templateDefaults
0969: .selectSingleNode("@vertical-alignment");//$NON-NLS-1$
0970: if (node != null) {
0971: field.setVerticalAlignment(node.getText());
0972: }
0973: }
0974: if (AdhocWebService.isDefaultStringProperty(field
0975: .getFormat())) {
0976: node = templateDefaults.selectSingleNode("@format");//$NON-NLS-1$
0977: if (node != null) {
0978: field.setFormat(node.getText());
0979: }
0980: }
0981: if (AdhocWebService.isDefaultStringProperty(field
0982: .getFontName())) {
0983: node = templateDefaults.selectSingleNode("@fontname");//$NON-NLS-1$
0984: if (node != null) {
0985: field.setFontName(node.getText());
0986: }
0987: }
0988: if (AdhocWebService.isDefaultStringProperty(field
0989: .getFontColor())) {
0990: node = templateDefaults.selectSingleNode("@color");//$NON-NLS-1$
0991: if (node != null) {
0992: field.setFontColor(node.getText());
0993: }
0994: }
0995: if (!field.hasFontSize()) {
0996: node = templateDefaults.selectSingleNode("@fontsize"); //$NON-NLS-1$
0997: if (node != null) {
0998: field.setFontSize(Integer.parseInt(node.getText()));
0999: }
1000: }
1001: }
1002: }
1003:
1004: // TODO sbarkdull, this has been upgraded to new naming convention, delete comment
1005: private void addMQLQueryXml(Element elem, String domainId,
1006: String modelId, String tableId, String columnId,
1007: String searchStr) {
1008:
1009: Element mqlElement = elem.addElement("mql"); //$NON-NLS-1$
1010: mqlElement.addElement("domain_type").setText("relational"); //$NON-NLS-1$ //$NON-NLS-2$
1011: mqlElement.addElement("domain_id").setText(domainId); //$NON-NLS-1$
1012: mqlElement.addElement("model_id").setText(modelId); //$NON-NLS-1$
1013: Element selectionElement = mqlElement.addElement("selections"); //$NON-NLS-1$
1014: selectionElement = selectionElement.addElement("selection"); //$NON-NLS-1$
1015: selectionElement.addElement("table").setText(tableId); //$NON-NLS-1$
1016: selectionElement.addElement("column").setText(columnId); //$NON-NLS-1$
1017:
1018: if (!StringUtils.isEmpty(searchStr)) {
1019: Element constraintElement = mqlElement
1020: .addElement("constraints"); //$NON-NLS-1$
1021: constraintElement = constraintElement
1022: .addElement("constraint"); //$NON-NLS-1$
1023: constraintElement.addElement("table_id").setText(tableId); //$NON-NLS-1$
1024: constraintElement
1025: .addElement("condition").setText(searchStr); //$NON-NLS-1$
1026: }
1027: }
1028:
1029: // TODO sbarkdull, this has been upgraded to new naming convention, delete comment
1030: public void createMQLQueryActionSequence(String domainId,
1031: String modelId, String tableId, String columnId,
1032: String searchStr, OutputStream outputStream,
1033: String userSessionName) throws IOException {
1034:
1035: Document document = DOMDocumentFactory.getInstance()
1036: .createDocument();
1037: document.setXMLEncoding(LocaleHelper.getSystemEncoding());
1038: Element actionSeqElement = document
1039: .addElement("action-sequence"); //$NON-NLS-1$
1040: actionSeqElement.addElement("version").setText("1"); //$NON-NLS-1$ //$NON-NLS-2$
1041: actionSeqElement.addElement("title").setText("MQL Query"); //$NON-NLS-1$ //$NON-NLS-2$
1042: actionSeqElement.addElement("logging-level").setText("ERROR"); //$NON-NLS-1$ //$NON-NLS-2$
1043: Element documentationElement = actionSeqElement
1044: .addElement("documentation"); //$NON-NLS-1$
1045: Element authorElement = documentationElement
1046: .addElement("author"); //$NON-NLS-1$
1047: if (userSessionName != null) {
1048: authorElement.setText(userSessionName);
1049: } else {
1050: authorElement.setText("Web Query & Reporting"); //$NON-NLS-1$
1051: }
1052: documentationElement
1053: .addElement("description").setText("Temporary action sequence used by Web Query & Reporting"); //$NON-NLS-1$ //$NON-NLS-2$
1054: documentationElement
1055: .addElement("result-type").setText("result-set"); //$NON-NLS-1$ //$NON-NLS-2$
1056: Element outputsElement = actionSeqElement.addElement("outputs"); //$NON-NLS-1$
1057: Element reportTypeElement = outputsElement
1058: .addElement("query_result"); //$NON-NLS-1$
1059: reportTypeElement.addAttribute("type", "result-set"); //$NON-NLS-1$ //$NON-NLS-2$
1060: Element destinationsElement = reportTypeElement
1061: .addElement("destinations"); //$NON-NLS-1$
1062: destinationsElement
1063: .addElement("response").setText("query_result"); //$NON-NLS-1$ //$NON-NLS-2$
1064:
1065: Element actionsElement = actionSeqElement.addElement("actions"); //$NON-NLS-1$
1066: Element actionDefinitionElement = actionsElement
1067: .addElement("action-definition"); //$NON-NLS-1$
1068: Element actionOutputsElement = actionDefinitionElement
1069: .addElement("action-outputs"); //$NON-NLS-1$
1070: Element ruleResultElement = actionOutputsElement
1071: .addElement("query-result"); //$NON-NLS-1$
1072: ruleResultElement.addAttribute("type", "result-set"); //$NON-NLS-1$ //$NON-NLS-2$
1073: ruleResultElement.addAttribute("mapping", "query_result"); //$NON-NLS-1$ //$NON-NLS-2$
1074: actionDefinitionElement
1075: .addElement("component-name").setText("MQLRelationalDataComponent"); //$NON-NLS-1$ //$NON-NLS-2$
1076: actionDefinitionElement
1077: .addElement("action-type").setText("MQL Query"); //$NON-NLS-1$ //$NON-NLS-2$
1078: Element componentDefinitionElement = actionDefinitionElement
1079: .addElement("component-definition"); //$NON-NLS-1$
1080:
1081: // componentDefinitionElement.addElement("query").addCDATA(createMQLQueryXml(domainId, modelId, tableId, columnId, searchStr)); //$NON-NLS-1$
1082: addMQLQueryXml(componentDefinitionElement, domainId, modelId,
1083: tableId, columnId, searchStr);
1084:
1085: // end action-definition for JFreeReportComponent
1086: OutputFormat format = OutputFormat.createPrettyPrint();
1087: format.setEncoding(LocaleHelper.getSystemEncoding());
1088: XMLWriter writer = new XMLWriter(outputStream, format);
1089: writer.write(document);
1090: writer.close();
1091: }
1092:
1093: // TODO sbarkdull, method needs to be renamed
1094: // TODO sbarkdull, method needs to be refactored so that instead of constructing the
1095: // document using the DOM, an xml template with no values is read in at initialization
1096: // and then this method uses the template to create a new document, and adds the
1097: // report specific information to the new document. It will make this code MUCH
1098: // easier to read and maintain. Other similar methods in this class should likely
1099: // be refactored in a similar way
1100: public ByteArrayOutputStream createMQLReportActionSequenceAsStream(
1101: String reportName, String reportDescription,
1102: Element mqlNode, String[] outputTypeList,
1103: String xactionName, String jfreeReportXML,
1104: String jfreeReportFilename, String loggingLevel,
1105: IPentahoSession userSession) throws IOException {
1106:
1107: boolean bIsMultipleOutputType = outputTypeList.length > 1;
1108: ByteArrayOutputStream xactionOutputStream = new ByteArrayOutputStream();
1109:
1110: Document document = DOMDocumentFactory.getInstance()
1111: .createDocument();
1112: document.setXMLEncoding(LocaleHelper.getSystemEncoding());
1113: Element actionSeqElement = document
1114: .addElement("action-sequence"); //$NON-NLS-1$
1115: Element actionSeqNameElement = actionSeqElement
1116: .addElement("name"); //$NON-NLS-1$
1117: actionSeqNameElement.setText(xactionName);
1118: Element actionSeqVersionElement = actionSeqElement
1119: .addElement("version"); //$NON-NLS-1$
1120: actionSeqVersionElement.setText("1"); //$NON-NLS-1$
1121:
1122: Element actionSeqTitleElement = actionSeqElement
1123: .addElement("title"); //$NON-NLS-1$
1124: String reportTitle = AdhocWebService
1125: .getBaseFilename(reportName); // remove ".waqr.xreportspec" if it is there
1126: actionSeqTitleElement.setText(reportTitle);
1127:
1128: Element loggingLevelElement = actionSeqElement
1129: .addElement("logging-level"); //$NON-NLS-1$
1130: loggingLevelElement.setText(loggingLevel);
1131:
1132: Element documentationElement = actionSeqElement
1133: .addElement("documentation"); //$NON-NLS-1$
1134: Element authorElement = documentationElement
1135: .addElement("author"); //$NON-NLS-1$
1136: if (userSession.getName() != null) {
1137: authorElement.setText(userSession.getName());
1138: } else {
1139: authorElement.setText("Web Query & Reporting"); //$NON-NLS-1$
1140: }
1141: Element descElement = documentationElement
1142: .addElement("description"); //$NON-NLS-1$
1143: descElement.setText(reportDescription);
1144: Element iconElement = documentationElement.addElement("icon"); //$NON-NLS-1$
1145: iconElement.setText("PentahoReporting.png"); //$NON-NLS-1$
1146: Element helpElement = documentationElement.addElement("help"); //$NON-NLS-1$
1147: helpElement.setText("Auto-generated action-sequence for WAQR."); //$NON-NLS-1$
1148: Element resultTypeElement = documentationElement
1149: .addElement("result-type"); //$NON-NLS-1$
1150: resultTypeElement.setText("report"); //$NON-NLS-1$
1151: // inputs
1152: Element inputsElement = actionSeqElement.addElement("inputs"); //$NON-NLS-1$
1153: Element outputTypeElement = inputsElement
1154: .addElement("output-type"); //$NON-NLS-1$
1155: outputTypeElement.addAttribute("type", "string"); //$NON-NLS-1$ //$NON-NLS-2$
1156: Element defaultValueElement = outputTypeElement
1157: .addElement("default-value"); //$NON-NLS-1$
1158: defaultValueElement.setText(outputTypeList[0]);
1159: Element sourcesElement = outputTypeElement
1160: .addElement("sources"); //$NON-NLS-1$
1161: Element requestElement = sourcesElement
1162: .addElement(HttpRequestParameterProvider.SCOPE_REQUEST);
1163: requestElement.setText("type"); //$NON-NLS-1$
1164:
1165: if (bIsMultipleOutputType) {
1166: // define list of report output-file extensions (html, pdf, xls, csv)
1167: /*
1168: * <mimeTypes type="string-list"> <sources> <request>mimeTypes</request> </sources> <default-value type="string-list"> <list-item>html</list-item> <list-item>pdf</list-item> <list-item>xls</list-item> <list-item>csv</list-item>
1169: * </default-value> </mimeTypes>
1170: */
1171: Element mimeTypes = inputsElement.addElement("mimeTypes");//$NON-NLS-1$
1172: mimeTypes.addAttribute("type", "string-list"); //$NON-NLS-1$ //$NON-NLS-2$
1173: Element sources = mimeTypes.addElement("sources");//$NON-NLS-1$
1174: requestElement = sources.addElement("request"); //$NON-NLS-1$
1175: requestElement.setText("mimeTypes"); //$NON-NLS-1$
1176: Element defaultValue = mimeTypes
1177: .addElement("default-value"); //$NON-NLS-1$
1178: defaultValue.addAttribute("type", "string-list"); //$NON-NLS-1$ //$NON-NLS-2$
1179: //$NON-NLS-1$
1180: Element listItem = null;
1181: for (int ii = 0; ii < outputTypeList.length; ++ii) {
1182: // array elements should be one of: html, pdf, csv, xls
1183: String outputType = outputTypeList[ii];
1184: listItem = defaultValue.addElement("list-item"); //$NON-NLS-1$
1185: listItem.setText(outputType);
1186: }
1187: }
1188:
1189: // outputs
1190: Element outputsElement = actionSeqElement.addElement("outputs"); //$NON-NLS-1$
1191: Element reportTypeElement = outputsElement.addElement("report"); //$NON-NLS-1$
1192: reportTypeElement.addAttribute("type", "content"); //$NON-NLS-1$ //$NON-NLS-2$
1193: Element destinationsElement = reportTypeElement
1194: .addElement("destinations"); //$NON-NLS-1$
1195: Element responseElement = destinationsElement
1196: .addElement("response"); //$NON-NLS-1$
1197: responseElement.setText("content"); //$NON-NLS-1$
1198: // resources
1199: Element resourcesElement = actionSeqElement
1200: .addElement("resources"); //$NON-NLS-1$
1201: Element reportDefinitionElement = resourcesElement
1202: .addElement("report-definition"); //$NON-NLS-1$
1203:
1204: Element solutionFileElement = null;
1205: if (null == jfreeReportFilename) {
1206: // likely they are running a preview
1207: solutionFileElement = reportDefinitionElement
1208: .addElement("xml"); //$NON-NLS-1$
1209: Element locationElement = solutionFileElement
1210: .addElement("location"); //$NON-NLS-1$
1211: Document jfreeReportDoc = XmlHelper
1212: .getDocFromString(jfreeReportXML);
1213: Node reportNode = jfreeReportDoc
1214: .selectSingleNode("/report"); //$NON-NLS-1$
1215: locationElement.add(reportNode);
1216: } else {
1217: // likely they are saving the report
1218: solutionFileElement = reportDefinitionElement
1219: .addElement("solution-file"); //$NON-NLS-1$
1220: Element locationElement = solutionFileElement
1221: .addElement("location"); //$NON-NLS-1$
1222: locationElement.setText(jfreeReportFilename);
1223: }
1224:
1225: Element mimeTypeElement = solutionFileElement
1226: .addElement("mime-type"); //$NON-NLS-1$
1227: mimeTypeElement.setText("text/xml"); //$NON-NLS-1$
1228: Element actionsElement = actionSeqElement.addElement("actions"); //$NON-NLS-1$
1229: Element actionDefinitionElement = null;
1230: if (bIsMultipleOutputType) // do secure filter
1231: {
1232: // begin action-definition for Secure Filter
1233: /*
1234: * <action-definition> <component-name>SecureFilterComponent</component-name> <action-type>Prompt/Secure Filter</action-type> <action-inputs> <output-type type="string"/> <mimeTypes type="string-list"/> </action-inputs>
1235: * <component-definition> <selections> <output-type prompt-if-one-value="true"> <title>Select output type:</title> <filter>mimeTypes</filter> </output-type> </selections> </component-definition> </action-definition>
1236: */
1237: actionDefinitionElement = actionsElement
1238: .addElement("action-definition"); //$NON-NLS-1$
1239: Element componentName = actionDefinitionElement
1240: .addElement("component-name"); //$NON-NLS-1$
1241: componentName.setText("SecureFilterComponent"); //$NON-NLS-1$
1242: Element actionType = actionDefinitionElement
1243: .addElement("action-type"); //$NON-NLS-1$
1244: actionType.setText("Prompt/Secure Filter"); //$NON-NLS-1$
1245:
1246: Element actionInputs = actionDefinitionElement
1247: .addElement("action-inputs"); //$NON-NLS-1$
1248: Element outputType = actionInputs.addElement("output-type"); //$NON-NLS-1$
1249: outputType.addAttribute("type", "string"); //$NON-NLS-1$ //$NON-NLS-2$
1250: Element mimeTypes = actionInputs.addElement("mimeTypes"); //$NON-NLS-1$
1251: mimeTypes.addAttribute("type", "string-list"); //$NON-NLS-1$ //$NON-NLS-2$
1252:
1253: Element componentDefinition = actionDefinitionElement
1254: .addElement("component-definition"); //$NON-NLS-1$
1255: Element selections = componentDefinition
1256: .addElement("selections"); //$NON-NLS-1$
1257: outputType = selections.addElement("output-type"); //$NON-NLS-1$
1258: outputType.addAttribute("prompt-if-one-value", "true"); //$NON-NLS-1$ //$NON-NLS-2$
1259: Element title = outputType.addElement("title"); //$NON-NLS-1$
1260: String prompt = Messages
1261: .getString("AdhocWebService.SELECT_OUTPUT_TYPE");//$NON-NLS-1$
1262: title.setText(prompt);
1263: Element filter = outputType.addElement("filter"); //$NON-NLS-1$
1264: filter.setText("mimeTypes"); //$NON-NLS-1$
1265: }
1266:
1267: // begin action-definition for SQLLookupRule
1268: actionDefinitionElement = actionsElement
1269: .addElement("action-definition"); //$NON-NLS-1$
1270: Element actionOutputsElement = actionDefinitionElement
1271: .addElement("action-outputs"); //$NON-NLS-1$
1272: Element ruleResultElement = actionOutputsElement
1273: .addElement("rule-result"); //$NON-NLS-1$
1274: ruleResultElement.addAttribute("type", "result-set"); //$NON-NLS-1$ //$NON-NLS-2$
1275: Element componentNameElement = actionDefinitionElement
1276: .addElement("component-name"); //$NON-NLS-1$
1277: componentNameElement.setText("MQLRelationalDataComponent"); //$NON-NLS-1$
1278: Element actionTypeElement = actionDefinitionElement
1279: .addElement("action-type"); //$NON-NLS-1$
1280: actionTypeElement.setText("rule"); //$NON-NLS-1$
1281: Element componentDefinitionElement = actionDefinitionElement
1282: .addElement("component-definition"); //$NON-NLS-1$
1283: componentDefinitionElement.add(mqlNode);
1284: componentDefinitionElement.addElement("live").setText("true"); //$NON-NLS-1$ //$NON-NLS-2$
1285: componentDefinitionElement
1286: .addElement("display-names").setText("false"); //$NON-NLS-1$ //$NON-NLS-2$
1287: // end action-definition for SQLLookupRule
1288: // begin action-definition for JFreeReportComponent
1289: actionDefinitionElement = actionsElement
1290: .addElement("action-definition"); //$NON-NLS-1$
1291: actionOutputsElement = actionDefinitionElement
1292: .addElement("action-outputs"); //$NON-NLS-1$
1293:
1294: Element actionInputsElement = actionDefinitionElement
1295: .addElement("action-inputs"); //$NON-NLS-1$
1296: outputTypeElement = actionInputsElement
1297: .addElement("output-type"); //$NON-NLS-1$
1298: outputTypeElement.addAttribute("type", "string"); //$NON-NLS-1$ //$NON-NLS-2$
1299: Element dataElement = actionInputsElement.addElement("data"); //$NON-NLS-1$
1300:
1301: Element actionResourcesElement = actionDefinitionElement
1302: .addElement("action-resources"); //$NON-NLS-1$
1303: Element reportDefinition = actionResourcesElement
1304: .addElement("report-definition"); //$NON-NLS-1$
1305: reportDefinition.addAttribute("type", "resource"); //$NON-NLS-1$ //$NON-NLS-2$
1306:
1307: dataElement.addAttribute("type", "result-set"); //$NON-NLS-1$ //$NON-NLS-2$
1308: dataElement.addAttribute("mapping", "rule-result"); //$NON-NLS-1$ //$NON-NLS-2$
1309: Element reportOutputElement = actionOutputsElement
1310: .addElement("report"); //$NON-NLS-1$
1311: reportOutputElement.addAttribute("type", "content"); //$NON-NLS-1$ //$NON-NLS-2$
1312: componentNameElement = actionDefinitionElement
1313: .addElement("component-name"); //$NON-NLS-1$
1314: componentNameElement.setText("JFreeReportComponent"); //$NON-NLS-1$
1315: actionTypeElement = actionDefinitionElement
1316: .addElement("action-type"); //$NON-NLS-1$
1317: actionTypeElement.setText("report"); //$NON-NLS-1$
1318: componentDefinitionElement = actionDefinitionElement
1319: .addElement("component-definition"); //$NON-NLS-1$
1320: componentDefinitionElement
1321: .addElement("output-type").setText(outputTypeList[0]); //$NON-NLS-1$
1322:
1323: // end action-definition for JFreeReportComponent
1324: OutputFormat format = OutputFormat.createPrettyPrint();
1325: format.setEncoding(LocaleHelper.getSystemEncoding());
1326: XMLWriter writer = new XMLWriter(xactionOutputStream, format);
1327: writer.write(document);
1328: writer.close();
1329:
1330: return xactionOutputStream;
1331: }
1332:
1333: public void lookupValues(IParameterProvider parameterProvider,
1334: OutputStream outputStream, IPentahoSession userSession,
1335: boolean isAjax) throws IOException {
1336:
1337: String domainName = parameterProvider.getStringParameter(
1338: "model", null); //$NON-NLS-1$
1339: String viewId = parameterProvider.getStringParameter(
1340: "view", null); //$NON-NLS-1$
1341: String columnId = parameterProvider.getStringParameter(
1342: "column", null); //$NON-NLS-1$
1343:
1344: IPentahoUrlFactory urlFactory = new SimpleUrlFactory(""); //$NON-NLS-1$
1345:
1346: PMDUIComponent component = new PMDUIComponent(urlFactory,
1347: new ArrayList());
1348: component.validate(userSession, null);
1349: component.setAction(PMDUIComponent.ACTION_LOOKUP);
1350: component.setDomainName(domainName);
1351: component.setModelId(viewId);
1352: component.setColumnId(columnId);
1353:
1354: Document doc = component.getXmlContent();
1355: writeDocumentAsSoapResponse(outputStream, doc, isAjax);
1356: }
1357:
1358: private void getWaqrRepositoryIndexDoc(
1359: IParameterProvider parameterProvider,
1360: OutputStream outputStream, IPentahoSession userSession,
1361: boolean isAjax) throws IOException,
1362: AdhocWebServiceException {
1363:
1364: String templateFolderPath = parameterProvider
1365: .getStringParameter("templateFolderPath", null); //$NON-NLS-1$
1366: if (StringUtil
1367: .doesPathContainParentPathSegment(templateFolderPath)) {
1368: String msg = Messages
1369: .getString(
1370: "AdhocWebService.ERROR_0010_OPEN_INDEX_DOC_FAILED", templateFolderPath); //$NON-NLS-1$
1371: throw new AdhocWebServiceException(msg);
1372: }
1373:
1374: ISolutionRepository repository = PentahoSystem
1375: .getSolutionRepository(userSession);
1376: String templateFilename = "system/waqr" + templateFolderPath + "/" + SolutionRepositoryBase.INDEX_FILENAME; //$NON-NLS-1$ //$NON-NLS-2$
1377: try {
1378: InputStream inStrm = repository.getResourceInputStream(
1379: templateFilename, false);
1380: Document indexDoc = CleanXmlHelper.getDocFromStream(inStrm);
1381: ISolutionFile templateFile = repository
1382: .getFileByPath(templateFilename);
1383: repository.localizeDoc(indexDoc, templateFile);
1384:
1385: writeDocumentAsSoapResponse(outputStream, indexDoc, isAjax);
1386: } catch (Exception e) {
1387: String msg = Messages
1388: .getString("AdhocWebService.ERROR_0010_OPEN_INDEX_DOC_FAILED"); //$NON-NLS-1$
1389: msg = msg + " " + e.getLocalizedMessage(); //$NON-NLS-1$
1390: throw new AdhocWebServiceException(msg);
1391: }
1392: }
1393:
1394: private void deleteWaqrReport(IParameterProvider parameterProvider,
1395: OutputStream outputStream, IPentahoSession userSession,
1396: boolean isAjax) throws IOException,
1397: AdhocWebServiceException {
1398:
1399: ISolutionRepository repository = PentahoSystem
1400: .getSolutionRepository(userSession);
1401: // NOTE: sbarkdull, shouldn't have to place the "/" on the front of the path segments.
1402: String solution = "/" + parameterProvider.getStringParameter("solution", null); //$NON-NLS-1$ //$NON-NLS-2$
1403: String path = "/" + parameterProvider.getStringParameter("path", null); //$NON-NLS-1$ //$NON-NLS-2$
1404: String filename = parameterProvider.getStringParameter(
1405: "filename", null); //$NON-NLS-1$
1406: String baseFilename = AdhocWebService.getBaseFilename(filename);
1407:
1408: if (StringUtil.doesPathContainParentPathSegment(path)) {
1409: String msg = Messages
1410: .getString(
1411: "AdhocWebService.ERROR_0007_FAILED_TO_DELETE_FILES", filename); //$NON-NLS-1$
1412: throw new AdhocWebServiceException(msg);
1413: }
1414:
1415: String msg = ""; //$NON-NLS-1$
1416: String xactionFile = "/" + baseFilename + "." + WAQR_EXTENSION + ".xaction"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1417: boolean success = repository.removeSolutionFile(solution, path,
1418: xactionFile);
1419: // if we fail to delete the protected xaction file, don't delete the xml or reportspec files
1420: if (success) {
1421: String jfreeFile = "/" + baseFilename + "." + WAQR_EXTENSION + ".xml"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1422: if (!repository.removeSolutionFile(solution, path,
1423: jfreeFile)) {
1424: msg = jfreeFile + " "; //$NON-NLS-1$
1425: }
1426:
1427: String reportSpecFile = "/" + baseFilename + "." + WAQR_EXTENSION + ".xreportspec"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1428: if (!repository.removeSolutionFile(solution, path,
1429: reportSpecFile)) {
1430: msg += reportSpecFile + " "; //$NON-NLS-1$
1431: }
1432: } else {
1433: msg += xactionFile + " "; //$NON-NLS-1$
1434: }
1435:
1436: if (msg.length() == 0) {
1437: msg = AdhocWebService
1438: .getStatusXml(Messages
1439: .getString("AdhocWebService.USER_DELETE_SUCCESSFUL")); //$NON-NLS-1$
1440: } else {
1441: msg = Messages
1442: .getString(
1443: "AdhocWebService.ERROR_0007_FAILED_TO_DELETE_FILES", msg); //$NON-NLS-1$
1444: throw new AdhocWebServiceException(msg);
1445: }
1446:
1447: writeStringAsSoapResponse(outputStream, msg, isAjax);
1448: }
1449:
1450: private void saveFile(IParameterProvider parameterProvider,
1451: OutputStream outputStream, IPentahoSession userSession,
1452: boolean isAjax) throws AdhocWebServiceException,
1453: IOException, PentahoMetadataException {
1454:
1455: String fileName = parameterProvider.getStringParameter(
1456: "name", null); //$NON-NLS-1$
1457: if (isWaqrFilename(fileName)) {
1458: saveReportSpec(fileName, parameterProvider, outputStream,
1459: userSession, isAjax);
1460: } else {
1461: throw new RuntimeException(
1462: "saveFile is only implemented for WAQR files, stay tuned."); //$NON-NLS-1$
1463: }
1464: }
1465:
1466: /**
1467: *
1468: * @param fileName
1469: * @param parameterProvider
1470: * @param outputStream
1471: * @param userSession
1472: * @param isAjax
1473: * @throws AdhocWebServiceException
1474: * @throws IOException
1475: * @throws PentahoMetadataException
1476: */
1477: protected void saveReportSpec(String fileName,
1478: IParameterProvider parameterProvider,
1479: OutputStream outputStream, IPentahoSession userSession,
1480: boolean isAjax) throws AdhocWebServiceException,
1481: IOException, PentahoMetadataException {
1482:
1483: // TODO sbarkdull, all parameters coming in from the client need to be validated, and error msgs returned to the client when a parameter does not validate
1484: String reportXML = parameterProvider.getStringParameter(
1485: "content", null); //$NON-NLS-1$
1486: String solutionName = parameterProvider.getStringParameter(
1487: "solution", null); //$NON-NLS-1$
1488: String solutionPath = parameterProvider.getStringParameter(
1489: "path", null); //$NON-NLS-1$
1490: String templatePath = parameterProvider.getStringParameter(
1491: "templatePath", null); //$NON-NLS-1$
1492: boolean overwrite = parameterProvider.getStringParameter(
1493: "overwrite", "false").equalsIgnoreCase("true"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1494: String outputType = parameterProvider.getStringParameter(
1495: "outputType", null); //$NON-NLS-1$
1496:
1497: if (StringUtil.doesPathContainParentPathSegment(solutionPath)
1498: || StringUtil
1499: .doesPathContainParentPathSegment(templatePath)) {
1500: String msg = Messages
1501: .getString("AdhocWebService.ERROR_0008_MISSING_OR_INVALID_REPORT_NAME"); //$NON-NLS-1$
1502: throw new AdhocWebServiceException(msg);
1503: }
1504: ISolutionRepository repository = PentahoSystem
1505: .getSolutionRepository(userSession);
1506: String baseUrl = PentahoSystem.getApplicationContext()
1507: .getSolutionPath(""); //$NON-NLS-1$
1508:
1509: Document reportSpecDoc = XmlHelper.getDocFromString(reportXML);
1510: Element mqlNode = (Element) reportSpecDoc
1511: .selectSingleNode("/report-spec/query/mql"); //$NON-NLS-1$
1512: mqlNode.detach();
1513:
1514: Node reportNameNd = reportSpecDoc
1515: .selectSingleNode("/report-spec/report-name"); //$NON-NLS-1$
1516: String reportName = reportNameNd.getText();
1517: Node reportDescNd = reportSpecDoc
1518: .selectSingleNode("/report-spec/report-desc"); //$NON-NLS-1$
1519: String reportDesc = reportDescNd.getText();
1520:
1521: String[] outputTypeList = outputType.split(","); //$NON-NLS-1$
1522:
1523: String baseName = AdhocWebService.getBaseFilename(fileName);
1524: if (null == baseName) {
1525: String msg = Messages
1526: .getString("AdhocWebService.ERROR_0008_MISSING_OR_INVALID_REPORT_NAME");//$NON-NLS-1$
1527: throw new AdhocWebServiceException(msg);
1528: }
1529: baseName += "." + WAQR_EXTENSION; //$NON-NLS-1$
1530: String xactionFilename = baseName + ".xaction"; //$NON-NLS-1$
1531: String jfreeFilename = baseName + ".xml"; //$NON-NLS-1$
1532: String xreportSpecFilename = baseName + ".xreportspec"; //$NON-NLS-1$
1533:
1534: ByteArrayOutputStream jfreeOutputStream = createJFreeReportDefinitionAsStream(
1535: reportXML, templatePath, mqlNode, repository,
1536: userSession);
1537: String jfreeString = jfreeOutputStream.toString(LocaleHelper
1538: .getSystemEncoding());
1539:
1540: // create .xaction to save
1541: ByteArrayOutputStream xactionOutputStream = createMQLReportActionSequenceAsStream(
1542: reportName, reportDesc, mqlNode, outputTypeList,
1543: xactionFilename, jfreeString, jfreeFilename, "warn",
1544: userSession);
1545: solutionPath = StringUtils.isEmpty(solutionPath) ? "" : "/" + solutionPath; //$NON-NLS-1$ //$NON-NLS-2$
1546: String path = solutionName + solutionPath + "/"; //$NON-NLS-1$
1547:
1548: int jfreeSaveStatus = ISolutionRepository.FILE_ADD_FAILED;
1549: int xreportSpecSaveStatus = ISolutionRepository.FILE_ADD_FAILED;
1550:
1551: int xactionSaveStatus = repository.addSolutionFile(baseUrl,
1552: path, xactionFilename, xactionOutputStream.toString(
1553: LocaleHelper.getSystemEncoding()).getBytes(),
1554: overwrite);
1555: if (xactionSaveStatus == ISolutionRepository.FILE_ADD_SUCCESSFUL) {
1556: // add jfree report xml
1557: jfreeSaveStatus = repository.addSolutionFile(baseUrl, path,
1558: jfreeFilename, jfreeString.getBytes(LocaleHelper
1559: .getSystemEncoding()), overwrite);
1560: if (jfreeSaveStatus == ISolutionRepository.FILE_ADD_SUCCESSFUL) {
1561: xreportSpecSaveStatus = repository.addSolutionFile(
1562: baseUrl, path, xreportSpecFilename, reportXML
1563: .getBytes(LocaleHelper
1564: .getSystemEncoding()),
1565: overwrite);
1566: }
1567: }
1568: int[] errorStatusAr = { xactionSaveStatus, jfreeSaveStatus,
1569: xreportSpecSaveStatus };
1570: int errorStatus = AdhocWebService
1571: .getSaveErrorStatus(errorStatusAr);
1572: if (errorStatus == ISolutionRepository.FILE_ADD_SUCCESSFUL) {
1573: String msg = AdhocWebService.getStatusXml(Messages
1574: .getString("AdhocWebService.USER_REPORT_SAVED")); //$NON-NLS-1$
1575: writeStringAsSoapResponse(outputStream, msg, isAjax);
1576:
1577: // Force a refresh of the cached solution tree. This will cause the
1578: // newly saved files to show up in the next directory listing.
1579: // if overwrite is true, they are saving over an existing file, so that file's name
1580: // will already be in the cached sol. repos. tree.
1581: if (!overwrite) {
1582: invalidateSolutionRepositoryTree(userSession);
1583: repository.reloadSolutionRepository(userSession,
1584: repository.getLoggingLevel());
1585: }
1586:
1587: } else {
1588: // TODO sbarkdull, if any of the saves fails, remove the saved files
1589: // that succeeded (simulate a transaction)
1590: String msg = Messages
1591: .getString("AdhocWebService.ERROR_0009_SAVE_FAILED") + " " + ISolutionRepository.FILE_STATUS_MSG[errorStatus]; //$NON-NLS-1$ //$NON-NLS-2$
1592: if (ISolutionRepository.FILE_EXISTS == errorStatus) {
1593: msg += " (" + xreportSpecFilename + ")"; //$NON-NLS-1$ //$NON-NLS-2$
1594: }
1595: throw new AdhocWebServiceException(msg);
1596: }
1597: }
1598:
1599: public void listBusinessModels(
1600: IParameterProvider parameterProvider,
1601: OutputStream outputStream, IPentahoSession userSession,
1602: boolean isAjax) throws IOException {
1603:
1604: String domainName = parameterProvider.getStringParameter(
1605: "domain", null); //$NON-NLS-1$
1606:
1607: IPentahoUrlFactory urlFactory = new SimpleUrlFactory(""); //$NON-NLS-1$
1608:
1609: PMDUIComponent component = new PMDUIComponent(urlFactory,
1610: new ArrayList());
1611: component.validate(userSession, null);
1612: component.setAction(PMDUIComponent.ACTION_LIST_MODELS);
1613: component.setDomainName(domainName);
1614:
1615: Document doc = component.getXmlContent();
1616:
1617: writeDocumentAsSoapResponse(outputStream, doc, isAjax);
1618: }
1619:
1620: public void getBusinessModel(IParameterProvider parameterProvider,
1621: OutputStream outputStream, IPentahoSession userSession,
1622: boolean isAjax) throws IOException {
1623:
1624: String domainName = parameterProvider.getStringParameter(
1625: "domain", null); //$NON-NLS-1$
1626: String modelId = parameterProvider.getStringParameter(
1627: "model", null); //$NON-NLS-1$
1628:
1629: IPentahoUrlFactory urlFactory = new SimpleUrlFactory(""); //$NON-NLS-1$
1630:
1631: PMDUIComponent component = new PMDUIComponent(urlFactory,
1632: new ArrayList());
1633: component.validate(userSession, null);
1634: component.setAction(PMDUIComponent.ACTION_LOAD_MODEL);
1635: component.setDomainName(domainName);
1636: component.setModelId(modelId);
1637:
1638: Document doc = component.getXmlContent();
1639: writeDocumentAsSoapResponse(outputStream, doc, isAjax);
1640: }
1641:
1642: // TODO sbarkdull, this has been partially upgraded to new naming convention, delete comment
1643: public void searchTable(IParameterProvider parameterProvider,
1644: OutputStream outputStream, IPentahoSession userSession,
1645: boolean isAjax) throws IOException {
1646: String domainId = (String) parameterProvider
1647: .getParameter("modelId"); //$NON-NLS-1$
1648: String modelId = (String) parameterProvider
1649: .getParameter("viewId"); //$NON-NLS-1$
1650: String tableId = (String) parameterProvider
1651: .getParameter("tableId"); //$NON-NLS-1$
1652: String columnId = (String) parameterProvider
1653: .getParameter("columnId"); //$NON-NLS-1$
1654: String searchStr = (String) parameterProvider
1655: .getParameter("searchStr"); //$NON-NLS-1$
1656:
1657: ByteArrayOutputStream xactionOutputStream = new ByteArrayOutputStream();
1658: createMQLQueryActionSequence(domainId, modelId, tableId,
1659: columnId, searchStr, xactionOutputStream, userSession
1660: .getName());
1661: Document document = DocumentHelper.createDocument();
1662: document.setXMLEncoding(LocaleHelper.getSystemEncoding());
1663: Element resultsElement = document.addElement("results"); //$NON-NLS-1$
1664:
1665: IRuntimeContext runtimeContext = executeActionSequence(
1666: xactionOutputStream.toString(),
1667: "mqlQuery.xaction", new SimpleParameterProvider(), userSession, new ByteArrayOutputStream()); //$NON-NLS-1$
1668: if (runtimeContext.getStatus() == IRuntimeContext.RUNTIME_STATUS_SUCCESS) {
1669: IActionParameter actionParameter = runtimeContext
1670: .getOutputParameter("query_result"); //$NON-NLS-1$
1671: IPentahoResultSet pentahoResultSet = actionParameter
1672: .getValueAsResultSet();
1673: TreeSet treeSet = new TreeSet();
1674: for (int i = 0; i < pentahoResultSet.getRowCount(); i++) {
1675: Object[] rowValues = pentahoResultSet.getDataRow(i);
1676: if (rowValues[0] != null) {
1677: treeSet.add(rowValues[0]);
1678: }
1679: }
1680: for (Iterator iterator = treeSet.iterator(); iterator
1681: .hasNext();) {
1682: resultsElement
1683: .addElement("row").setText(iterator.next().toString()); //$NON-NLS-1$
1684: }
1685: runtimeContext.dispose();
1686: }
1687: writeStringAsSoapResponse(outputStream, document.asXML(),
1688: isAjax);
1689: }
1690:
1691: public void getTemplateReportSpec(
1692: IParameterProvider parameterProvider,
1693: OutputStream outputStream, IPentahoSession userSession,
1694: boolean isAjax) throws AdhocWebServiceException,
1695: IOException {
1696:
1697: ISolutionRepository repository = PentahoSystem
1698: .getSolutionRepository(userSession);
1699: String reportSpecName = parameterProvider.getStringParameter(
1700: "reportSpecPath", null); //$NON-NLS-1$
1701: Document reportSpecDoc = null;
1702: if (!StringUtils.isEmpty(reportSpecName)) {
1703: try {
1704: reportSpecName = WAQR_REPOSITORY_PATH + reportSpecName;
1705: reportSpecDoc = repository
1706: .getResourceAsDocument(reportSpecName);
1707: } catch (IOException ex) {
1708: String msg = Messages
1709: .getString(
1710: "AdhocWebService.ERROR_0004_FAILED_TO_LOAD_REPORTSPEC", reportSpecName);//$NON-NLS-1$
1711: throw new AdhocWebServiceException(msg, ex);
1712: }
1713: } else {
1714: String msg = Messages
1715: .getString("AdhocWebService.ERROR_0005_MISSING_REPORTSPEC_NAME"); //$NON-NLS-1$
1716: throw new AdhocWebServiceException(msg);
1717: }
1718: writeDocumentAsSoapResponse(outputStream, reportSpecDoc, isAjax);
1719: }
1720:
1721: public void getWaqrReportSpecDoc(
1722: IParameterProvider parameterProvider,
1723: OutputStream outputStream, IPentahoSession userSession,
1724: boolean isAjax) throws AdhocWebServiceException,
1725: IOException {
1726:
1727: ISolutionRepository repository = PentahoSystem
1728: .getSolutionRepository(userSession);
1729: String solution = parameterProvider.getStringParameter(
1730: "solution", null); //$NON-NLS-1$
1731: String path = parameterProvider
1732: .getStringParameter("path", null); //$NON-NLS-1$
1733: String filename = parameterProvider.getStringParameter(
1734: "filename", null); //$NON-NLS-1$
1735:
1736: Document reportSpecDoc = null;
1737: if (!StringUtils.isEmpty(solution) && null != path
1738: && !StringUtils.isEmpty(filename)) {
1739: try {
1740: String filePath = AdhocWebService.buildSolutionPath(
1741: solution, path, filename);
1742: reportSpecDoc = repository
1743: .getResourceAsDocument(filePath);
1744: } catch (IOException ex) {
1745: String msg = Messages
1746: .getString(
1747: "AdhocWebService.ERROR_0004_FAILED_TO_LOAD_REPORTSPEC",//$NON-NLS-1$
1748: filename);
1749: throw new AdhocWebServiceException(msg, ex);
1750: }
1751: } else {
1752: String msg = Messages
1753: .getString("AdhocWebService.ERROR_0005_MISSING_REPORTSPEC_NAME"); //$NON-NLS-1$
1754: throw new AdhocWebServiceException(msg);
1755: }
1756: writeDocumentAsSoapResponse(outputStream, reportSpecDoc, isAjax);
1757: }
1758:
1759: private static String buildSolutionPath(String solution,
1760: String path, String filename) {
1761: StringBuffer buf = new StringBuffer("/"); //$NON-NLS-1$
1762: String maybePathSeparator = ((StringUtils.isEmpty(path)) ? "" : "/"); //$NON-NLS-1$//$NON-NLS-2$
1763: return buf.append(solution).append(maybePathSeparator).append(
1764: path).append("/").append(filename).toString(); //$NON-NLS-1$
1765: }
1766:
1767: private static String getErrorXml(String errorMsg) {
1768: errorMsg = StringEscapeUtils.escapeXml(errorMsg);
1769: return "<adhoc><error msg=\"" + errorMsg + "\"/></adhoc>"; //$NON-NLS-1$ //$NON-NLS-2$
1770: }
1771:
1772: private static String getErrorHtml(Exception e, String errorMsg) {
1773: errorMsg = StringEscapeUtils.escapeXml(errorMsg);
1774:
1775: StringBuffer b = new StringBuffer();
1776: List msgList = new LinkedList();
1777: msgList.add(errorMsg);
1778: msgList.add(Messages.getString("AdhocWebService.REASON")); //$NON-NLS-1$
1779: if (null != e.getMessage()) {
1780: msgList.add(e.getMessage());
1781: } else {
1782: msgList.add(e.getClass().getName());
1783: }
1784: UIUtil
1785: .formatErrorMessage(
1786: "text/html", Messages.getString("AdhocWebService.HEADER_ERROR_PAGE"),//$NON-NLS-1$//$NON-NLS-2$
1787: msgList, b);
1788:
1789: return b.toString();
1790: }
1791:
1792: private static String getStatusXml(String statusMsg) {
1793: statusMsg = StringEscapeUtils.escapeXml(statusMsg);
1794: return "<adhoc><status msg=\"" + statusMsg + "\"/></adhoc>"; //$NON-NLS-1$ //$NON-NLS-2$
1795: }
1796:
1797: private static int getSaveErrorStatus(int[] statusAr) {
1798: for (int ii = 0; ii < statusAr.length; ++ii) {
1799: int status = statusAr[ii];
1800: if (status != ISolutionRepository.FILE_ADD_SUCCESSFUL) {
1801: return status;
1802: }
1803: }
1804: return ISolutionRepository.FILE_ADD_SUCCESSFUL;
1805: }
1806:
1807: private static boolean isWaqrFilename(String filename) {
1808: return filename.matches(".*\\.waqr\\..*"); //$NON-NLS-1$
1809: }
1810:
1811: public Document getSolutionRepositoryDoc(String solutionName,
1812: String path, IPentahoSession userSession) {
1813:
1814: Document solutionRepositoryDoc = null;
1815: CacheManager cacheManager = PentahoSystem.getCacheManager();
1816: if (null != cacheManager) {
1817: Map solutionRepositoryFolderMap = (Map) cacheManager
1818: .getFromSessionCache(userSession,
1819: SOLUTION_NAVIGATION_DOCUMENT_MAP);
1820: if (solutionRepositoryFolderMap == null) {
1821: solutionRepositoryFolderMap = new HashMap();
1822: cacheManager.putInSessionCache(userSession,
1823: SOLUTION_NAVIGATION_DOCUMENT_MAP,
1824: solutionRepositoryFolderMap);
1825: }
1826: String cacheKey = solutionName + "/" + path; //$NON-NLS-1$
1827: solutionRepositoryDoc = (Document) solutionRepositoryFolderMap
1828: .get(cacheKey);
1829: if (solutionRepositoryDoc == null) {
1830: solutionRepositoryDoc = createSolutionRepositoryDoc(
1831: solutionName, path, userSession);
1832: solutionRepositoryFolderMap.put(cacheKey,
1833: solutionRepositoryDoc);
1834: }
1835: } else {
1836: solutionRepositoryDoc = createSolutionRepositoryDoc(
1837: solutionName, path, userSession);
1838: }
1839: // TODO sbarkdull, clean up
1840: //String strXml = solutionRepositoryDoc.asXML();
1841:
1842: return solutionRepositoryDoc;
1843: }
1844:
1845: /**
1846: * Used in conjunction with the xml document returned by getFullSolutionDoc()
1847: * @param element
1848: */
1849: private static void removeChildElements(Element element) {
1850: if (element.getName().equals("leaf")) { //$NON-NLS-1$
1851: List childElements = element.elements();
1852: for (Iterator iter = childElements.iterator(); iter
1853: .hasNext();) {
1854: Element childElement = (Element) iter.next();
1855: if (!childElement.getName().equals("leafText") //$NON-NLS-1$
1856: && !childElement.getName().equals("path")) { //$NON-NLS-1$
1857: childElement.detach();
1858: }
1859: }
1860: } else {
1861: List childElements = element.elements();
1862: for (Iterator iter = childElements.iterator(); iter
1863: .hasNext();) {
1864: Element childElement = (Element) iter.next();
1865: if (childElement.getName().equals("leaf")) { //$NON-NLS-1$
1866: List grandChildren = childElement.elements();
1867: for (Iterator iter2 = grandChildren.iterator(); iter2
1868: .hasNext();) {
1869: Element grandChildElement = (Element) iter2
1870: .next();
1871: if (!grandChildElement.getName().equals(
1872: "leafText") //$NON-NLS-1$
1873: && !grandChildElement.getName().equals(
1874: "path")) { //$NON-NLS-1$
1875: grandChildElement.detach();
1876: }
1877: }
1878: } else if (childElement.getName().equals("branch")) { //$NON-NLS-1$
1879: List grandChildren = childElement.elements();
1880: for (Iterator iter2 = grandChildren.iterator(); iter2
1881: .hasNext();) {
1882: Element grandChildElement = (Element) iter2
1883: .next();
1884: if (!grandChildElement.getName().equals(
1885: "branchText")) { //$NON-NLS-1$
1886: grandChildElement.detach();
1887: }
1888: }
1889: } else if (!childElement.getName().equals("branchText")) { //$NON-NLS-1$
1890: childElement.detach();
1891: }
1892: }
1893: }
1894: }
1895:
1896: private static Element getFolderElement(Document doc,
1897: String folderPath) {
1898:
1899: // looks like: //branch[@id='/stuff/stuff2' and @isDir='true']
1900: String folderXPath = "//" + SolutionReposUtil.BRANCH_NODE_NAME //$NON-NLS-1$
1901: + "[@" + SolutionReposUtil.ID_ATTR_NAME + "='" + folderPath + "' and @" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1902: + SolutionReposUtil.IS_DIR_ATTR_NAME + "='true']"; //$NON-NLS-1$
1903: Element folderElement = (Element) doc
1904: .selectSingleNode(folderXPath);
1905: return folderElement;
1906: }
1907:
1908: private Document getFullSolutionDoc(IPentahoSession userSession) {
1909:
1910: Document fullDoc = null;
1911: ISolutionRepository repository = PentahoSystem
1912: .getSolutionRepository(userSession);
1913: CacheManager cacheManager = PentahoSystem.getCacheManager();
1914:
1915: if (null != cacheManager) {
1916: fullDoc = (Document) cacheManager.getFromSessionCache(
1917: userSession, FULL_SOLUTION_DOC);
1918: if (fullDoc == null) {
1919: fullDoc = repository.getFullSolutionTree(
1920: ISolutionRepository.ACTION_EXECUTE, null);
1921: cacheManager.putInSessionCache(userSession,
1922: FULL_SOLUTION_DOC, fullDoc);
1923: }
1924: } else {
1925: fullDoc = repository.getFullSolutionTree(
1926: ISolutionRepository.ACTION_EXECUTE, null);
1927: }
1928: return fullDoc;
1929: }
1930:
1931: private Document getWaqrRepositoryDoc(String folderPath,
1932: IPentahoSession userSession)
1933: throws AdhocWebServiceException {
1934:
1935: if (StringUtil.doesPathContainParentPathSegment(folderPath)) {
1936: String msg = Messages
1937: .getString(
1938: "AdhocWebService.ERROR_0011_FAILED_TO_LOCATE_PATH", folderPath); //$NON-NLS-1$
1939: throw new AdhocWebServiceException(msg);
1940: }
1941: String solutionRepositoryName = AdhocWebService
1942: .getSolutionRepositoryName(userSession);
1943:
1944: String path = "/" + solutionRepositoryName + WAQR_REPOSITORY_PATH; //$NON-NLS-1$
1945: if (!folderPath.equals("/")) { //$NON-NLS-1$
1946: path += folderPath;
1947: }
1948:
1949: Document fullDoc = getFullSolutionDoc(userSession);
1950:
1951: Element folderElement = getFolderElement(fullDoc, path);
1952: Document systemDoc = null;
1953: if (folderElement != null) {
1954: Element clonedFolderElement = (Element) folderElement
1955: .clone();
1956: removeChildElements(clonedFolderElement);
1957: systemDoc = DocumentHelper
1958: .createDocument((Element) clonedFolderElement
1959: .detach());
1960: systemDoc.setXMLEncoding(LocaleHelper.getSystemEncoding());
1961: } else {
1962: String msg = Messages
1963: .getString(
1964: "AdhocWebService.ERROR_0011_FAILED_TO_LOCATE_PATH", folderPath); //$NON-NLS-1$
1965: throw new AdhocWebServiceException(msg);
1966: }
1967: // TODO sbarkdull
1968: //String tmp = systemDoc.asXML();
1969: return systemDoc;
1970: }
1971:
1972: /**
1973: * @param IPentahoSession userSession
1974: */
1975: private Document createSolutionRepositoryDoc(String solutionName,
1976: String path, IPentahoSession userSession) {
1977: ISolutionRepository repository = PentahoSystem
1978: .getSolutionRepository(userSession);
1979: Document document = repository.getNavigationUIDocument(
1980: solutionName, path, ISolutionRepository.ACTION_EXECUTE);
1981:
1982: return document;
1983: }
1984:
1985: /**
1986: * @param IPentahoSession userSession
1987: */
1988: private void invalidateSolutionRepositoryTree(
1989: IPentahoSession userSession) {
1990: CacheManager cacheManager = PentahoSystem.getCacheManager();
1991: if (null != cacheManager) {
1992: cacheManager.removeFromSessionCache(userSession,
1993: SOLUTION_NAVIGATION_DOCUMENT_MAP);
1994: }
1995: }
1996:
1997: /**
1998: * Get the solution repository name, for instance, "pentaho-solutions".
1999: * @param userSession
2000: * @return String containing the name of the solution repository
2001: */
2002: private static String getSolutionRepositoryName(
2003: IPentahoSession userSession) {
2004: ISolutionRepository repository = PentahoSystem
2005: .getSolutionRepository(userSession);
2006: ISolutionFile rootFolder = repository.getRootFolder();
2007: return rootFolder.getSolution();
2008: }
2009:
2010: /**
2011: * If fullFilename has ".waqr.xreportspec" on the end of it,
2012: * remove it. Otherwise just return fullFilename
2013: * @param fullFilename
2014: * @return
2015: */
2016: private static String getBaseFilename(String fullFilename) {
2017: Matcher m = BASE_WAQR_FILENAME_PATTERN.matcher(fullFilename);
2018: String baseName = fullFilename;
2019: if (m.matches()) {
2020: baseName = m.group(1);
2021: }
2022: return baseName;
2023: }
2024: }
|