Package com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger

Source Code of com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.GerritDynamicUrlProcessor

/*
*  The MIT License
*
*  Copyright 2012 Sony Mobile Communications AB. All rights reserved.
*
*  Permission is hereby granted, free of charge, to any person obtaining a copy
*  of this software and associated documentation files (the "Software"), to deal
*  in the Software without restriction, including without limitation the rights
*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the Software is
*  furnished to do so, subject to the following conditions:
*
*  The above copyright notice and this permission notice shall be included in
*  all copies or substantial portions of the Software.
*
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
*  THE SOFTWARE.
*/

package com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger;

import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.Branch;
import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.CompareType;
import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.FilePath;
import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.GerritProject;
import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.Topic;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* This class handles the fetching and parsing of URLs for the Dynamic Trigger
* Configuration.
*
* @author Fredrik Abrahamson <fredrik.abrahamson@sonymobile.com>
*/
public final class GerritDynamicUrlProcessor {

    private static final Logger logger = LoggerFactory.getLogger(GerritDynamicUrlProcessor.class);

    private static final String SHORTNAME_PROJECT = "p";
    private static final String SHORTNAME_BRANCH = "b";
    private static final String SHORTNAME_TOPIC = "t";
    private static final String SHORTNAME_FILE = "f";
    private static final String SHORTNAME_FORBIDDEN_FILE = "o";
    private static final int SOCKET_READ_TIMEOUT = 10000;

    /**
     * Private constructor.
     */
    private GerritDynamicUrlProcessor() {
    }

    /**
     * Build the regex pattern for matching lines in the config.
     * @return the pattern
     */
    private static Pattern buildLinePattern() {
      // This is what a line in the file should look like, after all comments and
      // leading and trailing whitespace have been removed:
      // item: one of the characters p (for Project), b (for Branch), t (for Topic) or f (for FilePath)
      // optional whitespace
      // operator: one of the characters = (for Plain), ~ (for RegExp), or ^ (for ANT path)
      // optional whitespace
      // the pattern: everything else on the line
      String projectBranchFile = "^("
              + SHORTNAME_PROJECT
              + "|" + SHORTNAME_BRANCH
              + "|" + SHORTNAME_TOPIC
              + "|" + SHORTNAME_FILE
              + "|" + SHORTNAME_FORBIDDEN_FILE
              + ")";
      String operators = "(";
      boolean firstoperator = true;
      for (CompareType type : CompareType.values()) {
        if (!firstoperator) {
          operators += "|";
        }
        operators += type.getOperator();
        firstoperator = false;
      }
      operators += ")";

      return Pattern.compile(projectBranchFile
              + "\\s*"
              + operators
              + "\\s*(.+)$");
    }

