Package uk.ac.bbsrc.tgac.miso.notification.core

Source Code of uk.ac.bbsrc.tgac.miso.notification.core.DefaultNotifier$SignedHeaderValueMessageProcessor

/*
* Copyright (c) 2012. The Genome Analysis Centre, Norwich, UK
* MISO project contacts: Robert Davey, Mario Caccamo @ TGAC
* *********************************************************************
*
* This file is part of MISO.
*
* MISO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MISO 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.
*
* You should have received a copy of the GNU General Public License
* along with MISO.  If not, see <http://www.gnu.org/licenses/>.
*
* *********************************************************************
*/

package uk.ac.bbsrc.tgac.miso.notification.core;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.http.HttpMethod;
import org.springframework.integration.Message;
import org.springframework.integration.channel.ChannelInterceptor;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.interceptor.WireTap;
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
import org.springframework.integration.file.filters.CompositeFileListFilter;
import org.springframework.integration.handler.LoggingHandler;
import org.springframework.integration.handler.MethodInvokingMessageProcessor;
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
import org.springframework.integration.http.support.DefaultHttpHeaderMapper;
import org.springframework.integration.ip.tcp.TcpOutboundGateway;
import org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory;
import org.springframework.integration.splitter.MethodInvokingSplitter;
import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
import org.springframework.integration.support.channel.ChannelResolver;
import org.springframework.integration.transformer.HeaderEnricher;
import org.springframework.integration.transformer.MessageTransformingHandler;
import uk.ac.bbsrc.tgac.miso.core.data.type.PlatformType;
import uk.ac.bbsrc.tgac.miso.core.service.integration.ws.pacbio.PacBioServiceWrapper;
import uk.ac.bbsrc.tgac.miso.core.service.integration.ws.solid.SolidServiceWrapper;
import uk.ac.bbsrc.tgac.miso.notification.manager.NotificationRequestManager;
import uk.ac.bbsrc.tgac.miso.notification.util.NotificationMessageEnricher;
import uk.ac.bbsrc.tgac.miso.notification.util.NotificationUtils;
import uk.ac.bbsrc.tgac.miso.tools.run.MultiFileQueueMessageSource;
import uk.ac.bbsrc.tgac.miso.tools.run.RunFolderScanner;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.URI;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
* uk.ac.bbsrc.tgac.miso.notification.service.impl
* <p/>
* Info
*
* @author Rob Davey
* @date 06-Dec-2010
* @since 0.1.4
*/
public class DefaultNotifier {
  protected static final Logger log = LoggerFactory.getLogger(DefaultNotifier.class);

