Build pulsar-adapters (#1)

* Build pulsar-adapters
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000..00c4b58
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,14 @@
+#### Expected behavior
+
+Tell us what should happen
+
+#### Actual behavior
+
+Tell us what happens instead
+
+#### Steps to reproduce
+
+How can we reproduce the issue
+
+#### System configuration
+**Pulsar version**: x.y
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..b9be206
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,30 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: type/bug
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Desktop (please complete the following information):**
+ - OS: [e.g. iOS]
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/enhancement_request.md b/.github/ISSUE_TEMPLATE/enhancement_request.md
new file mode 100644
index 0000000..98adf72
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/enhancement_request.md
@@ -0,0 +1,20 @@
+---
+name: Enhancement request
+about: Suggest an enhancement for this project
+title: ''
+labels: type/enhancement
+assignees: ''
+
+---
+
+**Is your enhancement request related to a problem? Please describe.**
+A clear and concise description of what the enhancement is.
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..5b8022c
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: type/feature
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..0277fbf
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,74 @@
+<!--
+### Contribution Checklist
+  
+  - Name the pull request in the form "[Issue XYZ][component] Title of the pull request", where *XYZ* should be replaced by the actual issue number.
+    Skip *Issue XYZ* if there is no associated github issue for this pull request.
+    Skip *component* if you are unsure about which is the best component. E.g. `[docs] Fix typo in produce method`.
+
+  - Fill out the template below to describe the changes contributed by the pull request. That will give reviewers the context they need to do the review.
+  
+  - Each pull request should address only one issue, not mix up code from multiple issues.
+  
+  - Each commit in the pull request has a meaningful commit message
+
+  - Once all items of the checklist are addressed, remove the above text and this checklist, leaving only the filled out template below.
+
+**(The sections below can be removed for hotfixes of typos)**
+-->
+
+*(If this PR fixes a github issue, please add `Fixes #<xyz>`.)*
+
+Fixes #<xyz>
+
+*(or if this PR is one task of a github issue, please add `Master Issue: #<xyz>` to link to the master issue.)*
+
+Master Issue: #<xyz>
+
+### Motivation
+
+
+*Explain here the context, and why you're making that change. What is the problem you're trying to solve.*
+
+### Modifications
+
+*Describe the modifications you've done.*
+
+### Verifying this change
+
+- [ ] Make sure that the change passes the CI checks.
+
+*(Please pick either of the following options)*
+
+This change is a trivial rework / code cleanup without any test coverage.
+
+*(or)*
+
+This change is already covered by existing tests, such as *(please describe tests)*.
+
+*(or)*
+
+This change added tests and can be verified as follows:
+
+*(example:)*
+  - *Added integration tests for end-to-end deployment with large payloads (10MB)*
+  - *Extended integration test for recovery after broker failure*
+
+### Does this pull request potentially affect one of the following parts:
+
+*If `yes` was chosen, please highlight the changes*
+
+  - Dependencies (does it add or upgrade a dependency): (yes / no)
+  - The public API: (yes / no)
+  - The schema: (yes / no / don't know)
+  - The default values of configurations: (yes / no)
+  - The wire protocol: (yes / no)
+  - The rest endpoints: (yes / no)
+  - The admin cli options: (yes / no)
+  - Anything that affects deployment: (yes / no / don't know)
+
+### Documentation
+
+  - Does this pull request introduce a new feature? (yes / no)
+  - If yes, how is the feature documented? (not applicable / docs / JavaDocs / not documented)
+  - If a feature is not applicable for documentation, explain why?
+  - If a feature is not documented yet in this PR, please create a followup issue for adding the documentation
diff --git a/.github/workflows/unit-test.yaml b/.github/workflows/unit-test.yaml
new file mode 100644
index 0000000..0ac2b5a
--- /dev/null
+++ b/.github/workflows/unit-test.yaml
@@ -0,0 +1,100 @@
+#
+# 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.
+#
+
+name: CI - Unit
+on:
+  pull_request:
+    branches:
+      - master
+  push:
+    branches:
+      - branch-*
+
+env:
+  MAVEN_OPTS: -Dmaven.wagon.httpconnectionManager.ttlSeconds=25 -Dmaven.wagon.http.retryHandler.count=3
+
+jobs:
+  unit-test:
+    name:
+    runs-on: ubuntu-latest
+    container:
+      image: apachepulsar/pulsar-build:latest
+    timeout-minutes: 120
+
+    steps:
+      - name: Cancel Previous Runs
+        uses: styfle/cancel-workflow-action@0.6.0
+        with:
+          access_token: ${{ github.token }}
+
+      - name: Clone Pulsar
+        uses: actions/checkout@v2
+        with:
+          fetch-depth: 1
+          repository: apache/pulsar
+          ref: master
+          path: pulsar
+        
+      - name: checkout
+        uses: actions/checkout@v2
+        with:
+          fetch-depth: 25
+          ref: ${{ github.event.pull_request.head.sha }}
+
+      - name: Cache local Maven repository
+        uses: actions/cache@v2
+        with:
+          path: ~/.m2/repository
+          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+          restore-keys: |
+            ${{ runner.os }}-maven-
+
+      - name: Set up JDK 1.8
+        uses: actions/setup-java@v1
+        with:
+          java-version: 1.8
+
+      - name: Set up Maven
+        uses: apache/pulsar-test-infra/setup-maven@master
+        with:
+          maven-version: 3.6.1
+
+      - name: Build pulsar
+        run: |
+          cd pulsar
+          mvn -q -B -DskipTests -am -pl pulsar-broker install
+
+      - name: Build pulsar adapters
+        run: |
+          mvn clean license:check install
+
+      - name: package surefire artifacts
+        if: failure()
+        run: |
+          rm -rf artifacts
+          mkdir artifacts
+          find . -type d -name "*surefire*" -exec cp --parents -R {} artifacts/ \;
+          zip -r artifacts.zip artifacts
+
+      - uses: actions/upload-artifact@master
+        name: upload surefire-artifacts
+        if: failure()
+        with:
+          name: surefire-artifacts
+          path: artifacts.zip
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..297f31d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,90 @@
+status.html
+.metadata
+test-output
+test-results
+dependency-reduced-pom.xml
+logs
+/data
+pulsar-broker/data/
+pulsar-broker/tmp.*
+pulsar-broker/src/test/resources/log4j2.yaml
+pulsar-functions/worker/test-tenant/
+pulsar-broker/src/test/resources/pulsar-functions-api-examples.jar
+pulsar-functions/runtime/src/test/resources/
+pulsar-functions/worker/src/test/resources/
+*.log
+*.nar
+
+*.versionsBackup
+*/bin
+
+# Eclipse
+.classpath
+.project
+.settings/
+.recommenders/
+.factorypath
+
+# Intellij
+.idea/
+*.iml
+*.iws
+
+# Mac
+**/.DS_Store
+
+# VisualStudioCode artifacts
+.vscode/
+
+# Maven
+log/
+target/
+
+# Python
+*.pyc
+
+# Perf tools
+*.hgrm
+
+# tmp files
+*.pid
+
+# Generated website
+generated-site/
+
+# Ansible and Terraform artifacts
+deployment/terraform-ansible/deploy-pulsar.retry
+deployment/terraform-ansible/aws/.terraform/
+deployment/terraform-ansible/aws/.terraform.tfstate.lock.info
+deployment/terraform-ansible/aws/terraform.tfstate
+deployment/terraform-ansible/aws/terraform.tfstate.backup
+
+# Vagrant
+**/.vagrant
+
+
+pulsar-client-cpp/python/pkg/osx/*/*.bak
+pulsar-client-cpp/python/pkg/osx/*/*.whl
+pulsar-client-cpp/python/wheelhouse
+
+# CI generated files
+.repository
+docker.debug-info
+
+# Yarn
+
+**/yarn.lock
+
+# docusaurus
+
+**/website/i18n/*
+**/website/translated_docs*
+**/website/brodocs/index.html
+**/website/brodocs/navData.js
+**/website/brodocs/documents/*.md
+
+# Avro
+examples/flink/src/main/java/org/apache/flink/avro/generated
+pulsar-flink/src/test/java/org/apache/flink/avro/generated
+pulsar-client/src/test/java/org/apache/pulsar/client/avro/generated
+/build/
diff --git a/README.md b/README.md
index e70ab00..b819fd2 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,24 @@
+<!--
+
+    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.
+
+-->
+
 # Apache Pulsar Adapters
 
 This repository is used for hosting all the adapters maintained and supported by Apache Pulsar PMC.
\ No newline at end of file
diff --git a/buildtools/src/main/resources/log4j2.xml b/buildtools/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..2fdc2d0
--- /dev/null
+++ b/buildtools/src/main/resources/log4j2.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<Configuration status="INFO">
+    <Appenders>
+        <Console name="Console" target="SYSTEM_OUT">
+            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t:%C@%L] %-5level %logger{36} - %msg%n" />
+        </Console>
+    </Appenders>
+    <Loggers>
+        <Root level="warn">
+            <AppenderRef ref="Console" />
+        </Root>
+        <Logger name="org.eclipse.jetty" level="info"/>
+        <Logger name="org.apache.pulsar" level="info"/>
+        <Logger name="org.apache.bookkeeper" level="info"/>
+        <Logger name="org.apache.kafka" level="info"/>
+    </Loggers>
+</Configuration>
diff --git a/buildtools/src/main/resources/pulsar/checkstyle.xml b/buildtools/src/main/resources/pulsar/checkstyle.xml
new file mode 100644
index 0000000..b46c8bf
--- /dev/null
+++ b/buildtools/src/main/resources/pulsar/checkstyle.xml
@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<!DOCTYPE module PUBLIC
+        "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
+        "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<!-- This is a checkstyle configuration file. For descriptions of
+what the following rules do, please see the checkstyle configuration
+page at http://checkstyle.sourceforge.net/config.html -->
+
+<module name="Checker">
+
+    <module name="SuppressWarningsFilter" />
+
+    <module name="FileTabCharacter">
+        <!-- Checks that there are no tab characters in the file. -->
+    </module>
+
+    <module name="RegexpSingleline">
+        <!-- Checks that TODOs don't have stuff in parenthesis, e.g., username. -->
+        <property name="format" value="((//.*)|(\*.*))TODO\(" />
+        <property name="message" value="TODO comments must not include usernames." />
+        <property name="severity" value="error" />
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format" value="\s+$"/>
+        <property name="message" value="Trailing whitespace"/>
+        <property name="severity" value="error"/>
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format" value="Throwables.propagate\("/>
+        <property name="message" value="Throwables.propagate is deprecated"/>
+        <property name="severity" value="error"/>
+    </module>
+
+    <!-- Prevent *Tests.java as tools may not pick them up -->
+    <module name="RegexpOnFilename">
+        <property name="fileNamePattern" value=".*Tests\.java$" />
+    </module>
+
+    <!-- Allow use of comment to suppress javadocstyle -->
+    <module name="SuppressionCommentFilter">
+        <property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)"/>
+        <property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)"/>
+        <property name="checkFormat" value="$1"/>
+    </module>
+    <module name="SuppressionFilter">
+        <property name="file" value="${checkstyle.suppressions.file}" default="suppressions.xml" />
+    </module>
+
+    <!-- Check that every module has a package-info.java -->
+    <module name="JavadocPackage"/>
+
+    <!-- All Java AST specific tests live under TreeWalker module. -->
+    <module name="TreeWalker">
+
+        <module name="SuppressWarningsHolder" />
+
+        <module name="TodoComment">
+            <!-- Checks that disallowed strings are not used in comments.  -->
+            <property name="format" value="(FIXME)|(XXX)|(@author)" />
+        </module>
+
+        <!--
+
+        IMPORT CHECKS
+
+        -->
+
+        <module name="RedundantImport">
+            <!-- Checks for redundant import statements. -->
+            <property name="severity" value="error"/>
+            <message key="import.redundancy"
+                     value="Redundant import {0}."/>
+        </module>
+
+        <module name="ImportOrder">
+            <property name="severity" value="error"/>
+            <!-- This ensures that static imports go first. -->
+            <property name="option" value="top"/>
+            <property name="sortStaticImportsAlphabetically" value="true"/>
+            <property name="tokens" value="STATIC_IMPORT, IMPORT"/>
+            <message key="import.ordering"
+                     value="Import {0} appears after other imports that it should precede"/>
+        </module>
+
+        <module name="AvoidStarImport">
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="IllegalImport">
+            <property name="illegalPkgs" value="autovalue.shaded, avro.shaded, bk-shade, com.google.api.client.repackaged, com.google.appengine.repackaged, io.netty.util.internal"/>
+        </module>
+
+        <module name="RedundantModifier">
+            <!-- Checks for redundant modifiers on various symbol definitions.
+              See: http://checkstyle.sourceforge.net/config_modifier.html#RedundantModifier
+            -->
+            <property name="tokens" value="METHOD_DEF, VARIABLE_DEF, ANNOTATION_FIELD_DEF, INTERFACE_DEF, CLASS_DEF, ENUM_DEF"/>
+        </module>
+
+        <!--
+            IllegalImport cannot blacklist classes, and c.g.api.client.util is used for some shaded
+            code and some useful code. So we need to fall back to Regexp.
+        -->
+        <module name="RegexpSinglelineJava">
+            <property name="format" value="com\.google\.api\.client\.util\.(ByteStreams|Charsets|Collections2|Joiner|Lists|Maps|Objects|Preconditions|Sets|Strings|Throwables)"/>
+        </module>
+
+        <!--
+             Require static importing from Preconditions.
+        -->
+        <module name="RegexpSinglelineJava">
+            <property name="format" value="^import com.google.common.base.Preconditions;$"/>
+            <property name="message" value="Static import functions from Guava Preconditions"/>
+        </module>
+
+        <module name="UnusedImports">
+            <property name="severity" value="error"/>
+            <property name="processJavadoc" value="true"/>
+            <message key="import.unused"
+                     value="Unused import: {0}."/>
+        </module>
+
+        <!--
+
+        JAVADOC CHECKS
+
+        -->
+
+        <!-- Checks for Javadoc comments.                     -->
+        <!-- See http://checkstyle.sf.net/config_javadoc.html -->
+        <module name="JavadocMethod">
+            <property name="scope" value="protected"/>
+            <property name="severity" value="error"/>
+            <property name="allowMissingJavadoc" value="true"/>
+            <property name="allowMissingParamTags" value="true"/>
+            <property name="allowMissingReturnTag" value="true"/>
+            <property name="allowMissingThrowsTags" value="true"/>
+            <property name="allowThrowsTagsForSubclasses" value="true"/>
+            <property name="allowUndeclaredRTE" value="true"/>
+        </module>
+
+        <!-- Check that paragraph tags are used correctly in Javadoc. -->
+        <module name="JavadocParagraph"/>
+
+        <module name="JavadocType">
+            <property name="scope" value="protected"/>
+            <property name="severity" value="error"/>
+            <property name="allowMissingParamTags" value="true"/>
+        </module>
+
+        <module name="JavadocStyle">
+            <property name="severity" value="error"/>
+            <property name="checkHtml" value="true"/>
+        </module>
+
+        <!--
+
+        NAMING CHECKS
+
+        -->
+
+        <!-- Item 38 - Adhere to generally accepted naming conventions -->
+
+        <module name="PackageName">
+            <!-- Validates identifiers for package names against the
+              supplied expression. -->
+            <!-- Here the default checkstyle rule restricts package name parts to
+              seven characters, this is not in line with common practice at Google.
+            -->
+            <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]{1,})*$"/>
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="TypeNameCheck">
+            <!-- Validates static, final fields against the
+            expression "^[A-Z][a-zA-Z0-9]*$". -->
+            <metadata name="altname" value="TypeName"/>
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="ConstantNameCheck">
+            <!-- Validates non-private, static, final fields against the supplied
+            public/package final fields "^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$". -->
+            <metadata name="altname" value="ConstantName"/>
+            <property name="applyToPublic" value="true"/>
+            <property name="applyToProtected" value="true"/>
+            <property name="applyToPackage" value="true"/>
+            <property name="applyToPrivate" value="false"/>
+            <property name="format" value="^([A-Z][A-Za-z0-9_]*|FLAG_.*)$"/>
+            <message key="name.invalidPattern"
+                     value="Variable ''{0}'' should be in ALL_CAPS (if it is a constant) or be private (otherwise)."/>
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="StaticVariableNameCheck">
+            <!-- Validates static, non-final fields against the supplied
+            expression "^[a-z][a-zA-Z0-9]*_?$". -->
+            <metadata name="altname" value="StaticVariableName"/>
+            <property name="applyToPublic" value="true"/>
+            <property name="applyToProtected" value="true"/>
+            <property name="applyToPackage" value="true"/>
+            <property name="applyToPrivate" value="true"/>
+            <property name="format" value="^[a-z][a-zA-Z0-9]*_?$"/>
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="MemberNameCheck">
+            <!-- Validates non-static members against the supplied expression. -->
+            <metadata name="altname" value="MemberName"/>
+            <property name="applyToPublic" value="true"/>
+            <property name="applyToProtected" value="true"/>
+            <property name="applyToPackage" value="true"/>
+            <property name="applyToPrivate" value="true"/>
+            <property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="MethodNameCheck">
+            <!-- Validates identifiers for method names. -->
+            <metadata name="altname" value="MethodName"/>
+            <property name="format" value="(^[a-z][a-zA-Z0-9]*(_[a-zA-Z0-9]+)*$|Void)"/>
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="ParameterName">
+            <!-- Validates identifiers for method parameters against the
+              expression "^[a-z][a-zA-Z0-9]*$". -->
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="LocalFinalVariableName">
+            <!-- Validates identifiers for local final variables against the
+              expression "^[a-z][a-zA-Z0-9]*$". -->
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="LocalVariableName">
+            <!-- Validates identifiers for local variables against the
+              expression "^[a-z][a-zA-Z0-9]*$". -->
+            <property name="severity" value="error"/>
+        </module>
+
+        <!-- Type parameters must be either one of the four blessed letters
+        T, K, V, W, X or else be capital-case terminated with a T,
+        such as MyGenericParameterT -->
+        <module name="ClassTypeParameterName">
+            <property name="format" value="^(((T|K|V|W|X|R)[0-9]*)|([A-Z][a-z][a-zA-Z]*))$"/>
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="MethodTypeParameterName">
+            <property name="format" value="^(((T|K|V|W|X|R)[0-9]*)|([A-Z][a-z][a-zA-Z]*T))$"/>
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="InterfaceTypeParameterName">
+            <property name="format" value="^(((T|K|V|W|X|R)[0-9]*)|([A-Z][a-z][a-zA-Z]*T))$"/>
+            <property name="severity" value="error"/>
+        </module>
+
+        <!--
+
+        LENGTH and CODING CHECKS
+
+        -->
+
+        <module name="LineLength">
+            <!-- Checks if a line is too long. -->
+            <property name="max" value="120"/>
+            <property name="severity" value="error"/>
+
+            <!--
+              The default ignore pattern exempts the following elements:
+                - import statements
+                - long URLs inside comments
+            -->
+
+            <property name="ignorePattern"
+                      value="^(package .*;\s*)|(import .*;\s*)|( *\* .*https?://.*)$"/>
+        </module>
+
+        <module name="LeftCurly">
+            <!-- Checks for placement of the left curly brace ('{'). -->
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="RightCurly">
+            <!-- Checks right curlies on CATCH, ELSE, and TRY blocks are on
+            the same line. e.g., the following example is fine:
+            <pre>
+              if {
+                ...
+              } else
+            </pre>
+            -->
+            <!-- This next example is not fine:
+            <pre>
+              if {
+                ...
+              }
+              else
+            </pre>
+            -->
+            <property name="option" value="same"/>
+            <property name="severity" value="error"/>
+        </module>
+
+        <!-- Checks for braces around if and else blocks -->
+        <module name="NeedBraces">
+            <property name="severity" value="error"/>
+            <property name="tokens" value="LITERAL_IF, LITERAL_ELSE, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO"/>
+        </module>
+
+        <module name="UpperEll">
+            <!-- Checks that long constants are defined with an upper ell.-->
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="FallThrough">
+            <!-- Warn about falling through to the next case statement.  Similar to
+            javac -Xlint:fallthrough, but the check is suppressed if a single-line comment
+            on the last non-blank line preceding the fallen-into case contains 'fall through' (or
+            some other variants that we don't publicized to promote consistency).
+            -->
+            <property name="reliefPattern"
+                      value="fall through|Fall through|fallthru|Fallthru|falls through|Falls through|fallthrough|Fallthrough|No break|NO break|no break|continue on"/>
+            <property name="severity" value="error"/>
+        </module>
+
+        <!-- Checks for over-complicated boolean expressions. -->
+        <module name="SimplifyBooleanExpression"/>
+
+        <!-- Detects empty statements (standalone ";" semicolon). -->
+        <module name="EmptyStatement"/>
+
+        <!--
+
+        WHITESPACE CHECKS
+
+        -->
+
+        <module name="WhitespaceAround">
+            <!-- Checks that various tokens are surrounded by whitespace.
+                 This includes most binary operators and keywords followed
+                 by regular or curly braces.
+            -->
+            <property name="tokens" value="ASSIGN, BAND, BAND_ASSIGN, BOR,
+        BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN,
+        EQUAL, GE, GT, LAND, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE,
+        LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN,
+        LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS,
+        MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION,
+        SL, SL_ASSIGN, SR_ASSIGN, STAR, STAR_ASSIGN"/>
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="WhitespaceAfter">
+            <!-- Checks that commas, semicolons and typecasts are followed by
+                 whitespace.
+            -->
+            <property name="tokens" value="COMMA, SEMI, TYPECAST"/>
+        </module>
+
+        <module name="NoWhitespaceAfter">
+            <!-- Checks that there is no whitespace after various unary operators.
+                 Linebreaks are allowed.
+            -->
+            <property name="tokens" value="BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS,
+        UNARY_PLUS"/>
+            <property name="allowLineBreaks" value="true"/>
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="NoWhitespaceBefore">
+            <!-- Checks that there is no whitespace before various unary operators.
+                 Linebreaks are allowed.
+            -->
+            <property name="tokens" value="SEMI, DOT, POST_DEC, POST_INC"/>
+            <property name="allowLineBreaks" value="true"/>
+            <property name="severity" value="error"/>
+        </module>
+
+        <module name="OperatorWrap">
+            <!-- Checks that operators like + and ? appear at newlines rather than
+                 at the end of the previous line.
+            -->
+            <property name="option" value="NL"/>
+            <property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL,
+        GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD,
+        NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>
+        </module>
+
+        <module name="OperatorWrap">
+            <!-- Checks that assignment operators are at the end of the line. -->
+            <property name="option" value="eol"/>
+            <property name="tokens" value="ASSIGN"/>
+        </module>
+
+        <module name="ParenPad">
+            <!-- Checks that there is no whitespace before close parens or after
+                 open parens.
+            -->
+            <property name="severity" value="error"/>
+        </module>
+
+        <!-- Required to support SuppressWarningsComment -->
+        <module name="FileContentsHolder"/>
+
+    </module>
+</module>
diff --git a/buildtools/src/main/resources/pulsar/suppressions.xml b/buildtools/src/main/resources/pulsar/suppressions.xml
new file mode 100644
index 0000000..d6d38a2
--- /dev/null
+++ b/buildtools/src/main/resources/pulsar/suppressions.xml
@@ -0,0 +1,44 @@
+<?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.
+
+-->
+<!DOCTYPE suppressions PUBLIC
+        "-//Puppy Crawl//DTD Suppressions 1.1//EN"
+        "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
+
+<suppressions>
+    <suppress checks="JavadocPackage" files=".*[\\/]src[\\/]test[\\/].*"/>
+    <suppress checks="JavadocPackage" files=".*[\\/]maven-archetypes[\\/].*"/>
+    <suppress checks="JavadocPackage" files=".*[\\/]examples[\\/].*"/>
+
+    <!-- suppress javadoc check for impl classes -->
+    <suppress checks="JavadocType" files=".*Impl\.java$" />
+
+    <!-- suppress all checks in the generated directories -->
+    <suppress checks=".*" files=".+[\\/]generated[\\/].+\.java" />
+    <suppress checks=".*" files=".+[\\/]generated-sources[\\/].+\.java" />
+    <suppress checks=".*" files=".+[\\/]generated-test-sources[\\/].+\.java" />
+
+    <!-- suppress all checks in the copied code -->
+    <suppress checks=".*" files=".+[\\/]com[\\/]scurrilous[\\/]circe[\\/].+\.java" />
+    
+    <suppress checks=".*" files="MLDataFormats.java" />
+    <suppress checks=".*" files="BitSetRecyclable.java" />
+</suppressions>
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..2ed7599
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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>
+  <packaging>pom</packaging>
+  <parent>
+    <groupId>org.apache.pulsar</groupId>
+    <artifactId>pulsar</artifactId>
+    <version>2.7.0-SNAPSHOT</version>
+  </parent>
+
+  <groupId>org.apache.pulsar</groupId>
+  <artifactId>pulsar-adapters</artifactId>
+
+  <version>2.7.0-SNAPSHOT</version>
+
+  <name>Pulsar Adapters</name>
+  <description>A collections of Pulsar adapters.</description>
+  <url>https://github.com/apache/pulsar-adapters</url>
+
+  <organization>
+    <name>Apache Software Foundation</name>
+    <url>http://www.apache.org/</url>
+  </organization>
+  <inceptionYear>2017</inceptionYear>
+
+  <developers>
+    <developer>
+      <organization>Apache Pulsar developers</organization>
+      <organizationUrl>http://pulsar.apache.org/</organizationUrl>
+    </developer>
+  </developers>
+
+  <licenses>
+    <license>
+      <name>Apache License, Version 2.0</name>
+      <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
+      <distribution>repo</distribution>
+    </license>
+  </licenses>
+
+  <scm>
+    <url>https://github.com/apache/pulsar-adapters</url>
+    <connection>scm:git:https://github.com/apache/pulsar-adapters.git</connection>
+    <developerConnection>scm:git:ssh://git@github.com:apache/pulsar-adapters.git</developerConnection>
+  </scm>
+
+  <ciManagement>
+    <system>Travis</system>
+    <url>https://travis-ci.org/apache/pulsar</url>
+  </ciManagement>
+
+  <issueManagement>
+    <system>Github</system>
+    <url>https://github.com/apache/pulsar-adapters/issues</url>
+  </issueManagement>
+
+  <properties>
+  </properties>
+
+  <modules>
+    <module>pulsar-storm</module>
+    <module>pulsar-flink</module>
+    <module>pulsar-spark</module>
+    <module>pulsar-client-kafka-compat</module>
+    <module>pulsar-log4j2-appender</module>
+  </modules>
+
+  <dependencyManagement>
+  </dependencyManagement>
+
+  <dependencies>
+  </dependencies>
+
+  <build>
+  </build>
+
+  <profiles>
+    <profile>
+      <id>windows</id>
+      <activation>
+        <os>
+          <family>Windows</family>
+        </os>
+      </activation>
+      <properties>
+        <rename.netty.native.libs>rename-netty-native-libs.cmd</rename.netty.native.libs>
+      </properties>
+    </profile>
+  </profiles>
+
+  <repositories>
+    <repository>
+      <id>central</id>
+      <layout>default</layout>
+      <url>https://repo1.maven.org/maven2</url>
+    </repository>
+  </repositories>
+  
+</project>
+
diff --git a/pulsar-client-kafka-compat/pulsar-client-kafka/pom.xml b/pulsar-client-kafka-compat/pulsar-client-kafka/pom.xml
index c666169..a49554f 100644
--- a/pulsar-client-kafka-compat/pulsar-client-kafka/pom.xml
+++ b/pulsar-client-kafka-compat/pulsar-client-kafka/pom.xml
@@ -69,4 +69,28 @@
     </dependency>
   </dependencies>
 
+  <build>
+    <plugins>
+      <!--
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>check-style</id>
+            <phase>verify</phase>
+            <configuration>
+              <configLocation>../buildtools/src/main/resources/pulsar/checkstyle.xml</configLocation>
+              <suppressionsLocation>../buildtools/src/main/resources/pulsar/suppressions.xml</suppressionsLocation>
+              <encoding>UTF-8</encoding>
+            </configuration>
+            <goals>
+              <goal>check</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      -->
+    </plugins>
+  </build>
 </project>
diff --git a/pulsar-flink/pom.xml b/pulsar-flink/pom.xml
index d82efad..7d8a688 100644
--- a/pulsar-flink/pom.xml
+++ b/pulsar-flink/pom.xml
@@ -145,7 +145,6 @@
           </execution>
         </executions>
       </plugin>
-
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-checkstyle-plugin</artifactId>
diff --git a/pulsar-log4j2-appender/pom.xml b/pulsar-log4j2-appender/pom.xml
index a3520ea..7b08f2f 100644
--- a/pulsar-log4j2-appender/pom.xml
+++ b/pulsar-log4j2-appender/pom.xml
@@ -19,56 +19,79 @@
 
 -->
 <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.pulsar</groupId>
-		<artifactId>pulsar</artifactId>
-		<version>2.7.0-SNAPSHOT</version>
-		<relativePath>..</relativePath>
-	</parent>
+  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.pulsar</groupId>
+    <artifactId>pulsar</artifactId>
+    <version>2.7.0-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
 
-	<artifactId>pulsar-log4j2-appender</artifactId>
-	<name>Pulsar Log4j2 Appender</name>
-	<description>Pulsar Log4j2 Appender</description>
+  <artifactId>pulsar-log4j2-appender</artifactId>
+  <name>Pulsar Log4j2 Appender</name>
+  <description>Pulsar Log4j2 Appender</description>
 
-	<dependencies>
-		<dependency>
-			<groupId>${project.groupId}</groupId>
-			<artifactId>pulsar-client</artifactId>
-			<version>${project.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.logging.log4j</groupId>
-			<artifactId>log4j-api</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.logging.log4j</groupId>
-			<artifactId>log4j-core</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.logging.log4j</groupId>
-			<artifactId>log4j-slf4j-impl</artifactId>
-		</dependency>
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>pulsar-client</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-slf4j-impl</artifactId>
+    </dependency>
 
-		<dependency>
-			<groupId>org.apache.logging.log4j</groupId>
-			<artifactId>log4j-api</artifactId>
-			<type>test-jar</type>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+      <type>test-jar</type>
             <scope>test</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.logging.log4j</groupId>
-			<artifactId>log4j-core</artifactId>
-			<type>test-jar</type>
-			<scope>test</scope>
-		</dependency>
-		<!-- Required for AsyncLoggers -->
-		<dependency>
-			<groupId>com.lmax</groupId>
-			<artifactId>disruptor</artifactId>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
-
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <!-- Required for AsyncLoggers -->
+    <dependency>
+      <groupId>com.lmax</groupId>
+      <artifactId>disruptor</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <!--
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>check-style</id>
+            <phase>verify</phase>
+            <configuration>
+              <configLocation>../buildtools/src/main/resources/pulsar/checkstyle.xml</configLocation>
+              <suppressionsLocation>../buildtools/src/main/resources/pulsar/suppressions.xml</suppressionsLocation>
+              <encoding>UTF-8</encoding>
+            </configuration>
+            <goals>
+              <goal>check</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+    -->
+  </build>
 </project>
diff --git a/pulsar-spark/pom.xml b/pulsar-spark/pom.xml
index ac89185..898b460 100644
--- a/pulsar-spark/pom.xml
+++ b/pulsar-spark/pom.xml
@@ -101,6 +101,26 @@
           </execution>
         </executions>
       </plugin>
+      <!--
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>check-style</id>
+            <phase>verify</phase>
+            <configuration>
+              <configLocation>../buildtools/src/main/resources/pulsar/checkstyle.xml</configLocation>
+              <suppressionsLocation>../buildtools/src/main/resources/pulsar/suppressions.xml</suppressionsLocation>
+              <encoding>UTF-8</encoding>
+            </configuration>
+            <goals>
+              <goal>check</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      -->
     </plugins>
   </build>
 </project>
diff --git a/pulsar-storm/pom.xml b/pulsar-storm/pom.xml
index db3121f..0618e91 100644
--- a/pulsar-storm/pom.xml
+++ b/pulsar-storm/pom.xml
@@ -52,14 +52,14 @@
       <version>${storm.version}</version>
       <scope>provided</scope>
       <exclusions>
-      	<exclusion>
-      		<groupId>ch.qos.logback</groupId>
-      		<artifactId>logback-classic</artifactId>
-      	</exclusion>
-      	<exclusion>
-      		<groupId>org.slf4j</groupId>
-      		<artifactId>log4j-over-slf4j</artifactId>
-      	</exclusion>
+        <exclusion>
+          <groupId>ch.qos.logback</groupId>
+          <artifactId>logback-classic</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.slf4j</groupId>
+          <artifactId>log4j-over-slf4j</artifactId>
+        </exclusion>
       </exclusions>
     </dependency>
 
@@ -72,5 +72,27 @@
         <filtering>true</filtering>
       </resource>
     </resources>
+    <!--
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>check-style</id>
+            <phase>verify</phase>
+            <configuration>
+              <configLocation>../buildtools/src/main/resources/pulsar/checkstyle.xml</configLocation>
+              <suppressionsLocation>../buildtools/src/main/resources/pulsar/suppressions.xml</suppressionsLocation>
+              <encoding>UTF-8</encoding>
+            </configuration>
+            <goals>
+              <goal>check</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+    -->
   </build>
 </project>
diff --git a/src/license-header.txt b/src/license-header.txt
new file mode 100644
index 0000000..60b675e
--- /dev/null
+++ b/src/license-header.txt
@@ -0,0 +1,16 @@
+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.
diff --git a/src/rename-netty-native-libs.cmd b/src/rename-netty-native-libs.cmd
new file mode 100644
index 0000000..9003f6d
--- /dev/null
+++ b/src/rename-netty-native-libs.cmd
@@ -0,0 +1,82 @@
+@REM
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM   http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM
+
+@echo off
+
+set ARTIFACT_ID=%1
+set JAR_PATH=%cd%/target/%ARTIFACT_ID%.jar
+set FILE_PREFIX=META-INF/native
+
+:: echo %JAR_PATH%
+:: echo %FILE_PREFIX%
+
+ECHO.
+echo ----- Renaming epoll lib in %JAR_PATH% ------
+set TMP_DIR=%temp%\tmp_pulsar
+
+rd %TMP_DIR% /s /q
+mkdir %TMP_DIR%
+
+set UNZIP_CMD=unzip -q %JAR_PATH% -d %TMP_DIR%
+call %UNZIP_CMD%
+
+:: echo %UNZIP_CMD%
+:: echo %TMP_DIR%
+
+cd /d %TMP_DIR%/%FILE_PREFIX%
+
+:: Loop through the number of groups
+SET Obj_Length=2
+SET Obj[0].FROM=libnetty_transport_native_epoll_x86_64.so
+SET Obj[0].TO=liborg_apache_pulsar_shade_netty_transport_native_epoll_x86_64.so
+SET Obj[1].FROM=libnetty_tcnative_linux_x86_64.so
+SET Obj[1].TO=liborg_apache_pulsar_shade_netty_tcnative_linux_x86_64.so
+SET Obj_Index=0
+
+:LoopStart
+IF %Obj_Index% EQU %Obj_Length% GOTO END
+
+SET Obj_Current.FROM=0
+SET Obj_Current.TO=0
+
+FOR /F "usebackq delims==. tokens=1-3" %%I IN (`SET Obj[%Obj_Index%]`) DO (
+  SET Obj_Current.%%J=%%K.so
+)
+
+echo "Renaming %Obj_Current.FROM% -> %Obj_Current.TO%"
+call ren %Obj_Current.FROM% %Obj_Current.TO%
+
+SET /A Obj_Index=%Obj_Index% + 1
+
+GOTO LoopStart
+:: Loop end
+
+:END
+cd /d %TMP_DIR%
+
+:: Overwrite the original ZIP archive
+rd %JAR_PATH% /s /q
+set ZIP_CMD=zip -q -r %JAR_PATH% .
+:: echo %ZIP_CMD%
+call %ZIP_CMD%
+:: echo %TMP_DIR%
+rd %TMP_DIR% /s /q
+
+exit /b 0
+:: echo.&pause&goto:eof
\ No newline at end of file
diff --git a/src/rename-netty-native-libs.sh b/src/rename-netty-native-libs.sh
new file mode 100755
index 0000000..9835ad8
--- /dev/null
+++ b/src/rename-netty-native-libs.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+#
+# 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.
+#
+
+set -e
+
+ARTIFACT_ID=$1
+JAR_PATH="$PWD/target/$ARTIFACT_ID.jar"
+
+FILE_PREFIX='META-INF/native'
+
+FILES_TO_RENAME=(
+    'libnetty_transport_native_epoll_x86_64.so liborg_apache_pulsar_shade_netty_transport_native_epoll_x86_64.so'
+    'libnetty_tcnative_linux_x86_64.so liborg_apache_pulsar_shade_netty_tcnative_linux_x86_64.so'
+)
+
+echo "----- Renaming epoll lib in $JAR_PATH ------"
+TMP_DIR=`mktemp -d`
+unzip -q $JAR_PATH -d $TMP_DIR
+
+pushd $TMP_DIR
+
+for line in "${FILES_TO_RENAME[@]}"; do
+    read -r -a A <<< "$line"
+    FROM=${A[0]}
+    TO=${A[1]}
+
+    if [ -f $FILE_PREFIX/$FROM ]; then
+        echo "Renaming $FROM -> $TO"
+        mv $FILE_PREFIX/$FROM $FILE_PREFIX/$TO
+    fi
+done
+
+# Overwrite the original ZIP archive
+rm $JAR_PATH
+zip -q -r $JAR_PATH .
+popd
+
+rm -rf $TMP_DIR