    /**
     * Read and parse the dynamic trigger configuration.
     *
     * @param reader stream from which to read the config
     * @param serverName the name of the Gerrit server configured in the project, could be null.
     *
     * @return List of Gerrit projects
     * @throws ParseException when the fetched content couldn't be parsed
     * @throws IOException for all other kinds of fetch errors
     */
    private static List<GerritProject> readAndParseTriggerConfig(BufferedReader reader, String serverName)
            throws IOException, ParseException {
      Pattern linePattern = buildLinePattern();

      List<GerritProject> dynamicGerritProjects = new ArrayList<GerritProject>();
      List<Branch> branches = null;
      List<Topic> topics = null;
      List<FilePath> filePaths = null;
      List<FilePath> forbiddenFilePaths = null;
      GerritProject dynamicGerritProject = null;

      String line = "";
      int lineNr = 0;
      while ((line = reader.readLine()) != null) {
        ++lineNr;
        // Remove any comments starting with a #
        int commentPos = line.indexOf('#');
        if (commentPos > -1) {
          line = line.substring(0, commentPos);
        }

        // Remove any comments starting with a ;
        commentPos = line.indexOf(';');
        if (commentPos > -1) {
          line = line.substring(0, commentPos);
        }

        // Trim leading and trailing whitespace
        line = line.trim();
        if (line.isEmpty()) {
          continue;
        }

        Matcher matcher = linePattern.matcher(line);
        if (!matcher.matches()) {
          throw new ParseException("Line " + lineNr + ": cannot parse '" + line + "'", lineNr);
        }

        // CS IGNORE MagicNumber FOR NEXT 3 LINES. REASON: ConstantsNotNeeded
        String item = matcher.group(1);
        String oper = matcher.group(2);
        String text = matcher.group(3);
        if (item == null || oper == null || text == null) {
          throw new ParseException("Line " + lineNr + ": cannot parse '" + line + "'", lineNr);
        }
        char operChar = oper.charAt(0);
        CompareType type = CompareType.findByOperator(operChar);

        logger.trace("==> item:({0}) oper:({1}) text:({2})", new Object[]{item, oper, text});

        if (SHORTNAME_PROJECT.equals(item)) { // Project
          // stash previous project to the list
          if (dynamicGerritProject != null) {
            dynamicGerritProjects.add(dynamicGerritProject);
          }

          branches = new ArrayList<Branch>();
          topics = new ArrayList<Topic>();
          filePaths = new ArrayList<FilePath>();
          forbiddenFilePaths = new ArrayList<FilePath>();
          dynamicGerritProject = new GerritProject(type, text, branches, topics, filePaths, forbiddenFilePaths);
        } else if (SHORTNAME_BRANCH.equals(item)) { // Branch
          if (branches == null) {
            throw new ParseException("Line " + lineNr + ": attempt to use 'Branch' before 'Project'", lineNr);
          }
          Branch branch = new Branch(type, text);
          branches.add(branch);
          dynamicGerritProject.setBranches(branches);
        } else if (SHORTNAME_TOPIC.equals(item)) { // Topic
            if (topics == null) {
                throw new ParseException("Line " + lineNr + ": attempt to use 'Topic' before 'Project'", lineNr);
            }
            Topic topic = new Topic(type, text);
            topics.add(topic);
            dynamicGerritProject.setTopics(topics);
        } else if (SHORTNAME_FILE.equals(item)) { // FilePath
          if (filePaths == null) {
            throw new ParseException("Line " + lineNr + ": attempt to use 'FilePath' before 'Project'", lineNr);
          }
          FilePath filePath = new FilePath(type, text);
          filePaths.add(filePath);
          dynamicGerritProject.setFilePaths(filePaths);
        } else if (SHORTNAME_FORBIDDEN_FILE.equals(item)) { // ForbiddenFilePath
          if (forbiddenFilePaths == null) {
            throw new ParseException("Line " + lineNr + ": attempt to use 'ForbiddenFilePath' before 'Project'", lineNr);
          }
          FilePath filePath = new FilePath(type, text);
          forbiddenFilePaths.add(filePath);
          dynamicGerritProject.setForbiddenFilePaths(filePaths);
        }
      }

      // Finally stash the last project to the list
      if (dynamicGerritProject != null) {
        dynamicGerritProjects.add(dynamicGerritProject);
      }

      return dynamicGerritProjects;
    }

    /**
     * This is where the actual fetching is done. If everything goes well,
     * it returns a list of GerritProjects. If the fetched content hasn't changed
     * since the last fetch, it returns null.
     *
     * @param gerritTriggerConfigUrl the URL to fetch
     * @param serverName name of the Gerrit server.
     * @return a list of GerritProjects if successful, or null if no change
     * @throws ParseException when the fetched content couldn't be parsed
     * @throws IOException for all other kinds of fetch errors
     */
    public static List<GerritProject> fetch(String gerritTriggerConfigUrl, String serverName)
            throws IOException, ParseException {

        if (gerritTriggerConfigUrl == null) {
          throw new MalformedURLException("The gerritTriggerConfigUrl is null");
        }
        if (gerritTriggerConfigUrl.isEmpty()) {
          throw new MalformedURLException("The gerritTriggerConfigUrl is empty");
        }

        // Prepare for fetching the URL
        URL url = new URL(gerritTriggerConfigUrl);
        URLConnection connection = url.openConnection();
        connection.setReadTimeout(SOCKET_READ_TIMEOUT);
        connection.setDoInput(true);

        InputStream instream = null;
        BufferedReader reader = null;
        try {
          instream = connection.getInputStream();
          reader = new BufferedReader(new InputStreamReader(instream));
          return readAndParseTriggerConfig(reader, serverName);
        } finally {
          if (reader != null) {
            reader.close();
          } else if (instream != null) {
            instream.close();
          }
        }
    }
}
TOP

Related Classes of com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.GerritDynamicUrlProcessor

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.