  public static void main(String[] args) {
    log.info("Starting notification system...");
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/notification.xml");

    ChannelResolver channelResolver = new BeanFactoryChannelResolver(context);
    NotificationUtils notificationUtils = new NotificationUtils();

    File propsPath = new File(".", "notification.properties");
    Properties props = new Properties();
    try {
      props.load(new FileReader(propsPath));

      CompositeFileListFilter statusFilter = (CompositeFileListFilter) context.getBean("statusFilter");

      Map<String, Set<File>> allDataPaths = new HashMap<String, Set<File>>();

      for (String platformType : PlatformType.getKeys()) {
        platformType = platformType.toLowerCase();

        if (props.containsKey(platformType + ".splitterBatchSize")) {
          notificationUtils.setSplitterBatchSize(Integer.parseInt(props.getProperty(platformType + ".splitterBatchSize")));
        }

        if (props.containsKey(platformType + ".dataPaths")) {
          log.debug("Resolving " + platformType + ".dataPaths ...");
          String dataPaths = props.getProperty(platformType + ".dataPaths");
          Set<File> paths = new HashSet<File>();
          for (String path : dataPaths.split(",")) {
            File f = new File(path);
            if (f.exists() && f.canRead() && f.isDirectory()) {
              paths.add(f);
              log.debug("Added " + path);
            }
          }

          allDataPaths.put(platformType, paths);

          if (platformType.equals("solid")) {
            for (String key : props.stringPropertyNames()) {
              if (key.startsWith("solid.wsdl.url.")) {
                String serviceName = key.substring(key.lastIndexOf(".") + 1);
                log.debug("Creating service: " + serviceName);
                SolidServiceWrapper ssw = new SolidServiceWrapper(serviceName, URI.create(props.getProperty(key)).toURL());
                context.getBeanFactory().registerSingleton(serviceName, ssw);
              }
            }
          }

          if (platformType.equals("pacbio")) {
            for (String key : props.stringPropertyNames()) {
              if (key.startsWith("pacbio.ws.url.")) {
                String serviceName = key.substring(key.lastIndexOf(".") + 1);
                log.debug("Creating service: " + serviceName);
                PacBioServiceWrapper psw = new PacBioServiceWrapper(serviceName, URI.create(props.getProperty(key)));
                context.getBeanFactory().registerSingleton(serviceName, psw);
              }
            }
          }

          RunFolderScanner rfs = (RunFolderScanner) context.getBean(platformType + "StatusRecursiveScanner");

          MultiFileQueueMessageSource mfqms = new MultiFileQueueMessageSource();
          mfqms.setBeanName(platformType + "MultiFileQueueMessageSource");
          mfqms.setBeanFactory(context.getBeanFactory());
          mfqms.setScanner(rfs);
          mfqms.setFilter(statusFilter);
          mfqms.setDirectories(paths);
          //make sure all the directories are rescanned each poll
          mfqms.setScanEachPoll(false);
          mfqms.afterPropertiesSet();

          SourcePollingChannelAdapter spca = new SourcePollingChannelAdapter();
          spca.setBeanName(platformType + "StatusFileSource");
          spca.setBeanFactory(context.getBeanFactory());
          spca.setMaxMessagesPerPoll(1);

          DynamicTrigger trigger;
          if (props.containsKey(platformType + ".scanRate")) {
            trigger = new DynamicTrigger(Integer.parseInt(props.getProperty(platformType + ".scanRate")), TimeUnit.MILLISECONDS);
          }
          else {
            trigger = new DynamicTrigger(600000, TimeUnit.MILLISECONDS);
          }
          trigger.setFixedRate(false);
          spca.setTrigger(trigger);

          spca.setSource(mfqms);
          spca.setOutputChannel(channelResolver.resolveChannelName(platformType + "StatusFileInputChannel"));
          spca.setAutoStartup(false);
          spca.afterPropertiesSet();

          DirectChannel outputChannel = (DirectChannel) channelResolver.resolveChannelName(platformType + "StatusChannel");
          outputChannel.setBeanName(platformType + "StatusChannel");
          outputChannel.setBeanFactory(context.getBeanFactory());

          if (props.containsKey("wiretap.enabled") && "true".equals(props.get("wiretap.enabled"))) {
            //set up wire tap
            DirectChannel wireTapChannel = (DirectChannel) channelResolver.resolveChannelName("wireTapChannel");
            wireTapChannel.setBeanName("wireTapChannel");
            wireTapChannel.setBeanFactory(context.getBeanFactory());

            LoggingHandler wireTapLogger = new LoggingHandler("TRACE");
            wireTapLogger.setBeanName("OutputWireTapper");
            wireTapLogger.setBeanFactory(context.getBeanFactory());
            wireTapLogger.setLoggerName("wiretap");
            wireTapLogger.setShouldLogFullMessage(true);
            wireTapLogger.afterPropertiesSet();
            wireTapChannel.subscribe(wireTapLogger);

            List<ChannelInterceptor> ints = new ArrayList<ChannelInterceptor>();
            WireTap wt = new WireTap(wireTapChannel);
            ints.add(wt);
            outputChannel.setInterceptors(ints);
          }

          DirectChannel signChannel = (DirectChannel)channelResolver.resolveChannelName(platformType+"MessageSignerChannel");
          signChannel.setBeanFactory(context.getBeanFactory());

          DirectChannel splitterChannel = (DirectChannel)channelResolver.resolveChannelName(platformType+"SplitterChannel");
          splitterChannel.setBeanFactory(context.getBeanFactory());

          if (props.containsKey(platformType + ".http.statusEndpointURIs")) {
            log.debug("Resolving " + platformType + ".http.statusEndpointURIs ...");
            String statusEndpointURIs = props.getProperty(platformType + ".http.statusEndpointURIs");
            for (String uri : statusEndpointURIs.split(",")) {
              //split into multiple messages
              MethodInvokingSplitter mis = new MethodInvokingSplitter(notificationUtils, "splitMessage");
              mis.setBeanName(platformType + "Splitter");
              mis.setBeanFactory(context.getBeanFactory());
              mis.setChannelResolver(channelResolver);
              mis.setOutputChannel(signChannel);
              splitterChannel.subscribe(mis);

              //sign messages and inject url into message headers via HeaderEnricher
              Map<String, SignedHeaderValueMessageProcessor<String>> urlHeaderToSign = new HashMap<String, SignedHeaderValueMessageProcessor<String>>();
              URI su = URI.create(uri);
              urlHeaderToSign.put("x-url", new SignedHeaderValueMessageProcessor<String>(su.getPath()));
              urlHeaderToSign.put("x-user", new SignedHeaderValueMessageProcessor<String>("notification"));
              NotificationMessageEnricher signer = new NotificationMessageEnricher(urlHeaderToSign);
              signer.setMessageProcessor(new MethodInvokingMessageProcessor(notificationUtils, "signMessageHeaders"));

              MessageTransformingHandler mth = new MessageTransformingHandler(signer);
              mth.setBeanName(platformType + "Signer");
              mth.setBeanFactory(context.getBeanFactory());
              mth.setChannelResolver(channelResolver);
              mth.setOutputChannel(outputChannel);
              mth.setRequiresReply(false);
              signChannel.subscribe(mth);

              DefaultHttpHeaderMapper hm = new DefaultHttpHeaderMapper();
              hm.setUserDefinedHeaderPrefix("");
              String[] names = {"Accept", "x-url", "x-signature", "x-user"};
              hm.setBeanFactory(context.getBeanFactory());
              hm.setOutboundHeaderNames(names);
              hm.setInboundHeaderNames(names);

              HttpRequestExecutingMessageHandler statusNotifier = new HttpRequestExecutingMessageHandler(uri);
              statusNotifier.setBeanName(platformType + "StatusNotifier");
              statusNotifier.setBeanFactory(context.getBeanFactory());
              statusNotifier.setChannelResolver(channelResolver);
              statusNotifier.setHttpMethod(HttpMethod.POST);
              statusNotifier.setCharset("UTF-8");
              statusNotifier.setHeaderMapper(hm);
              statusNotifier.setExtractPayload(true);
              statusNotifier.setOrder(3);
              statusNotifier.setRequiresReply(false);
              statusNotifier.setExpectReply(false);

              outputChannel.subscribe(statusNotifier);
            }
          }

          if (props.containsKey(platformType + ".tcp.host") && props.containsKey(platformType + ".tcp.port")) {
            String host = props.getProperty(platformType + ".tcp.host");
            int port = Integer.parseInt(props.getProperty(platformType + ".tcp.port"));

            TcpNetClientConnectionFactory tnccf = new TcpNetClientConnectionFactory(host, port);
            tnccf.setSoTimeout(10000);
            tnccf.setSingleUse(true);

            TcpOutboundGateway tog = new TcpOutboundGateway();
            tog.setBeanName(platformType + "StatusNotifier");
            tog.setBeanFactory(context.getBeanFactory());
            tog.setChannelResolver(channelResolver);
            tog.setConnectionFactory(tnccf);
            tog.setRequestTimeout(10000);
            tog.setRequiresReply(false);
            tog.setOutputChannel(outputChannel);

            outputChannel.subscribe(tog);
          }

          if ((!props.containsKey(platformType + ".tcp.host") || !props.containsKey(platformType + ".tcp.port")) && !props.containsKey(platformType + ".http.statusEndpointURIs")) {
            log.error("You have specified a list of paths to scan, but no valid endpoint to notify. Please add a <platform>.http.statusEndpointURIs property and/or <platform>.tcp.host/port properties in notification.properties");
          }
          else {
            spca.start();
          }
        }
        else {
          log.warn("You have not specified a list of " + platformType + " paths to scan. Please add a " + platformType.toLowerCase() + ".dataPaths property in notification.properties if you wish to track this platform");
        }

        NotificationRequestManager nrm = (NotificationRequestManager)context.getBean("notificationRequestManager");
        nrm.setApplicationContext(context);
        nrm.setDataPaths(allDataPaths);
      }
    }
    catch (FileNotFoundException e) {
      log.error("Cannot find a notification.properties file in the same directory as the notification jar. Please add one");
    }
    catch (IOException e) {
      log.error("Cannot read notification.properties. Please check permissions/availability");
      //e.printStackTrace();
    }
    catch(Exception e) {
      log.error("Something else went wrong:"+e.getMessage());
    }
  }

  static class SignedHeaderValueMessageProcessor<T> implements HeaderEnricher.HeaderValueMessageProcessor<T> {
    // null indicates no explicit setting; use header-enricher's 'default-overwrite' value
    private volatile Boolean overwrite = null;
    private final T value;

    public SignedHeaderValueMessageProcessor(T value) {
      this.value = value;
    }

    public T processMessage(Message<?> message) {
      return this.value;
    }

    public void setOverwrite(Boolean overwrite) {
      this.overwrite = overwrite;
    }

    public Boolean isOverwrite() {
      return this.overwrite;
    }
  }
}
TOP

Related Classes of uk.ac.bbsrc.tgac.miso.notification.core.DefaultNotifier$SignedHeaderValueMessageProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.