ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From oleew...@apache.org
Subject [2/2] ambari git commit: AMBARI-21257. Add ambari prefix for utility and serviceadvisor modules (oleewere)
Date Fri, 16 Jun 2017 11:12:51 GMT
AMBARI-21257. Add ambari prefix for utility and serviceadvisor modules (oleewere)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/1fbb933e
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/1fbb933e
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/1fbb933e

Branch: refs/heads/trunk
Commit: 1fbb933ef91d5a1ccf704e8d043c0ab0f6c30df7
Parents: c52faea
Author: oleewere <oleewere@gmail.com>
Authored: Thu Jun 15 15:49:03 2017 +0200
Committer: oleewere <oleewere@gmail.com>
Committed: Fri Jun 16 13:10:17 2017 +0200

----------------------------------------------------------------------
 ambari-agent/pom.xml                            |   4 +-
 ambari-infra/pom.xml                            |   4 +-
 ambari-logsearch/pom.xml                        |   4 +-
 .../ambari-metrics-timelineservice/pom.xml      |   4 +-
 ambari-metrics/pom.xml                          |  10 +-
 ambari-project/pom.xml                          |   4 +-
 ambari-server/pom.xml                           |  10 +-
 ambari-serviceadvisor/pom.xml                   | 124 +++++++++++
 .../ambari/serviceadvisor/ServiceAdvisor.java   | 147 ++++++++++++
 .../ServiceAdvisorCommandType.java              |  63 ++++++
 ambari-utility/checkstyle.xml                   |  38 ++++
 ambari-utility/pom.xml                          | 145 ++++++++++++
 .../src/main/java/category/AlertTest.java       |  27 +++
 .../main/java/category/AmbariUpgradeTest.java   |  27 +++
 .../src/main/java/category/BlueprintTest.java   |  27 +++
 .../src/main/java/category/FastTest.java        |  27 +++
 .../src/main/java/category/KerberosTest.java    |  27 +++
 .../src/main/java/category/MetricsTest.java     |  27 +++
 .../src/main/java/category/SlowTest.java        |  27 +++
 .../main/java/category/StackUpgradeTest.java    |  27 +++
 .../apache/ambari/annotations/ApiIgnore.java    |  29 +++
 ...AvoidTransactionalOnPrivateMethodsCheck.java |  55 +++++
 .../UndocumentedRestApiOperationCheck.java      |  76 +++++++
 .../ambari/swagger/AmbariSwaggerReader.java     | 222 +++++++++++++++++++
 .../src/main/resources/checkstyle_packages.xml  |  15 ++
 ...dTransactionalOnPrivateMethodsCheckTest.java |  49 ++++
 .../UndocumentedRestApiOperationCheckTest.java  |  53 +++++
 .../ambari/swagger/AmbariSwaggerReaderTest.java | 182 +++++++++++++++
 .../src/test/resources/log4j.properties         |  19 ++
 .../checkstyle/InputRestApiOperation.java       | 138 ++++++++++++
 .../InputTransactionalOnPrivateMethods.java     |  46 ++++
 pom.xml                                         |  16 +-
 serviceadvisor/pom.xml                          | 124 -----------
 .../ambari/serviceadvisor/ServiceAdvisor.java   | 147 ------------
 .../ServiceAdvisorCommandType.java              |  63 ------
 utility/checkstyle.xml                          |  38 ----
 utility/pom.xml                                 | 145 ------------
 utility/src/main/java/category/AlertTest.java   |  27 ---
 .../main/java/category/AmbariUpgradeTest.java   |  27 ---
 .../src/main/java/category/BlueprintTest.java   |  27 ---
 utility/src/main/java/category/FastTest.java    |  27 ---
 .../src/main/java/category/KerberosTest.java    |  27 ---
 utility/src/main/java/category/MetricsTest.java |  27 ---
 utility/src/main/java/category/SlowTest.java    |  27 ---
 .../main/java/category/StackUpgradeTest.java    |  27 ---
 .../apache/ambari/annotations/ApiIgnore.java    |  29 ---
 ...AvoidTransactionalOnPrivateMethodsCheck.java |  55 -----
 .../UndocumentedRestApiOperationCheck.java      |  76 -------
 .../ambari/swagger/AmbariSwaggerReader.java     | 222 -------------------
 .../src/main/resources/checkstyle_packages.xml  |  15 --
 ...dTransactionalOnPrivateMethodsCheckTest.java |  49 ----
 .../UndocumentedRestApiOperationCheckTest.java  |  53 -----
 .../ambari/swagger/AmbariSwaggerReaderTest.java | 182 ---------------
 utility/src/test/resources/log4j.properties     |  19 --
 .../checkstyle/InputRestApiOperation.java       | 138 ------------
 .../InputTransactionalOnPrivateMethods.java     |  46 ----
 56 files changed, 1645 insertions(+), 1645 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-agent/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-agent/pom.xml b/ambari-agent/pom.xml
index 7690fcf..f2add9a 100644
--- a/ambari-agent/pom.xml
+++ b/ambari-agent/pom.xml
@@ -103,8 +103,8 @@
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>utility</groupId>
-      <artifactId>utility</artifactId>
+      <groupId>org.apache.ambari</groupId>
+      <artifactId>ambari-utility</artifactId>
       <scope>test</scope>
       <version>1.0.0.0-SNAPSHOT</version>
     </dependency>

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-infra/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-infra/pom.xml b/ambari-infra/pom.xml
index a5a5b38..07adb3e 100644
--- a/ambari-infra/pom.xml
+++ b/ambari-infra/pom.xml
@@ -178,8 +178,8 @@
   <dependencies>
     <!-- Dependency in order to annotate unit tests with a category. -->
     <dependency>
-      <groupId>utility</groupId>
-      <artifactId>utility</artifactId>
+      <groupId>org.apache.ambari</groupId>
+      <artifactId>ambari-utility</artifactId>
       <version>1.0.0.0-SNAPSHOT</version>
       <scope>test</scope>
     </dependency>

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-logsearch/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-logsearch/pom.xml b/ambari-logsearch/pom.xml
index 6f78abe..af1dc6a 100644
--- a/ambari-logsearch/pom.xml
+++ b/ambari-logsearch/pom.xml
@@ -184,8 +184,8 @@
   <dependencies>
     <!-- Dependency in order to annotate unit tests with a category. -->
     <dependency>
-      <groupId>utility</groupId>
-      <artifactId>utility</artifactId>
+      <groupId>org.apache.ambari</groupId>
+      <artifactId>ambari-utility</artifactId>
       <version>1.0.0.0-SNAPSHOT</version>
       <scope>test</scope>
     </dependency>

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-metrics/ambari-metrics-timelineservice/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-timelineservice/pom.xml b/ambari-metrics/ambari-metrics-timelineservice/pom.xml
index 3419f16..a5eb572 100644
--- a/ambari-metrics/ambari-metrics-timelineservice/pom.xml
+++ b/ambari-metrics/ambari-metrics-timelineservice/pom.xml
@@ -658,8 +658,8 @@
 
     <!-- Dependency in order to annotate unit tests with a category. -->
     <dependency>
-      <groupId>utility</groupId>
-      <artifactId>utility</artifactId>
+      <groupId>org.apache.ambari</groupId>
+      <artifactId>ambari-utility</artifactId>
       <version>1.0.0.0-SNAPSHOT</version>
       <scope>test</scope>
     </dependency>

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-metrics/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-metrics/pom.xml b/ambari-metrics/pom.xml
index 02f9574..b585916 100644
--- a/ambari-metrics/pom.xml
+++ b/ambari-metrics/pom.xml
@@ -22,7 +22,7 @@
   <version>2.0.0.0-SNAPSHOT</version>
   <packaging>pom</packaging>
   <modules>
