/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU General Public License, version 2 as published by the Free Software * Foundation. * * You should have received a copy of the GNU General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * * Copyright 2005-2008 Pentaho Corporation. All rights reserved. * * @created Oct 15, 2005 * @author James Dixon */ package org.pentaho.platform.repository.subscription; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.DateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.pentaho.platform.api.engine.IActionSequence; import org.pentaho.platform.api.engine.IBackgroundExecution; import org.pentaho.platform.api.engine.IContentGenerator; import org.pentaho.platform.api.engine.IMessageFormatter; import org.pentaho.platform.api.engine.IOutputHandler; import org.pentaho.platform.api.engine.IParameterProvider; import org.pentaho.platform.api.engine.IParameterSetter; import org.pentaho.platform.api.engine.IPentahoSession; import org.pentaho.platform.api.engine.IPluginManager; import org.pentaho.platform.api.engine.IRuntimeContext; import org.pentaho.platform.api.engine.ISolutionEngine; import org.pentaho.platform.api.engine.ISystemSettings; import org.pentaho.platform.api.repository.IContentItem; import org.pentaho.platform.api.repository.IContentItemFile; import org.pentaho.platform.api.repository.ISchedule; import org.pentaho.platform.api.repository.ISolutionRepository; import org.pentaho.platform.api.repository.ISubscribeContent; import org.pentaho.platform.api.repository.ISubscription; import org.pentaho.platform.api.repository.ISubscriptionRepository; import org.pentaho.platform.api.scheduler.BackgroundExecutionException; import org.pentaho.platform.engine.core.output.SimpleOutputHandler; import org.pentaho.platform.engine.core.solution.ActionInfo; import org.pentaho.platform.engine.core.solution.PentahoSessionParameterProvider; import org.pentaho.platform.engine.core.solution.SimpleParameterProvider; import org.pentaho.platform.engine.core.system.PentahoSystem; import org.pentaho.platform.engine.services.solution.SimpleParameterSetter; import org.pentaho.platform.engine.services.solution.StandardSettings; import org.pentaho.platform.repository.messages.Messages; import org.pentaho.platform.util.UUIDUtil; import org.pentaho.platform.util.messages.LocaleHelper; import org.pentaho.platform.util.web.SimpleUrlFactory; public class SubscriptionHelper { protected static final Log logger = LogFactory.getLog(SubscriptionHelper.class); public static void editSubscription(final String subscriptionName, final IPentahoSession session, final SimpleUrlFactory urlFactory, final OutputStream outputStream) { ISubscriptionRepository subscriptionRepository = PentahoSystem.get(ISubscriptionRepository.class, session); ISubscription subscription = subscriptionRepository.getSubscription(subscriptionName, session); if (subscription == null) { // TODO surface an error return; } ISubscribeContent content = subscription.getContent(); Map contentParameters = content.getParameters(); SimpleParameterSetter parameters = new SimpleParameterSetter(); parameters.setParameters(contentParameters); SubscriptionHelper.getSubscriptionParameters(subscriptionName, parameters, session); // SimpleParameterProvider parameterProvider = new SimpleParameterProvider( // contentParameters ); // Proposed fix for bug BISERVER-97 by Ezequiel Cuellar // Changed to set parameterXsl from the value specified specified in the Pentaho.xml tag "default-parameter-xsl" // Proposed fix for bug BISERVER-238 by Ezequiel Cuellar // Took away reference to SubscribeForm.xsl and changed it to DefaultParameterForm.xsl ISystemSettings systemSettings = PentahoSystem.getSystemSettings(); String defaultParameterXsl = systemSettings.getSystemSetting("default-parameter-xsl", "DefaultParameterForm.xsl"); //$NON-NLS-1$ //$NON-NLS-2$ ISolutionEngine solutionEngine = (ISolutionEngine) PentahoSystem.get(ISolutionEngine.class, session); solutionEngine.setLoggingLevel(PentahoSystem.loggingLevel); solutionEngine.init(session); solutionEngine.setParameterXsl(defaultParameterXsl); solutionEngine.setForcePrompt(true); Map parameterProviderMap = new HashMap(); parameterProviderMap.put("PRO_EDIT_SUBSCRIPTION", parameters); //$NON-NLS-1$ PentahoSessionParameterProvider sessionParameters = new PentahoSessionParameterProvider(session); parameterProviderMap.put(IParameterProvider.SCOPE_SESSION, sessionParameters); SimpleOutputHandler outputHandler = null; if (outputStream != null) { outputHandler = new SimpleOutputHandler(outputStream, true); } outputHandler.setOutputPreference(IOutputHandler.OUTPUT_TYPE_PARAMETERS); ArrayList messages = new ArrayList(); IRuntimeContext runtime = null; String instanceId = null; boolean persisted = false; ActionInfo contentInfo = ActionInfo.parseActionString(content.getActionReference()); try { runtime = solutionEngine.execute(contentInfo.getSolutionName(), contentInfo.getPath(), contentInfo.getActionName(), "Subscriptions", false, true, instanceId, persisted, parameterProviderMap, outputHandler, null, urlFactory, messages); //$NON-NLS-1$ } finally { runtime.dispose(); } } /* * The regular save subscription */ public static String saveSubscription(final IParameterProvider parameterProvider, final String actionReference, final IPentahoSession userSession) { return SubscriptionHelper.saveSubscription(parameterProvider, actionReference, userSession, false); } /* * Pass in boolean true to save subscription information without requiring a content to be defined - Used for JPovot views */ public static String saveSubscription(final IParameterProvider parameterProvider, final String actionReference, final IPentahoSession userSession, final boolean saveOnly) { if ((userSession == null) || (userSession.getName() == null)) { return Messages.getInstance().getString("SubscriptionHelper.USER_LOGIN_NEEDED"); //$NON-NLS-1$ } String subscriptionId = (String) parameterProvider.getParameter("subscribe-id"); //$NON-NLS-1$ boolean editing = (subscriptionId != null) && (subscriptionId.length() > 0); String subscriptionName = (String) parameterProvider.getParameter("subscribe-name"); //$NON-NLS-1$ String destination = parameterProvider.getStringParameter("destination", null); //$NON-NLS-1$ ISubscriptionRepository subscriptionRepository = PentahoSystem.get(ISubscriptionRepository.class, userSession); if (!editing) { boolean isUniqueName = subscriptionRepository.checkUniqueSubscriptionName(subscriptionName, userSession.getName(), actionReference); if (!isUniqueName) { return Messages.getInstance().getString("SubscriptionHelper.USER_SUBSCRIPTION_NAME_ALREADY_EXISTS", subscriptionName); //$NON-NLS-1$ } } ISolutionRepository solutionRepository = PentahoSystem.get(ISolutionRepository.class, userSession); ActionInfo contentInfo = ActionInfo.parseActionString(actionReference); IActionSequence actionSequence = solutionRepository.getActionSequence(contentInfo.getSolutionName(), contentInfo.getPath(), contentInfo.getActionName(), PentahoSystem.loggingLevel, ISolutionRepository.ACTION_SUBSCRIBE); if (actionSequence == null) { // TODO log an error return Messages.getInstance().getString("SubscriptionHelper.USER_SUBSCRIPTION_NOT_CREATE"); //$NON-NLS-1$ } Map inputs = actionSequence.getInputDefinitionsForParameterProvider(IParameterProvider.SCOPE_REQUEST); ISubscribeContent content = subscriptionRepository.getContentByActionReference(actionReference); if (content == null) { if (saveOnly) { String subContId = UUIDUtil.getUUIDAsString(); content = new SubscribeContent(subContId, actionReference, SubscribeContent.TYPE_REPORT); subscriptionRepository.addContent(content); } else { return (Messages.getInstance().getString("SubscriptionHelper.ACTION_SEQUENCE_NOT_ALLOWED", contentInfo.getActionName())); //$NON-NLS-1$ } } HashMap parameters = new HashMap(); // we need to grab the parameters // TODO load the action sequence from the repository so we can limit this // to just the required parameters or the action name Iterator inputsIterator = inputs.keySet().iterator(); while (inputsIterator.hasNext()) { String parameterName = (String) inputsIterator.next(); Object parameterValue = parameterProvider.getParameter(parameterName); if (parameterValue != null) { parameters.put(parameterName, parameterValue); } } // Just in case it's a PivotView Subscription if (saveOnly) { String parameterValue = (String) parameterProvider.getParameter("mdx"); //$NON-NLS-1$ if (parameterValue != null) { parameters.put("mdx", parameterValue); //$NON-NLS-1$ } } String parameterValue = (String) parameterProvider.getParameter("action2"); //$NON-NLS-1$ if (parameterValue != null) { parameters.put("action", parameterValue); //$NON-NLS-1$ } ISubscription subscription = null; if (editing) { // update an existing subscription subscription = subscriptionRepository.getSubscription(subscriptionId, userSession); if (subscription == null) { editing = false; } else { subscription.setTitle(subscriptionName); subscription.setDestination(destination); subscription.getParameters().clear(); subscription.getParameters().putAll(parameters); subscription.getSchedules().clear(); } } if (!editing) { // create a new subscription subscriptionId = UUIDUtil.getUUIDAsString(); subscription = new Subscription(subscriptionId, userSession.getName(), subscriptionName, content, destination, Subscription.TYPE_PERSONAL, parameters); } // now add the schedules List schedules = subscriptionRepository.getSchedules(); for (int i = 0; i < schedules.size(); i++) { ISchedule schedule = (ISchedule) schedules.get(i); String scheduleId = schedule.getId(); String scheduleValue = (String) parameterProvider.getParameter("schedule-" + scheduleId); //$NON-NLS-1$ if ("true".equals(scheduleValue)) { //$NON-NLS-1$ subscription.addSchedule(schedule); } } if (subscriptionRepository.addSubscription(subscription)) { return Messages.getInstance().getString("SubscriptionHelper.USER_SUBSCRIPTION_CREATED"); //$NON-NLS-1$ } else { // TODO log an error return Messages.getInstance().getString("SubscriptionHelper.USER_SUBSCRIPTION_NOT_CREATE"); //$NON-NLS-1$ } } /* * This method doesn't have any callers, and it introduces un-needed dependencies. So, it's being removed. * * public static boolean scheduleSubscription(final ISubscription subscription) { IScheduler scheduler = PentahoSystem.getScheduler(); return * scheduler.scheduleSubscription(subscription); } */ public static String deleteSubscription(final String subscriptionId, final IPentahoSession userSession) { ISubscriptionRepository subscriptionRepository = PentahoSystem.get(ISubscriptionRepository.class, userSession); ISubscription subscription = subscriptionRepository.getSubscription(subscriptionId, userSession); if (subscription == null) { return Messages.getInstance().getString("SubscriptionHelper.USER_SUBSCRIPTION_NOT_DELETED"); //$NON-NLS-1$ } try { subscriptionRepository.deleteSubscription(subscriptionId, userSession); return Messages.getInstance().getString("SubscriptionHelper.USER_SUBSCRIPTION_DELETED"); //$NON-NLS-1$ } catch (Exception e) { return Messages.getInstance().getString("SubscriptionHelper.USER_SUBSCRIPTION_NOT_DELETED"); //$NON-NLS-1$ } } public static void runSubscription(final String subscriptionName, final IPentahoSession session, final IParameterProvider sessionParameters, final SimpleUrlFactory urlFactory, final IOutputHandler outputHandler) { try { ISubscriptionRepository subscriptionRepository = PentahoSystem.get(ISubscriptionRepository.class, session); ISubscription subscription = subscriptionRepository.getSubscription(subscriptionName, session); if (subscription == null) { // TODO surface an error return; } ISubscribeContent content = subscription.getContent(); Map contentParameters = content.getParameters(); Map subscriptionParameters = subscription.getParameters(); ActionInfo contentInfo = ActionInfo.parseActionString(content.getActionReference()); subscriptionParameters.put("solution", contentInfo.getSolutionName()); //$NON-NLS-1$ subscriptionParameters.put("path", contentInfo.getPath()); //$NON-NLS-1$ subscriptionParameters.put("action", contentInfo.getActionName()); //$NON-NLS-1$ SimpleParameterProvider parameterProvider = new SimpleParameterProvider(contentParameters); parameterProvider.setParameters(subscriptionParameters); ArrayList messages = new ArrayList(); String instanceId = null; boolean persisted = false; String actionName = contentInfo.getActionName(); int lastDot = actionName.lastIndexOf('.'); String type = actionName.substring(lastDot + 1); IPluginManager pluginManager = PentahoSystem.get(IPluginManager.class, session); IContentGenerator generator = pluginManager.getContentGeneratorForType(type, session); if (generator == null) { IRuntimeContext runtime = null; try { ISolutionEngine solutionEngine = PentahoSystem.get(ISolutionEngine.class, session); solutionEngine.setLoggingLevel(PentahoSystem.loggingLevel); solutionEngine.init(session); Map parameterProviderMap = new HashMap(); parameterProviderMap.put(IParameterProvider.SCOPE_REQUEST, parameterProvider); parameterProviderMap.put(IParameterProvider.SCOPE_SESSION, sessionParameters); runtime = solutionEngine.execute(contentInfo.getSolutionName(), contentInfo.getPath(), actionName, "Subscriptions", false, true, instanceId, persisted, parameterProviderMap, outputHandler, null, urlFactory, messages); //$NON-NLS-1$ // see if we need to provide feedback to the caller if (!outputHandler.contentDone()) { IContentItem contentItem = outputHandler.getFeedbackContentItem(); OutputStream outputStream = contentItem.getOutputStream(subscriptionName); if (runtime == null) { // we need an error message... StringBuffer buffer = new StringBuffer(); PentahoSystem.get(IMessageFormatter.class, session).formatFailureMessage("text/html", runtime, buffer); //$NON-NLS-1$ outputStream.write(buffer.toString().getBytes()); contentItem.closeOutputStream(); } else if (runtime.getStatus() == IRuntimeContext.RUNTIME_STATUS_SUCCESS) { StringBuffer buffer = new StringBuffer(); PentahoSystem.get(IMessageFormatter.class, session).formatSuccessMessage("text/html", runtime, buffer, false); //$NON-NLS-1$ outputStream.write(buffer.toString().getBytes()); contentItem.closeOutputStream(); } else { // we need an error message... StringBuffer buffer = new StringBuffer(); PentahoSystem.get(IMessageFormatter.class, session).formatFailureMessage("text/html", runtime, buffer); //$NON-NLS-1$ outputStream.write(buffer.toString().getBytes()); contentItem.closeOutputStream(); } } } catch (Throwable t) { } finally { if (runtime != null) { runtime.dispose(); } } } else { // we have a generator generator.setOutputHandler(outputHandler); generator.setItemName(actionName); generator.setInstanceId(instanceId); generator.setSession(session); Map<String, IParameterProvider> parameterProviders = new HashMap<String, IParameterProvider>(); parameterProviders.put(IParameterProvider.SCOPE_REQUEST, parameterProvider); parameterProviders.put(IParameterProvider.SCOPE_SESSION, new PentahoSessionParameterProvider(session)); generator.setParameterProviders(parameterProviders); try { generator.createContent(); // we succeeded if (!outputHandler.contentDone()) { String message = Messages.getInstance().getString("SubscriptionExecute.DEBUG_FINISHED_EXECUTION", subscriptionName); //$NON-NLS-1$ writeMessage(message.toString(), outputHandler, subscriptionName, contentInfo.getSolutionName(), actionName, instanceId, session); } } catch (Exception e) { e.printStackTrace(); // we need an error message... if (!outputHandler.contentDone()) { String message = Messages.getInstance().getString("PRO_SUBSCRIPTREP.EXCEPTION_WITH_SCHEDULE", subscriptionName); //$NON-NLS-1$ writeMessage(message.toString(), outputHandler, subscriptionName, contentInfo.getSolutionName(), actionName, instanceId, session); } } } } catch (Throwable t) { logger.error("Error Executing Subscription", t); //$NON-NLS-1$ } } protected static void writeMessage(String message, IOutputHandler outputHandler, String subscriptionName, String solutionName, String fileName, String instanceId, IPentahoSession userSession) { IContentItem outputContentItem = outputHandler.getOutputContentItem(IOutputHandler.RESPONSE, IOutputHandler.CONTENT, subscriptionName, null, solutionName, instanceId, "text/html"); //$NON-NLS-1$ outputContentItem.setMimeType("text/html"); //$NON-NLS-1$ try { OutputStream os = outputContentItem.getOutputStream(fileName); os.write(message.getBytes(LocaleHelper.getSystemEncoding())); outputContentItem.closeOutputStream(); } catch (IOException ex) { logger.error(ex.getLocalizedMessage()); } } public static void getArchived(final String subscriptionName, final String fileId, final IPentahoSession session, final IOutputHandler outputHandler) { ISubscriptionRepository subscriptionRepository = PentahoSystem.get(ISubscriptionRepository.class, session); ISubscription subscription = subscriptionRepository.getSubscription(subscriptionName, session); if (subscription == null) { // TODO surface an error return; } IContentItem contentItem = subscriptionRepository.getContentItem(subscriptionName, session); List files = contentItem.getFileVersions(); Iterator fileIterator = files.iterator(); IContentItemFile file = null; while (fileIterator.hasNext()) { file = (IContentItemFile) fileIterator.next(); if (fileId.equals(file.getId())) { break; } } try { IContentItem outoutContentItem = outputHandler.getOutputContentItem(IOutputHandler.RESPONSE, IOutputHandler.CONTENT, null, null, contentItem .getMimeType()); OutputStream outputStream = outoutContentItem.getOutputStream(subscriptionName); if (file == null) { // TODO surface an error outputStream.write(Messages.getInstance().getString("SubscriptionHelper.USER_ARCHIVE_NOT_FOUND").getBytes()); //$NON-NLS-1$ outoutContentItem.closeOutputStream(); return; } outoutContentItem.setMimeType(contentItem.getMimeType()); InputStream inputStream = file.getInputStream(); byte buffer[] = new byte[2048]; int n = inputStream.read(buffer); while (n > 0) { outputStream.write(buffer, 0, n); n = inputStream.read(buffer); } outoutContentItem.closeOutputStream(); } catch (IOException e) { // TODO surface an error SubscriptionHelper.logger.error(null, e); } } public static String getSubscriptionParameters(final String subscriptionName, final IParameterSetter parameters, final IPentahoSession session) { ISubscriptionRepository subscriptionRepository = PentahoSystem.get(ISubscriptionRepository.class, session); ISubscription subscription = subscriptionRepository.getSubscription(subscriptionName, session); if (subscription == null) { // TODO surface an error return Messages.getInstance().getString("SubscriptionHelper.USER_SUBSCRIPTION_DOES_NOT_EXIST"); //$NON-NLS-1$ } // handle the parameters for the subscription Map subscriptionParameters = subscription.getParameters(); Iterator parameterIterator = subscriptionParameters.keySet().iterator(); while (parameterIterator.hasNext()) { String key = (String) parameterIterator.next(); Object value = subscriptionParameters.get(key); parameters.setParameter(key, value); } // handle the main subscription info parameters.setParameter("subscribe-title", subscription.getTitle()); //$NON-NLS-1$ parameters.setParameter("destination", subscription.getDestination()); //$NON-NLS-1$ parameters.setParameter("action", subscription.getContent().getId()); //$NON-NLS-1$ // parameters.setParameter( "editing", "true" ); //$NON-NLS-1$ //$NON-NLS-2$ // add the subscription id so that we can update the object when the user // saves parameters.setParameter("subscribe-id", subscription.getId()); //$NON-NLS-1$ String actionReference = subscription.getContent().getActionReference(); ActionInfo actionInfo = ActionInfo.parseActionString(actionReference); parameters.setParameter("solution", actionInfo.getSolutionName()); //$NON-NLS-1$ parameters.setParameter("path", actionInfo.getPath()); //$NON-NLS-1$ parameters.setParameter("action", actionInfo.getActionName()); //$NON-NLS-1$ // parameters.setParameter( "subscribe", "edit" ); // handle the schedules List schedules = subscription.getSchedules(); ISchedule schedule; for (int i = 0; i < schedules.size(); i++) { schedule = (ISchedule) schedules.get(i); parameters.setParameter("schedule-" + schedule.getId(), "true"); //$NON-NLS-1$ //$NON-NLS-2$ } return null; } public static String deleteSubscriptionArchive(final String subscriptionName, final String fileId, final IPentahoSession session) { ISubscriptionRepository subscriptionRepository = PentahoSystem.get(ISubscriptionRepository.class, session); ISubscription subscription = subscriptionRepository.getSubscription(subscriptionName, session); if (subscription == null) { // TODO surface an error return Messages.getInstance().getString("SubscriptionHelper.USER_SUBSCRIPTION_DOES_NOT_EXIST"); //$NON-NLS-1$ } IContentItem contentItem = subscriptionRepository.getContentItem(subscriptionName, session); if (contentItem == null) { // TODO surface an error return Messages.getInstance().getString("SubscriptionHelper.USER_CONTENT_ITEM_DOES_NOT_EXIST"); //$NON-NLS-1$ } contentItem.removeVersion(fileId); return Messages.getInstance().getString("SubscriptionHelper.USER_ARCHIVE_DELETED"); //$NON-NLS-1$ } public static String createSubscriptionArchive(final String subscriptionName, final IPentahoSession session, final SimpleUrlFactory urlFactory, final IParameterProvider sessionParameters) throws BackgroundExecutionException { ISubscriptionRepository subscriptionRepository = PentahoSystem.get(ISubscriptionRepository.class, session); ISubscription subscription = subscriptionRepository.getSubscription(subscriptionName, session); if (subscription == null) { // TODO surface an error return Messages.getInstance().getString("SubscriptionHelper.USER_SUBSCRIPTION_DOES_NOT_EXIST"); //$NON-NLS-1$ } ISubscribeContent content = subscription.getContent(); if (content == null) { // TODO surface an error return Messages.getInstance().getString("SubscriptionHelper.USER_CONTENT_ITEM_DOES_NOT_EXIST"); //$NON-NLS-1$ } Map contentParameters = content.getParameters(); Map subscriptionParameters = subscription.getParameters(); SimpleParameterProvider parameterProvider = new SimpleParameterProvider(contentParameters); parameterProvider.setParameters(subscriptionParameters); if (subscriptionName != null) { parameterProvider.setParameter("subscribe-name", subscriptionName); //$NON-NLS-1$ } ActionInfo contentInfo = ActionInfo.parseActionString(content.getActionReference()); String actionName = (String) subscriptionParameters.get("action"); //$NON-NLS-1$ if (actionName == null) { actionName = contentInfo.getActionName(); } String path = ActionInfo.buildSolutionPath(contentInfo.getSolutionName(), contentInfo.getPath(), actionName); parameterProvider.setParameter(StandardSettings.ACTIONS_REF, path); // MB - Old code talked directly to quartz classes. IBackgroundExecution be = PentahoSystem.get(IBackgroundExecution.class, "BackgroundSubscriptionExecution", session); //$NON-NLS-1$ return be.backgroundExecuteAction(session, parameterProvider); } public static String getSubscriptionOutputLocation(final String solutionName, final String actionPath, final String actionName) { String outputFolder = actionName.substring(0, actionName.lastIndexOf('.')); return solutionName + "/" + actionPath + "/" + outputFolder + "/subscriptions"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } /** * This formatter works with a date/time string with this format: May 21, 2008 8:29:21 PM * * NOTE: the formatter cannot be shared across threads (since DateFormat implementations are not guaranteed to be thread safe) or across sessions (since * different sessions may have different locales). So create a new one an each call. * * @return */ public static DateFormat getDateTimeFormatter() { return DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.MEDIUM, LocaleHelper.getLocale()); } }