-    <module>../utility</module>
+    <module>../ambari-utility</module>
     <module>ambari-metrics-common</module>
     <module>ambari-metrics-hadoop-sink</module>
     <module>ambari-metrics-flume-sink</module>
@@ -305,8 +305,8 @@
   <dependencies>
     <!-- Dependency in order to annotate unit tests with a category. -->
     <dependency>
-      <groupId>utility</groupId>
-      <artifactId>utility</artifactId>
+      <groupId>org.apache.ambari</groupId>
+      <artifactId>ambari-utility</artifactId>
       <version>1.0.0.0-SNAPSHOT</version>
       <scope>test</scope>
     </dependency>
@@ -320,8 +320,8 @@
       </properties>
       <dependencies>
         <dependency>
-          <groupId>utility</groupId>
-          <artifactId>utility</artifactId>
+          <groupId>org.apache.ambari</groupId>
+          <artifactId>ambari-utility</artifactId>
           <version>1.0.0.0-SNAPSHOT</version>
         </dependency>
       </dependencies>

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-project/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-project/pom.xml b/ambari-project/pom.xml
index b06bd18..7e1b813 100644
--- a/ambari-project/pom.xml
+++ b/ambari-project/pom.xml
@@ -569,8 +569,8 @@
               <version>${checkstyle.version}</version>
             </dependency>
             <dependency>
-              <groupId>utility</groupId>
-              <artifactId>utility</artifactId>
+              <groupId>org.apache.ambari</groupId>
+              <artifactId>ambari-utility</artifactId>
               <version>1.0.0.0-SNAPSHOT</version>
             </dependency>
           </dependencies>

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-server/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-server/pom.xml b/ambari-server/pom.xml
index ca3b2da..91c35e5 100644
--- a/ambari-server/pom.xml
+++ b/ambari-server/pom.xml
@@ -1660,17 +1660,17 @@
       <artifactId>metrics-jvm</artifactId>
       <version>3.1.0</version>
     </dependency>
-    
+
     <dependency>
-      <groupId>serviceadvisor</groupId>
-      <artifactId>serviceadvisor</artifactId>
+      <groupId>org.apache.ambari</groupId>
+      <artifactId>ambari-serviceadvisor</artifactId>
       <version>1.0.0.0-SNAPSHOT</version>
     </dependency>
 
     <!-- Dependency in order to annotate unit tests with a category. -->
     <dependency>
-      <groupId>utility</groupId>
-      <artifactId>utility</artifactId>
+      <groupId>org.apache.ambari</groupId>
+      <artifactId>ambari-utility</artifactId>
       <version>1.0.0.0-SNAPSHOT</version>
       <scope>provided</scope> <!-- for @ApiIgnore -->
     </dependency>

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-serviceadvisor/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-serviceadvisor/pom.xml b/ambari-serviceadvisor/pom.xml
new file mode 100644
index 0000000..8719cd8
--- /dev/null
+++ b/ambari-serviceadvisor/pom.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <!-- Can compile this project independently, cd ambari-serviceadvisor ; mvn clean package install
+
+  To test independently without needing the rest of Ambari, simply compile and run as,
+  java -jar ambari-serviceadvisor-$VERSION.jar [ACTION] [HOSTS_FILE.json] [SERVICES_FILE.json]
+  -->
+  <groupId>org.apache.ambari</groupId>
+  <artifactId>ambari-serviceadvisor</artifactId>
+  <name>Ambari Service Advisor</name>
+  <version>1.0.0.0-SNAPSHOT</version>
+  <description>Service Advisor</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven.plugins</groupId>
+      <artifactId>maven-assembly-plugin</artifactId>
+      <version>2.6</version>
+    </dependency>
+
+    <!-- Log Factory logging
+    The main class is expected to write to stdout and stderr appropriately.
+    -->
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+      <version>1.2</version>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <version>1.7.20</version>
+    </dependency>
+      <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+      <version>3.0</version>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+      <version>2.4</version>
+    </dependency>
+  </dependencies>
+
+  <pluginRepositories>
+    <pluginRepository>
+      <id>oss.sonatype.org</id>
+      <name>OSS Sonatype Staging</name>
+      <url>https://oss.sonatype.org/content/groups/staging</url>
+    </pluginRepository>
+  </pluginRepositories>
+
+  <packaging>jar</packaging>
+  <!-- Run with mvn clean package .
+  Execute as, java -jar serviceadvisor-$VERSION.jar
+  -->
+  <build>
+    <plugins>
+      <!--
+      The next 2 plugins are to include the main class in the Jar and to create a single jar with all of the dependencies.
+      It conflicts with the maven-compiler-plugin since the jar created is different.
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <manifest>
+              <addClasspath>true</addClasspath>
+              <mainClass>org.apache.ambari.stackadvisor.StackAdvisor</mainClass>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <version>1.6</version>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      -->
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.2</version>
+        <configuration>
+          <source>1.7</source>
+          <target>1.7</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>rpm-maven-plugin</artifactId>
+        <version>2.0.1</version>
+        <executions>
+          <execution>
+            <!-- unbinds rpm creation from maven lifecycle -->
+            <phase>none</phase>
+            <goals>
+              <goal>rpm</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <copyright>2012, Apache Software Foundation</copyright>
+          <group>Development</group>
+          <disabled>true</disabled>
+          <description>Maven Recipe: RPM Package.</description>
+          <mappings/>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisor.java
----------------------------------------------------------------------
diff --git a/ambari-serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisor.java b/ambari-serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisor.java
new file mode 100644
index 0000000..77c482a
--- /dev/null
+++ b/ambari-serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisor.java
@@ -0,0 +1,147 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.serviceadvisor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.lang3.EnumUtils;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Class that can be called either through its jar or using its run method.
+ * The goal is to invoke a Service Advisor.
+ * Right now, it is backward compatible by invoking the python script and does not know which service is affected.
+ */
+public class ServiceAdvisor {
+  protected static Log LOG = LogFactory.getLog(ServiceAdvisor.class);
+
+  private static String USAGE = "Usage: java -jar serviceadvisor.jar [ACTION] [HOSTS_FILE.json] [SERVICES_FILE.json] [OUTPUT.txt] [ERRORS.txt]";
+  private static String PYTHON_STACK_ADVISOR_SCRIPT = "/var/lib/ambari-server/resources/scripts/stack_advisor.py";
+
+  /**
+   * Entry point for calling this class through its jar.
+   * @param args
+   */
+  public static void main(String[] args) {
+    if (args.length != 5) {
+      System.err.println(String.format("Wrong number of arguments. %s", USAGE));
+      System.exit(1);
+    }
+
+    String action = args[0];
+    String hostsFile = args[1];
+    String servicesFile = args[2];
+    String outputFile = args[3];
+    String errorFile = args[4];
+
+    int exitCode = run(action, hostsFile, servicesFile, outputFile, errorFile);
+    System.exit(exitCode);
+  }
+
+  public static int run(String action, String hostsFile, String servicesFile, String outputFile, String errorFile) {
+    LOG.info(String.format("ServiceAdvisor. Received arguments. Action: %s, Hosts File: %s, Services File: %s", action, hostsFile, servicesFile));
+    int returnCode = -1;
+
+    try {
+      ServiceAdvisorCommandType commandType = ServiceAdvisorCommandType.getEnum(action);
+
+      // TODO, load each Service's Service Advisor at Start Time and call it instead of Python command below.
+
+      ProcessBuilder builder = preparePythonShellCommand(commandType, hostsFile, servicesFile, outputFile, errorFile);
+      returnCode = launchProcess(builder);
+    } catch (IllegalArgumentException e) {
+      List<ServiceAdvisorCommandType> values = EnumUtils.getEnumList(ServiceAdvisorCommandType.class);
+      List<String> stringValues = new ArrayList<String>();
+      for (ServiceAdvisorCommandType value : values) {
+        stringValues.add(value.toString());
+      }
+      LOG.error("ServiceAdvisor. Illegal Argument. Action must be one of " + StringUtils.join(stringValues.toArray(), ", "));
+      return -1;
+    }  catch (Exception e) {
+      LOG.error("ServiceAdvisor. Failed with " + e.getMessage());
+      return -1;
+    }
+    return returnCode;
+  }
+
+  /**
+   * Generate a process to invoke a Python command for the old-style Stack Advisor.
+   * @param commandType Command Type
+   * @param hostsFile hosts.json file
+   * @param servicesFile services.json file
+   * @param outputFile output.txt
+   * @param errorFile error.txt
+   * @return Process that can launch.
+   */
+  private static ProcessBuilder preparePythonShellCommand(ServiceAdvisorCommandType commandType, String hostsFile, String servicesFile, String outputFile, String errorFile) {
+    List<String> builderParameters = new ArrayList<String>();
+
+    if (System.getProperty("os.name").contains("Windows")) {
+      builderParameters.add("cmd");
+      builderParameters.add("/c");
+    } else {
+      builderParameters.add("sh");
+      builderParameters.add("-c");
+    }
+
+    StringBuilder commandString = new StringBuilder();
+    commandString.append(PYTHON_STACK_ADVISOR_SCRIPT + " ");
+
+    commandString.append(commandType.toString()).append(" ");
+    commandString.append(hostsFile).append(" ");
+    commandString.append(servicesFile).append(" ");
+    commandString.append("1> ");
+    commandString.append(outputFile).append(" ");
+    commandString.append("2>");
+    commandString.append(errorFile).append(" ");
+
+    builderParameters.add(commandString.toString());
+
+    LOG.info("ServiceAdvisor. Python command is: " + builderParameters.toString());
+
+    return new ProcessBuilder(builderParameters);
+  }
+
+  /**
+   * Launch a process, wait for it to finish, and return its exit code.
+   * @param builder Process Builder
+   * @return Exit Code
+   * @throws Exception
+   */
+  private static int launchProcess(ProcessBuilder builder) throws Exception {
+    int exitCode = -1;
+    Process process = null;
+    try {
+      process = builder.start();
+      exitCode = process.waitFor();
+    } catch (Exception ioe) {
+      String message = "Error executing Service Advisor: ";
+      LOG.error(message, ioe);
+      throw new Exception(message + ioe.getMessage());
+    } finally {
+      if (process != null) {
+        process.destroy();
+      }
+    }
+    return exitCode;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisorCommandType.java
----------------------------------------------------------------------
diff --git a/ambari-serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisorCommandType.java b/ambari-serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisorCommandType.java
new file mode 100644
index 0000000..f067668
--- /dev/null
+++ b/ambari-serviceadvisor/src/main/java/org/apache/ambari/serviceadvisor/ServiceAdvisorCommandType.java
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.ambari.serviceadvisor;
+
+
+// TODO, use this class instead of org.apache.ambari.server.api.services.stackadvisor.commands.StackAdvisorCommandType
+public enum ServiceAdvisorCommandType {
+
+  RECOMMEND_COMPONENT_LAYOUT("recommend-component-layout"),
+
+  VALIDATE_COMPONENT_LAYOUT("validate-component-layout"),
+
+  RECOMMEND_CONFIGURATIONS("recommend-configurations"),
+
+  RECOMMEND_CONFIGURATION_DEPENDENCIES("recommend-configuration-dependencies"),
+
+  VALIDATE_CONFIGURATIONS("validate-configurations");
+  private final String name;
+
+  private ServiceAdvisorCommandType(String name) {
+    this.name = name;
+  }
+
+  public String getValue() {
+    return this.name.toLowerCase();
+  }
+
+  @Override
+  public String toString() {
+    return this.name;
+  }
+
+  /**
+   * Instead of Enum.valueOf("value"), use this method instead to map the string to the correct Enum.
+   * @param name Name with lowercase and dashes.
+   * @return Enum that matches the string.
+   */
+  public static ServiceAdvisorCommandType getEnum(String name) {
+    for (ServiceAdvisorCommandType v : values()) {
+      if (v.getValue().equalsIgnoreCase(name.replace("_", "-"))) {
+        return v;
+      }
+    }
+    throw new IllegalArgumentException();
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/checkstyle.xml
----------------------------------------------------------------------
diff --git a/ambari-utility/checkstyle.xml b/ambari-utility/checkstyle.xml
new file mode 100644
index 0000000..2e7d6f0
--- /dev/null
+++ b/ambari-utility/checkstyle.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!-- Licensed under the Apache License, Version 2.0 (the "License"); you
+  may not use this file except in compliance with the License. You may obtain
+  a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless
+  required by applicable law or agreed to in writing, software distributed
+  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
+  OR CONDITIONS OF ANY KIND, either express or implied. See the License for
+  the specific language governing permissions and limitations under the License.
+  See accompanying LICENSE file. -->
+<!DOCTYPE module PUBLIC
+  "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
+  "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+<module name="Checker">
+  <module name="TreeWalker">
+    <module name="FallThrough"/>
+
+    <!-- imports -->
+    <module name="AvoidStarImport"/>
+    <module name="IllegalImport"/>
+    <module name="ImportOrder">
+      <property name="groups" value="java,javax,org,com,*"/>
+      <property name="ordered" value="true"/>
+      <property name="separated" value="true"/>
+      <property name="option" value="top"/> <!-- static imports -->
+      <property name="sortStaticImportsAlphabetically" value="true"/>
+    </module>
+    <module name="RedundantImport"/>
+    <module name="UnusedImports"/>
+
+    <!-- blocks -->
+    <module name="AvoidNestedBlocks">
+      <property name="allowInSwitchCase" value="true"/>
+    </module>
+    <module name="EmptyBlock">
+      <property name="option" value="text"/>
+    </module>
+  </module>
+</module>

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-utility/pom.xml b/ambari-utility/pom.xml
new file mode 100644
index 0000000..1e86d40
--- /dev/null
+++ b/ambari-utility/pom.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.ambari</groupId>
+    <artifactId>ambari-project</artifactId>
+    <version>2.0.0.0-SNAPSHOT</version>
+    <relativePath>../ambari-project</relativePath>
+  </parent>
+
+  <artifactId>ambari-utility</artifactId>
+  <groupId>org.apache.ambari</groupId>
+  <version>1.0.0.0-SNAPSHOT</version>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.github.kongchen</groupId>
+      <artifactId>swagger-maven-plugin</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>compile</scope>    <!-- has to be compile-time dependency on junit -->
+    </dependency>
+    <dependency>
+      <groupId>com.puppycrawl.tools</groupId>
+      <artifactId>checkstyle</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.puppycrawl.tools</groupId>
+      <artifactId>checkstyle</artifactId>
+      <type>test-jar</type>
+      <version>${checkstyle.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <version>19.0</version> <!-- required for checkstyle -->
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.2</version>
+        <configuration>
+          <source>1.7</source>
+          <target>1.7</target>
+          <useIncrementalCompilation>false</useIncrementalCompilation>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.vafer</groupId>
+        <artifactId>jdeb</artifactId>
+        <version>1.0.1</version>
+        <executions>
+          <execution>
+            <!--Stub execution on direct plugin call - workaround for ambari deb build process-->
+            <id>stub-execution</id>
+            <phase>none</phase>
+            <goals>
+              <goal>jdeb</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <skip>true</skip>
+          <attach>false</attach>
+          <submodules>false</submodules>
+          <controlDir>${project.basedir}/../src/main/package/deb/control</controlDir>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <configuration>
+          <descriptors>
+            <descriptor>${project.parent.basedir}/src/main/assemblies/empty.xml</descriptor>
+          </descriptors>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>rpm-maven-plugin</artifactId>
+        <version>2.0.1</version>
+        <executions>
+          <execution>
+            <!-- unbinds rpm creation from maven lifecycle -->
+            <phase>none</phase>
+            <goals>
+              <goal>rpm</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <copyright>2012, Apache Software Foundation</copyright>
+          <group>Development</group>
+          <disabled>true</disabled>
+          <description>Maven Recipe: RPM Package.</description>
+          <mappings/>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/main/java/category/AlertTest.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/main/java/category/AlertTest.java b/ambari-utility/src/main/java/category/AlertTest.java
new file mode 100644
index 0000000..b6a20ec
--- /dev/null
+++ b/ambari-utility/src/main/java/category/AlertTest.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package category;
+
+/**
+ * Category of unit tests that can be annotated. E.g.,
+ * {@code @Category({ category.AlertTest.class}) }
+ *
+ * A Profile can have csv of categories, in order to run the unit tests like,
+ * mvn clean test -P AlertTests
+ */
+public interface AlertTest {}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/main/java/category/AmbariUpgradeTest.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/main/java/category/AmbariUpgradeTest.java b/ambari-utility/src/main/java/category/AmbariUpgradeTest.java
new file mode 100644
index 0000000..881107a
--- /dev/null
+++ b/ambari-utility/src/main/java/category/AmbariUpgradeTest.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package category;
+
+/**
+ * Category of unit tests that can be annotated. E.g.,
+ * {@code @Category({ category.AmbariUpgradeTest.class}) }
+ *
+ * A Profile can have csv of categories, in order to run the unit tests like,
+ * mvn clean test -P AmbariUpgradeTests
+ */
+public interface AmbariUpgradeTest {}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/main/java/category/BlueprintTest.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/main/java/category/BlueprintTest.java b/ambari-utility/src/main/java/category/BlueprintTest.java
new file mode 100644
index 0000000..cb7871d
--- /dev/null
+++ b/ambari-utility/src/main/java/category/BlueprintTest.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package category;
+
+/**
+ * Category of unit tests that can be annotated. E.g.,
+ * {@code @Category({ category.BlueprintTest.class}) }
+ *
+ * A Profile can have csv of categories, in order to run the unit tests like,
+ * mvn clean test -P BlueprintTests
+ */
+public interface BlueprintTest {}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/main/java/category/FastTest.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/main/java/category/FastTest.java b/ambari-utility/src/main/java/category/FastTest.java
new file mode 100644
index 0000000..a0abddf
--- /dev/null
+++ b/ambari-utility/src/main/java/category/FastTest.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package category;
+
+/**
+ * Category of unit tests that can be annotated. E.g.,
+ * {@code @Category({ category.FastTest.class}) }
+ *
+ * A Profile can have csv of categories, in order to run the unit tests like,
+ * mvn clean test -P FastTests
+ */
+public interface FastTest {}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/main/java/category/KerberosTest.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/main/java/category/KerberosTest.java b/ambari-utility/src/main/java/category/KerberosTest.java
new file mode 100644
index 0000000..f7cebdf
--- /dev/null
+++ b/ambari-utility/src/main/java/category/KerberosTest.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package category;
+
+/**
+ * Category of unit tests that can be annotated. E.g.,
+ * {@code @Category({ category.KerberosTest.class}) }
+ *
+ * A Profile can have csv of categories, in order to run the unit tests like,
+ * mvn clean test -P KerberosTests
+ */
+public interface KerberosTest {}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/main/java/category/MetricsTest.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/main/java/category/MetricsTest.java b/ambari-utility/src/main/java/category/MetricsTest.java
new file mode 100644
index 0000000..a352ae2
--- /dev/null
+++ b/ambari-utility/src/main/java/category/MetricsTest.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package category;
+
+/**
+ * Category of unit tests that can be annotated. E.g.,
+ * {@code @Category({ category.MetricsTest.class}) }
+ *
+ * A Profile can have csv of categories, in order to run the unit tests like,
+ * mvn clean test -P MetricsTests
+ */
+public interface MetricsTest {}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/main/java/category/SlowTest.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/main/java/category/SlowTest.java b/ambari-utility/src/main/java/category/SlowTest.java
new file mode 100644
index 0000000..c1025a9
--- /dev/null
+++ b/ambari-utility/src/main/java/category/SlowTest.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package category;
+
+/**
+ * Category of unit tests that can be annotated. E.g.,
+ * {@code @Category({ category.SlowTest.class}) }
+ *
+ * A Profile can have csv of categories, in order to run the unit tests like,
+ * mvn clean test -P SlowTests
+ */
+public interface SlowTest {}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/main/java/category/StackUpgradeTest.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/main/java/category/StackUpgradeTest.java b/ambari-utility/src/main/java/category/StackUpgradeTest.java
new file mode 100644
index 0000000..20a1723
--- /dev/null
+++ b/ambari-utility/src/main/java/category/StackUpgradeTest.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package category;
+
+/**
+ * Category of unit tests that can be annotated. E.g.,
+ * {@code @Category({ category.StackUpgradeTest.class}) }
+ *
+ * A Profile can have csv of categories, in order to run the unit tests like,
+ * mvn clean test -P StackUpgradeTests
+ */
+public interface StackUpgradeTest {}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/main/java/org/apache/ambari/annotations/ApiIgnore.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/main/java/org/apache/ambari/annotations/ApiIgnore.java b/ambari-utility/src/main/java/org/apache/ambari/annotations/ApiIgnore.java
new file mode 100644
index 0000000..d50c2fd
--- /dev/null
+++ b/ambari-utility/src/main/java/org/apache/ambari/annotations/ApiIgnore.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.METHOD})
+public @interface ApiIgnore {
+  // marker
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/main/java/org/apache/ambari/checkstyle/AvoidTransactionalOnPrivateMethodsCheck.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/main/java/org/apache/ambari/checkstyle/AvoidTransactionalOnPrivateMethodsCheck.java b/ambari-utility/src/main/java/org/apache/ambari/checkstyle/AvoidTransactionalOnPrivateMethodsCheck.java
new file mode 100644
index 0000000..80da103
--- /dev/null
+++ b/ambari-utility/src/main/java/org/apache/ambari/checkstyle/AvoidTransactionalOnPrivateMethodsCheck.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.checkstyle;
+
+import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
+import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
+
+/**
+ * Detects private methods annotated as <code>Transactional</code>.
+ * See https://github.com/google/guice/wiki/Transactions for why this should be
+ * avoided.
+ */
+public class AvoidTransactionalOnPrivateMethodsCheck extends AbstractCheck {
+
+  private static final String ANNOTATION_NAME = "Transactional";
+  public static final String MSG_TRANSACTIONAL_ON_PRIVATE_METHOD = "@" + ANNOTATION_NAME + " should not be used on private methods";
+
+  @Override
+  public int[] getDefaultTokens() {
+    return new int[] { TokenTypes.METHOD_DEF };
+  }
+
+  @Override
+  public void visitToken(DetailAST ast) {
+    DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
+    if (modifiers.findFirstToken(TokenTypes.LITERAL_PRIVATE) != null) {
+      DetailAST annotation = modifiers.findFirstToken(TokenTypes.ANNOTATION);
+      while (annotation != null) {
+        DetailAST name = annotation.findFirstToken(TokenTypes.IDENT);
+        if (name != null && ANNOTATION_NAME.equals(name.getText())) {
+          log(ast.getLineNo(), MSG_TRANSACTIONAL_ON_PRIVATE_METHOD);
+          break;
+        }
+        annotation = annotation.getNextSibling();
+      }
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/main/java/org/apache/ambari/checkstyle/UndocumentedRestApiOperationCheck.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/main/java/org/apache/ambari/checkstyle/UndocumentedRestApiOperationCheck.java b/ambari-utility/src/main/java/org/apache/ambari/checkstyle/UndocumentedRestApiOperationCheck.java
new file mode 100644
index 0000000..c6347db
--- /dev/null
+++ b/ambari-utility/src/main/java/org/apache/ambari/checkstyle/UndocumentedRestApiOperationCheck.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.checkstyle;
+
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
+import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
+import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
+import com.puppycrawl.tools.checkstyle.utils.AnnotationUtility;
+
+/**
+ * REST API operations should either be documented, or marked to be ignored.
+ */
+public class UndocumentedRestApiOperationCheck extends AbstractCheck {
+
+  private static final Set<String> API_ANNOTATIONS = ImmutableSet.of("DELETE", "GET", "HEAD", "OPTIONS", "PUT", "POST");
+  private static final String API_OPERATION = "ApiOperation";
+  private static final String API_IGNORE = "ApiIgnore";
+  public static final String MESSAGE = "REST API operation should be documented";
+
+  @Override
+  public int[] getDefaultTokens() {
+    return new int[] { TokenTypes.METHOD_DEF };
+  }
+
+  @Override
+  public void visitToken(DetailAST ast) {
+    if (isApiOperation(ast) && !isDocumentedApiOperation(ast) && !isIgnoredApi(ast)) {
+      log(ast.getLineNo(), MESSAGE);
+    }
+  }
+
+  private static boolean isApiOperation(DetailAST ast) {
+    DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
+    if (modifiers.findFirstToken(TokenTypes.LITERAL_PRIVATE) != null) {
+      return false;
+    }
+
+    DetailAST annotation = modifiers.findFirstToken(TokenTypes.ANNOTATION);
+    while (annotation != null) {
+      DetailAST name = annotation.findFirstToken(TokenTypes.IDENT);
+      if (name != null && API_ANNOTATIONS.contains(name.getText())) {
+        return true;
+      }
+      annotation = annotation.getNextSibling();
+    }
+
+    return false;
+  }
+
+  private static boolean isDocumentedApiOperation(DetailAST ast) {
+    return AnnotationUtility.containsAnnotation(ast, API_OPERATION);
+  }
+
+  private static boolean isIgnoredApi(DetailAST ast) {
+    return AnnotationUtility.containsAnnotation(ast, API_IGNORE);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/main/java/org/apache/ambari/swagger/AmbariSwaggerReader.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/main/java/org/apache/ambari/swagger/AmbariSwaggerReader.java b/ambari-utility/src/main/java/org/apache/ambari/swagger/AmbariSwaggerReader.java
new file mode 100644
index 0000000..e258fc4
--- /dev/null
+++ b/ambari-utility/src/main/java/org/apache/ambari/swagger/AmbariSwaggerReader.java
@@ -0,0 +1,222 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.swagger;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.Path;
+
+import org.apache.maven.plugin.logging.Log;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.annotation.AnnotationUtils;
+
+import com.github.kongchen.swagger.docgen.reader.JaxrsReader;
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import io.swagger.annotations.Api;
+import io.swagger.models.Operation;
+import io.swagger.models.Swagger;
+import io.swagger.models.Tag;
+import io.swagger.models.parameters.Parameter;
+import io.swagger.models.parameters.PathParameter;
+
+/**
+ * Customized {@link com.github.kongchen.swagger.docgen.reader.ClassSwaggerReader} implementation to
+ * treat nested API's.
+ */
+public class AmbariSwaggerReader extends JaxrsReader {
+
+  /**
+   * Logger instance.
+   */
+  protected final static Logger logger = LoggerFactory.getLogger(AmbariSwaggerReader.class);
+
+  public AmbariSwaggerReader(Swagger swagger, Log LOG) {
+    super(swagger, LOG);
+  }
+
+  private final Map<Class<?>, NestedApiRecord> nestedAPIs = Maps.newHashMap();
+
+  @Override
+  public Swagger getSwagger() {
+    if (null == this.swagger) {
+      this.swagger = new Swagger();
+    }
+    return this.swagger;
+  }
+
+  /**
+   * Original method is overwritten so that to gather information about top level api - nested api relations
+   */
+  @Override
+  public Swagger read(Set<Class<?>> classes) {
+    // scan for and register nested API classes
+    logger.debug("Looking for nested API's");
+    for (Class<?> cls: classes) {
+      logger.debug("Examining API {}", cls.getSimpleName());
+      for (Method method: cls.getMethods()) {
+        Path methodPath = AnnotationUtils.findAnnotation(method, Path.class);
+        if (null != methodPath) {
+          Class<?> returnType = method.getReturnType();
+          Api nestedApi = AnnotationUtils.findAnnotation(returnType, Api.class);
+          Path nestedApiPath = AnnotationUtils.findAnnotation(returnType, Path.class);
+          logger.debug("Examinig API method {}#{}, path={}, returnType={}", cls.getSimpleName(), method.getName(),
+              nestedApiPath != null ? nestedApiPath.value() : null, returnType.getSimpleName());
+          if (null != nestedApi) {
+            if (null != nestedApiPath) {
+              logger.info("This class exists both as top level and nested API: {}, treating it as top level API",
+                  returnType.getName());
+            }
+            else {
+              Path apiPath = AnnotationUtils.findAnnotation(cls, Path.class);
+              String apiPathValue;
+              if (null == apiPath) {
+                logger.warn("Parent api {} also seems to be a nested API. The current version does not support " +
+                    "multi-level nesting.");
+                apiPathValue = "";
+              }
+              else {
+                apiPathValue = apiPath.value();
+              }
+              NestedApiRecord nar = new NestedApiRecord(returnType, cls, apiPathValue, method, methodPath.value());
+              if (nestedAPIs.containsKey(returnType)) {
+                logger.warn("{} is a nested API of multiple top level API's. Ignoring top level API {}", returnType, cls);
+              }
+              else {
+                logger.info("Registering nested API: {}", returnType);
+                nestedAPIs.put(returnType, nar);
+              }
+            }
+          }
+        }
+      }
+    }
+    logger.info("Found {} nested API's", nestedAPIs.size());
+    // With all information gathered, call superclass implementation
+    return super.read(classes);
+  }
+
+  /**
+   * Original method is overwritten to handle nested api's properly
+   */
+  @Override
+  protected Swagger read(Class<?> cls, String parentPath,
+                         String parentMethod,
+                         boolean readHidden,
+                         String[] parentConsumes,
+                         String[] parentProduces,
+                         Map<String, Tag> parentTags,
+                         List<Parameter> parentParameters) {
+    NestedApiRecord nestedApiRecord = nestedAPIs.get(cls);
+    if (null != nestedApiRecord) {
+      logger.info("Processing nested API: {}", nestedApiRecord);
+      // Get the path parameters of the parent API method. All methods of the nested API class should include these
+      // parameters.
+      Operation operation = parseMethod(nestedApiRecord.parentMethod);
+      List<Parameter> pathParameters = ImmutableList.copyOf(
+          Collections2.filter(operation.getParameters(), Predicates.instanceOf(PathParameter.class)));
+      logger.info("Will copy path params from parent method: {}",
+          Lists.transform(pathParameters, new ParameterToName()));
+      return super.read(cls,
+          joinPaths(nestedApiRecord.parentApiPath, nestedApiRecord.parentMethodPath, parentPath),
+          parentMethod, readHidden,
+          parentConsumes, parentProduces, parentTags, pathParameters);
+    }
+    else {
+      logger.info("Processing top level API: {}", cls.getSimpleName());
+      return super.read(cls, parentPath, parentMethod, readHidden, parentConsumes, parentProduces, parentTags, parentParameters);
+    }
+  }
+
+  /**
+   * Joins path elements properly with slashes avoiding duplicate slashes.
+   *
+   * @param firstPath the first path element
+   * @param paths optionally other path elements
+   * @return the joined path
+   */
+  static String joinPaths(String firstPath, String... paths) {
+    StringBuilder joined = new StringBuilder(firstPath);
+    for(String path: paths) {
+      if (path.isEmpty()) { /* NOP */ }
+      else if (joined.length() == 0) {
+        joined.append(path);
+      }
+      else if (joined.charAt(joined.length() - 1) == '/') {
+        if (path.startsWith("/")) {
+          joined.append(path.substring(1, path.length()));
+        }
+        else {
+          joined.append(path);
+        }
+      }
+      else {
+        if (path.startsWith("/")) {
+          joined.append(path);
+        }
+        else {
+          joined.append('/').append(path);
+        }
+
+      }
+    }
+    return joined.toString();
+  }
+}
+
+class ParameterToName implements Function<Parameter, String> {
+  public String apply(Parameter input) {
+    return input.getName();
+  }
+}
+
+class NestedApiRecord {
+  final Class<?> nestedApi;
+  final Class<?> parentApi;
+  final String parentApiPath;
+  final Method parentMethod;
+  final String parentMethodPath;
+
+  public NestedApiRecord(Class<?> nestedApi, Class<?> parentApi, String parentApiPath, Method parentMethod, String parentMethodPath) {
+    this.nestedApi = nestedApi;
+    this.parentApi = parentApi;
+    this.parentApiPath = parentApiPath;
+    this.parentMethod = parentMethod;
+    this.parentMethodPath = parentMethodPath;
+  }
+
+  @Override
+  public String toString() {
+    return "NestedApiRecord {" +
+        "nestedApi=" + nestedApi +
+        ", parentApi=" + parentApi +
+        ", parentApiPath='" + parentApiPath + '\'' +
+        ", parentMethod=" + parentMethod +
+        ", parentMethodPath='" + parentMethodPath + '\'' +
+        '}';
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/main/resources/checkstyle_packages.xml
----------------------------------------------------------------------
diff --git a/ambari-utility/src/main/resources/checkstyle_packages.xml b/ambari-utility/src/main/resources/checkstyle_packages.xml
new file mode 100644
index 0000000..8cf4a44
--- /dev/null
+++ b/ambari-utility/src/main/resources/checkstyle_packages.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Licensed under the Apache License, Version 2.0 (the "License"); you
+  may not use this file except in compliance with the License. You may obtain
+  a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless
+  required by applicable law or agreed to in writing, software distributed
+  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
+  OR CONDITIONS OF ANY KIND, either express or implied. See the License for
+  the specific language governing permissions and limitations under the License.
+  See accompanying LICENSE file. -->
+<!DOCTYPE checkstyle-packages PUBLIC
+  "-//Puppy Crawl//DTD Package Names 1.0//EN"
+  "http://www.puppycrawl.com/dtds/packages_1_0.dtd">
+<checkstyle-packages>
+  <package name="org.apache.ambari.checkstyle"/>
+</checkstyle-packages>

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/test/java/org/apache/ambari/checkstyle/AvoidTransactionalOnPrivateMethodsCheckTest.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/test/java/org/apache/ambari/checkstyle/AvoidTransactionalOnPrivateMethodsCheckTest.java b/ambari-utility/src/test/java/org/apache/ambari/checkstyle/AvoidTransactionalOnPrivateMethodsCheckTest.java
new file mode 100644
index 0000000..bfdbfa1
--- /dev/null
+++ b/ambari-utility/src/test/java/org/apache/ambari/checkstyle/AvoidTransactionalOnPrivateMethodsCheckTest.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.checkstyle;
+
+import static org.apache.ambari.checkstyle.AvoidTransactionalOnPrivateMethodsCheck.MSG_TRANSACTIONAL_ON_PRIVATE_METHOD;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.junit.Test;
+
+import com.puppycrawl.tools.checkstyle.BaseCheckTestSupport;
+import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
+
+public class AvoidTransactionalOnPrivateMethodsCheckTest extends BaseCheckTestSupport {
+
+  @Override
+  protected String getPath(String filename) throws IOException {
+    return new File("src/test/resources/org/apache/ambari/checkstyle/" + filename)
+      .getCanonicalPath();
+  }
+
+  @Test
+  public void transactionalOnPrivateMethod() throws Exception {
+    final DefaultConfiguration config = createCheckConfig(AvoidTransactionalOnPrivateMethodsCheck.class);
+    final String[] expected = {
+      "32: " + MSG_TRANSACTIONAL_ON_PRIVATE_METHOD,
+      "41: " + MSG_TRANSACTIONAL_ON_PRIVATE_METHOD,
+    };
+
+    verify(config, getPath("InputTransactionalOnPrivateMethods.java"), expected);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/test/java/org/apache/ambari/checkstyle/UndocumentedRestApiOperationCheckTest.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/test/java/org/apache/ambari/checkstyle/UndocumentedRestApiOperationCheckTest.java b/ambari-utility/src/test/java/org/apache/ambari/checkstyle/UndocumentedRestApiOperationCheckTest.java
new file mode 100644
index 0000000..7caf3cf
--- /dev/null
+++ b/ambari-utility/src/test/java/org/apache/ambari/checkstyle/UndocumentedRestApiOperationCheckTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.checkstyle;
+
+import static org.apache.ambari.checkstyle.UndocumentedRestApiOperationCheck.MESSAGE;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.junit.Test;
+
+import com.puppycrawl.tools.checkstyle.BaseCheckTestSupport;
+import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
+
+public class UndocumentedRestApiOperationCheckTest extends BaseCheckTestSupport {
+
+  @Override
+  protected String getPath(String filename) throws IOException {
+    return new File("src/test/resources/org/apache/ambari/checkstyle/" + filename)
+      .getCanonicalPath();
+  }
+
+  @Test
+  public void test() throws Exception {
+    final DefaultConfiguration config = createCheckConfig(UndocumentedRestApiOperationCheck.class);
+    final String[] expected = {
+      "36: " + MESSAGE,
+      "53: " + MESSAGE,
+      "70: " + MESSAGE,
+      "87: " + MESSAGE,
+      "104: " + MESSAGE,
+      "121: " + MESSAGE
+    };
+
+    verify(config, getPath("InputRestApiOperation.java"), expected);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/test/java/org/apache/ambari/swagger/AmbariSwaggerReaderTest.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/test/java/org/apache/ambari/swagger/AmbariSwaggerReaderTest.java b/ambari-utility/src/test/java/org/apache/ambari/swagger/AmbariSwaggerReaderTest.java
new file mode 100644
index 0000000..a102152
--- /dev/null
+++ b/ambari-utility/src/test/java/org/apache/ambari/swagger/AmbariSwaggerReaderTest.java
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.swagger;
+
+import static org.easymock.EasyMock.createMock;
+import static org.junit.Assert.assertEquals ;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+
+import org.apache.commons.collections.set.ListOrderedSet;
+import org.apache.maven.plugin.logging.Log;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.models.Response;
+import io.swagger.models.Swagger;
+import io.swagger.models.parameters.Parameter;
+import io.swagger.models.parameters.PathParameter;
+
+public class AmbariSwaggerReaderTest {
+
+
+  /**
+   * Test the {@link AmbariSwaggerReader#joinPaths(String, String...)} method
+   */
+  @Test
+  public void testJoinPaths() {
+    assertEquals("/toplevel/nested/{param}/list",
+        AmbariSwaggerReader.joinPaths("", "/", "/", "", "toplevel", "/nested/", "/{param}", "list"));
+    assertEquals("/toplevel/nested/{param}/list",
+        AmbariSwaggerReader.joinPaths("/", "toplevel", "", "/nested/", "/", "/{param}", "list", ""));
+  }
+
+  /**
+   * Test the basic case: one top level API and one nested API, each with one operation
+   */
+  @Test
+  public void swaggerBasicCase() {
+    AmbariSwaggerReader asr = new AmbariSwaggerReader(null, createMock(Log.class));
+    Swagger swagger = asr.read(ImmutableSet.of(TopLevelAPI.class, NestedAPI.class));
+    assertEquals(ImmutableSet.of("/toplevel/top", "/toplevel/{param}/nested/list"),
+        swagger.getPaths().keySet());
+    assertPathParamsExist(swagger, "/toplevel/{param}/nested/list", "param");
+  }
+
+  /**
+   * Test conflicting nested API's (the same API's are returned from different top level API's).
+   * In this case the nested API should be associated to the first processed top level API.
+   */
+  @Test
+  public void swaggerConflictingNestedApis() {
+    AmbariSwaggerReader asr = new AmbariSwaggerReader(null, createMock(Log.class));
+    ListOrderedSet classes = ListOrderedSet.decorate(
+        Lists.newArrayList(TopLevelAPI.class, AnotherTopLevelAPI.class, NestedAPI.class));
+    Swagger swagger = asr.read(classes);
+    assertEquals(
+        ImmutableSet.of("/toplevel/top", "/toplevel/{param}/nested/list", "/toplevel2/anotherTop"),
+        swagger.getPaths().keySet());
+    assertPathParamsExist(swagger, "/toplevel/{param}/nested/list", "param");
+  }
+
+  /**
+   * If an API is both top level (the class has a @Path annotation) and nested (class is a return type of an
+   * API operation) then it should be treated as top level.
+   */
+  @Test
+  public void swaggerApiThatIsBothTopLevelAndNestedIsCountedAsTopLevel() {
+    AmbariSwaggerReader asr = new AmbariSwaggerReader(null, createMock(Log.class));
+    Swagger swagger = asr.read(ImmutableSet.of(YetAnotherTopLevelAPI.class, NestedAndTopLevelAPI.class));
+    assertEquals(ImmutableSet.of("/toplevel3/yetAnotherTop", "/canBeReachedFromTopToo/list"),
+        swagger.getPaths().keySet());
+  }
+
+
+  /**
+   * Verify that the top level API's path parameters are transferred to the nested API.
+   */
+  private static void assertPathParamsExist(Swagger swagger, String path, String... expectedPathParams) {
+    List<Parameter> parameters = swagger.getPath(path).getGet().getParameters();
+    assertNotNull("No path parameters for path: " + path, parameters);
+    Set<String> pathParamNames = new HashSet<>();
+    for (Parameter param: parameters) {
+      if (param instanceof PathParameter) {
+        pathParamNames.add(param.getName());
+      }
+    }
+    Set<String> missingPathParams = Sets.difference(ImmutableSet.copyOf(expectedPathParams), pathParamNames);
+    assertTrue("Expected path params for [" + path + "] are missing: " + missingPathParams, missingPathParams.isEmpty());
+  }
+
+}
+
+@Path("/toplevel")
+@Api(value = "Top Level", description = "A top level API")
+abstract class TopLevelAPI {
+
+  @GET
+  @Path("/top")
+  @ApiOperation(value = "list")
+  public abstract Response getList();
+
+  @Path("{param}/nested")
+  public abstract NestedAPI getNested(@ApiParam @PathParam(value = "param") String param);
+}
+
+@Path("/toplevel2")
+@Api(value = "Top Level 2", description = "Another top level API")
+abstract class AnotherTopLevelAPI {
+
+  @GET
+  @Path("/anotherTop")
+  @ApiOperation(value = "list")
+  public abstract Response getList();
+
+  @Path("{param}/anotherNested")
+  public abstract NestedAPI getSecondNested(@ApiParam @PathParam(value = "param") String param);
+
+}
+
+@Path("/toplevel3")
+@Api(value = "Top Level 3", description = "Yet another top level API")
+abstract class YetAnotherTopLevelAPI {
+
+  @GET
+  @Path("/yetAnotherTop")
+  @ApiOperation(value = "list")
+  public abstract Response getList();
+
+  @Path("{param}/nested")
+  public abstract NestedAPI getFirstNested(@ApiParam @PathParam(value = "param") String param);
+
+}
+
+@Api(value = "Nested", description = "A nested API")
+abstract class NestedAPI {
+
+  @GET
+  @Path("/list")
+  @ApiOperation(value = "list")
+  public abstract Response getList();
+
+}
+
+@Path("/canBeReachedFromTopToo")
+@Api(value = "Nested and Top Level", description = "An API that is both nested and top level")
+abstract class NestedAndTopLevelAPI {
+
+  @GET
+  @Path("/list")
+  @ApiOperation(value = "list")
+  public abstract Response getList();
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/ambari-utility/src/test/resources/log4j.properties b/ambari-utility/src/test/resources/log4j.properties
new file mode 100644
index 0000000..c088bb7
--- /dev/null
+++ b/ambari-utility/src/test/resources/log4j.properties
@@ -0,0 +1,19 @@
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+# log4j configuration used during build and unit tests
+
+log4j.rootLogger=INFO,stdout
+log4j.threshold=ALL
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/test/resources/org/apache/ambari/checkstyle/InputRestApiOperation.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/test/resources/org/apache/ambari/checkstyle/InputRestApiOperation.java b/ambari-utility/src/test/resources/org/apache/ambari/checkstyle/InputRestApiOperation.java
new file mode 100644
index 0000000..9aa35ba
--- /dev/null
+++ b/ambari-utility/src/test/resources/org/apache/ambari/checkstyle/InputRestApiOperation.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.checkstyle;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+
+import io.swagger.annotations.ApiOperation;
+
+import org.apache.ambari.annotations.ApiIgnore;
+
+/**
+ * Input file for UndocumentedRestApiOperationCheck.
+ */
+public class InputRestApiOperation {
+
+  @DELETE
+  public void undocumentedDELETE() {
+    ;
+  }
+
+  @DELETE
+  @ApiOperation(value = "...")
+  public void documentedDELETE() {
+    ;
+  }
+
+  @DELETE
+  @ApiIgnore
+  public void ignoredDELETE() {
+    ;
+  }
+
+  @HEAD
+  public void undocumentedHEAD() {
+    ;
+  }
+
+  @HEAD
+  @ApiOperation(value = "...")
+  public void documentedHEAD() {
+    ;
+  }
+
+  @HEAD
+  @ApiIgnore
+  public void ignoredHEAD() {
+    ;
+  }
+
+  @GET
+  public void undocumentedGET() {
+    ;
+  }
+
+  @GET
+  @ApiOperation(value = "...")
+  public void documentedGET() {
+    ;
+  }
+
+  @GET
+  @ApiIgnore
+  public void ignoredGET() {
+    ;
+  }
+
+  @OPTIONS
+  public void undocumentedOPTIONS() {
+    ;
+  }
+
+  @OPTIONS
+  @ApiOperation(value = "...")
+  public void documentedOPTIONS() {
+    ;
+  }
+
+  @OPTIONS
+  @ApiIgnore
+  public void ignoredOPTIONS() {
+    ;
+  }
+
+  @POST
+  public void undocumentedPOST() {
+    ;
+  }
+
+  @POST
+  @ApiOperation(value = "...")
+  public void documentedPOST() {
+    ;
+  }
+
+  @POST
+  @ApiIgnore
+  public void ignoredPOST() {
+    ;
+  }
+
+  @PUT
+  public void undocumentedPUT() {
+    ;
+  }
+
+  @PUT
+  @ApiOperation(value = "...")
+  public void documentedPUT() {
+    ;
+  }
+
+  @PUT
+  @ApiIgnore
+  public void ignoredPUT() {
+    ;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/ambari-utility/src/test/resources/org/apache/ambari/checkstyle/InputTransactionalOnPrivateMethods.java
----------------------------------------------------------------------
diff --git a/ambari-utility/src/test/resources/org/apache/ambari/checkstyle/InputTransactionalOnPrivateMethods.java b/ambari-utility/src/test/resources/org/apache/ambari/checkstyle/InputTransactionalOnPrivateMethods.java
new file mode 100644
index 0000000..2ea5444
--- /dev/null
+++ b/ambari-utility/src/test/resources/org/apache/ambari/checkstyle/InputTransactionalOnPrivateMethods.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.checkstyle;
+
+import com.google.inject.persist.Transactional;
+
+/**
+ * Input file for AvoidTransactionalOnPrivateMethodsCheckTest.
+ */
+public class InputTransactionalOnPrivateMethods {
+
+  @Transactional
+  public void publicMethodWithTransactional() {
+    ;
+  }
+
+  @Transactional
+  private void privateMethodWithTransactional() {
+    ;
+  }
+
+  private void privateMethodWithoutTransactional() {
+    ;
+  }
+
+  @Transactional
+  private void otherPrivateMethodWithTransactional() {
+    ;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 4e27ca6..a5aca94 100644
--- a/pom.xml
+++ b/pom.xml
@@ -402,7 +402,7 @@
             <!-- generated DDL-->
             <exclude>**/createDDL.jdbc</exclude>
             <exclude>**/yarn.lock</exclude>
-            <exclude>utility/target/**</exclude>
+            <exclude>ambari-utility/target/**</exclude>
           </excludes>
         </configuration>
         <executions>
@@ -459,7 +459,7 @@
         </property>
       </activation>
       <modules>
-        <module>serviceadvisor</module>
+        <module>ambari-serviceadvisor</module>
         <module>ambari-web</module>
         <module>ambari-project</module>
         <module>ambari-views</module>
@@ -483,7 +483,7 @@
         </property>
       </activation>
       <modules>
-        <module>serviceadvisor</module>
+        <module>ambari-serviceadvisor</module>
         <module>ambari-web</module>
         <module>ambari-project</module>
         <module>ambari-views</module>
@@ -511,7 +511,7 @@
         <module>ambari-shell</module>
         <module>ambari-logsearch</module>
         <module>ambari-infra</module>
-        <module>serviceadvisor</module>
+        <module>ambari-serviceadvisor</module>
       </modules>
     </profile>
     <profile>
@@ -534,7 +534,7 @@
         <module>ambari-shell</module>
         <module>ambari-logsearch</module>
         <module>ambari-infra</module>
-        <module>serviceadvisor</module>
+        <module>ambari-serviceadvisor</module>
         </modules>
     </profile>
     <profile>
@@ -544,9 +544,9 @@
       </modules>
     </profile>
     <profile>
-      <id>serviceadvisor</id>
+      <id>ambari-serviceadvisor</id>
       <modules>
-        <module>serviceadvisor</module>
+        <module>ambari-serviceadvisor</module>
       </modules>
     </profile>
     <profile>
@@ -557,7 +557,7 @@
         </os>
       </activation>
       <modules>
-        <module>serviceadvisor</module>
+        <module>ambari-serviceadvisor</module>
         <module>ambari-web</module>
         <module>ambari-project</module>
         <module>ambari-views</module>

http://git-wip-us.apache.org/repos/asf/ambari/blob/1fbb933e/serviceadvisor/pom.xml
----------------------------------------------------------------------
diff --git a/serviceadvisor/pom.xml b/serviceadvisor/pom.xml
deleted file mode 100644
index 7a68a09..0000000
--- a/serviceadvisor/pom.xml
+++ /dev/null
@@ -1,124 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <!-- Can compile this project independently, cd serviceadvisor ; mvn clean package install
-
-  To test independently without needing the rest of Ambari, simply compile and run as,
-  java -jar serviceadvisor-$VERSION.jar [ACTION] [HOSTS_FILE.json] [SERVICES_FILE.json]
-  -->
-  <groupId>serviceadvisor</groupId>
-  <artifactId>serviceadvisor</artifactId>
-  <name>Service Advisor</name>
-  <version>1.0.0.0-SNAPSHOT</version>
-  <description>Service Advisor</description>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.maven.plugins</groupId>
-      <artifactId>maven-assembly-plugin</artifactId>
-      <version>2.6</version>
-    </dependency>
-
-    <!-- Log Factory logging
-    The main class is expected to write to stdout and stderr appropriately.
-    -->
-    <dependency>
-      <groupId>commons-logging</groupId>
-      <artifactId>commons-logging</artifactId>
-      <version>1.2</version>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-      <version>1.7.20</version>
-    </dependency>
-      <dependency>
-      <groupId>org.apache.commons</groupId>
-      <artifactId>commons-lang3</artifactId>
-      <version>3.0</version>
-    </dependency>
-
-    <dependency>
-      <groupId>commons-lang</groupId>
-      <artifactId>commons-lang</artifactId>
-      <version>2.4</version>
-    </dependency>
-  </dependencies>
-
-  <pluginRepositories>
-    <pluginRepository>
-      <id>oss.sonatype.org</id>
-      <name>OSS Sonatype Staging</name>
-      <url>https://oss.sonatype.org/content/groups/staging</url>
-    </pluginRepository>
-  </pluginRepositories>
-
-  <packaging>jar</packaging>
-  <!-- Run with mvn clean package .
-  Execute as, java -jar serviceadvisor-$VERSION.jar
-  -->
-  <build>
-    <plugins>
-      <!--
-      The next 2 plugins are to include the main class in the Jar and to create a single jar with all of the dependencies.
-      It conflicts with the maven-compiler-plugin since the jar created is different.
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-jar-plugin</artifactId>
-        <configuration>
-          <archive>
-            <manifest>
-              <addClasspath>true</addClasspath>
-              <mainClass>org.apache.ambari.stackadvisor.StackAdvisor</mainClass>
-            </manifest>
-          </archive>
-        </configuration>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-shade-plugin</artifactId>
-        <version>1.6</version>
-        <executions>
-          <execution>
-            <phase>package</phase>
-            <goals>
-              <goal>shade</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-      -->
-      <plugin>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <version>3.2</version>
-        <configuration>
-          <source>1.7</source>
-          <target>1.7</target>
-        </configuration>
-      </plugin>
-      <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>rpm-maven-plugin</artifactId>
-        <version>2.0.1</version>
-        <executions>
-          <execution>
-            <!-- unbinds rpm creation from maven lifecycle -->
-            <phase>none</phase>
-            <goals>
-              <goal>rpm</goal>
-            </goals>
-          </execution>
-        </executions>
-        <configuration>
-          <copyright>2012, Apache Software Foundation</copyright>
-          <group>Development</group>
-          <disabled>true</disabled>
-          <description>Maven Recipe: RPM Package.</description>
-          <mappings/>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-</project>


Mime
View raw message