Repository: incubator-atlas
Updated Branches:
  refs/heads/master b9ce7a111 -> 1ee2c1bc4


ATLAS-987 Atlas hooks should avoid adding dependent libraries to component 
CLASSPATH (madhan.neethiraj via shwethags)


Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/043d2aa6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/043d2aa6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/043d2aa6

Branch: refs/heads/master
Commit: 043d2aa642e695c7c61c0b771d978fc352caf203
Parents: b9ce7a1
Author: Shwetha GS <[email protected]>
Authored: Fri Jul 8 11:31:10 2016 +0530
Committer: Shwetha GS <[email protected]>
Committed: Fri Jul 8 11:31:10 2016 +0530

----------------------------------------------------------------------
 addons/falcon-bridge-shim/pom.xml               |  52 +++
 .../atlas/falcon/service/AtlasService.java      | 215 ++++++++++++
 addons/falcon-bridge/pom.xml                    |  44 ++-
 addons/hive-bridge-shim/pom.xml                 |  53 +++
 .../org/apache/atlas/hive/hook/HiveHook.java    |  99 ++++++
 addons/hive-bridge/pom.xml                      |  60 ++--
 addons/sqoop-bridge-shim/pom.xml                |  52 +++
 .../org/apache/atlas/sqoop/hook/SqoopHook.java  |  98 ++++++
 addons/sqoop-bridge/pom.xml                     |  61 +++-
 addons/storm-bridge-shim/pom.xml                |  58 ++++
 .../apache/atlas/storm/hook/StormAtlasHook.java | 104 ++++++
 addons/storm-bridge/pom.xml                     |  44 ++-
 plugin-classloader/pom.xml                      |  42 +++
 .../classloader/AtlasPluginClassLoader.java     | 327 +++++++++++++++++++
 .../classloader/AtlasPluginClassLoaderUtil.java | 115 +++++++
 .../classloader/AtlasPluginClassLoaderTest.java |  66 ++++
 pom.xml                                         |  40 ++-
 release-log.txt                                 |   1 +
 18 files changed, 1489 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/addons/falcon-bridge-shim/pom.xml
----------------------------------------------------------------------
diff --git a/addons/falcon-bridge-shim/pom.xml 
b/addons/falcon-bridge-shim/pom.xml
new file mode 100755
index 0000000..ddb62ce
--- /dev/null
+++ b/addons/falcon-bridge-shim/pom.xml
@@ -0,0 +1,52 @@
+<?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>
+    <parent>
+        <artifactId>apache-atlas</artifactId>
+        <groupId>org.apache.atlas</groupId>
+        <version>0.8-incubating-SNAPSHOT</version>
+        <relativePath>../../</relativePath>
+    </parent>
+    <artifactId>falcon-bridge-shim</artifactId>
+    <description>Apache Atlas Falcon Bridge Shim Module</description>
+    <name>Apache Atlas Falcon Bridge Shim</name>
+    <packaging>jar</packaging>
+
+    <properties>
+        <falcon.version>0.8</falcon.version>
+        <checkstyle.failOnViolation>true</checkstyle.failOnViolation>
+    </properties>
+
+    <dependencies>
+        <!-- Logging -->
+        <dependency>
+            <groupId>org.apache.atlas</groupId>
+            <artifactId>atlas-plugin-classloader</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.falcon</groupId>
+            <artifactId>falcon-common</artifactId>
+            <version>${falcon.version}</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/addons/falcon-bridge-shim/src/main/java/org/apache/atlas/falcon/service/AtlasService.java
----------------------------------------------------------------------
diff --git 
a/addons/falcon-bridge-shim/src/main/java/org/apache/atlas/falcon/service/AtlasService.java
 
b/addons/falcon-bridge-shim/src/main/java/org/apache/atlas/falcon/service/AtlasService.java
new file mode 100755
index 0000000..28607fc
--- /dev/null
+++ 
b/addons/falcon-bridge-shim/src/main/java/org/apache/atlas/falcon/service/AtlasService.java
@@ -0,0 +1,215 @@
+/**
+ * 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.atlas.falcon.service;
+
+
+import org.apache.atlas.plugin.classloader.AtlasPluginClassLoader;
+import org.apache.falcon.FalconException;
+import org.apache.falcon.entity.v0.Entity;
+import org.apache.falcon.service.ConfigurationChangeListener;
+import org.apache.falcon.service.FalconService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Falcon hook used for atlas entity registration.
+ */
+public class AtlasService implements FalconService, 
ConfigurationChangeListener {
+    private static final Logger LOG = 
LoggerFactory.getLogger(AtlasService.class);
+
+    private static final String ATLAS_PLUGIN_TYPE = "falcon";
+    private static final String ATLAS_FALCON_HOOK_IMPL_CLASSNAME = 
"org.apache.atlas.falcon.hook.AtlasService";
+
+    private AtlasPluginClassLoader atlasPluginClassLoader = null;
+    private FalconService falconServiceImpl = null;
+    private ConfigurationChangeListener configChangeListenerImpl = null;
+
+    public AtlasService() {
+        this.initialize();
+    }
+
+    @Override
+    public String getName() {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasService.getName()");
+        }
+
+        String ret = null;
+
+        try {
+            activatePluginClassLoader();
+            ret = falconServiceImpl.getName();
+        } finally {
+            deactivatePluginClassLoader();
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasService.getName()");
+        }
+
+        return ret;
+    }
+
+    @Override
+    public void init() throws FalconException {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasService.init()");
+        }
+
+        try {
+            activatePluginClassLoader();
+            falconServiceImpl.init();
+        } finally {
+            deactivatePluginClassLoader();
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasService.init()");
+        }
+    }
+
+    @Override
+    public void destroy() throws FalconException {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasService.destroy()");
+        }
+
+        try {
+            activatePluginClassLoader();
+            falconServiceImpl.destroy();
+        } finally {
+            deactivatePluginClassLoader();
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasService.destroy()");
+        }
+    }
+
+    @Override
+    public void onAdd(Entity entity) throws FalconException {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasService.onAdd(" + entity + ")");
+        }
+
+        try {
+            activatePluginClassLoader();
+            configChangeListenerImpl.onAdd(entity);
+        } finally {
+            deactivatePluginClassLoader();
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasService.onAdd(" + entity + ")");
+        }
+    }
+
+    @Override
+    public void onRemove(Entity entity) throws FalconException {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasService.onRemove(" + entity + ")");
+        }
+
+        try {
+            activatePluginClassLoader();
+            configChangeListenerImpl.onRemove(entity);
+        } finally {
+            deactivatePluginClassLoader();
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasService.onRemove(" + entity + ")");
+        }
+    }
+
+    @Override
+    public void onChange(Entity entity, Entity entity1) throws FalconException 
{
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasService.onChange(" + entity + ", " + entity1 + 
")");
+        }
+
+        try {
+            activatePluginClassLoader();
+            configChangeListenerImpl.onChange(entity, entity1);
+        } finally {
+            deactivatePluginClassLoader();
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasService.onChange(" + entity + ", " + entity1 + 
")");
+        }
+    }
+
+    @Override
+    public void onReload(Entity entity) throws FalconException {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasService.onReload(" + entity + ")");
+        }
+
+        try {
+            activatePluginClassLoader();
+            configChangeListenerImpl.onReload(entity);
+        } finally {
+            deactivatePluginClassLoader();
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasService.onReload(" + entity + ")");
+        }
+    }
+
+    private void initialize() {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasService.initialize()");
+        }
+
+        try {
+            atlasPluginClassLoader = 
AtlasPluginClassLoader.getInstance(ATLAS_PLUGIN_TYPE, this.getClass());
+
+            Class<?> cls = Class.forName(ATLAS_FALCON_HOOK_IMPL_CLASSNAME, 
true, atlasPluginClassLoader);
+
+            activatePluginClassLoader();
+
+            Object atlasService = cls.newInstance();
+
+            falconServiceImpl = (FalconService) atlasService;
+            configChangeListenerImpl = (ConfigurationChangeListener) 
atlasService;
+        } catch (Exception excp) {
+            LOG.error("Error instantiating Atlas hook implementation", excp);
+        } finally {
+            deactivatePluginClassLoader();
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasService.initialize()");
+        }
+    }
+
+    private void activatePluginClassLoader() {
+        if (atlasPluginClassLoader != null) {
+            atlasPluginClassLoader.activate();
+        }
+    }
+
+    private void deactivatePluginClassLoader() {
+        if (atlasPluginClassLoader != null) {
+            atlasPluginClassLoader.deactivate();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/addons/falcon-bridge/pom.xml
----------------------------------------------------------------------
diff --git a/addons/falcon-bridge/pom.xml b/addons/falcon-bridge/pom.xml
index d79dda9..064fbf6 100644
--- a/addons/falcon-bridge/pom.xml
+++ b/addons/falcon-bridge/pom.xml
@@ -99,13 +99,13 @@
                 <artifactId>maven-dependency-plugin</artifactId>
                 <executions>
                     <execution>
-                        <id>copy-hook-dependencies</id>
+                        <id>copy-hook</id>
                         <phase>package</phase>
                         <goals>
                             <goal>copy</goal>
                         </goals>
                         <configuration>
-                            
<outputDirectory>${project.build.directory}/dependency/hook/falcon</outputDirectory>
+                            
<outputDirectory>${project.build.directory}/dependency/hook/falcon/atlas-falcon-plugin-impl</outputDirectory>
                             <overWriteReleases>false</overWriteReleases>
                             <overWriteSnapshots>false</overWriteSnapshots>
                             <overWriteIfNewer>true</overWriteIfNewer>
@@ -195,6 +195,46 @@
                                     <artifactId>kafka-clients</artifactId>
                                     <version>${kafka.version}</version>
                                 </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.apache.hadoop</groupId>
+                                    <artifactId>hadoop-common</artifactId>
+                                    <version>${hadoop.version}</version>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>com.google.code.gson</groupId>
+                                    <artifactId>gson</artifactId>
+                                    <version>${gson.version}</version>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>log4j</groupId>
+                                    <artifactId>log4j</artifactId>
+                                    <version>${log4j.version}</version>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>copy-hook-shim</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>copy</goal>
+                        </goals>
+                        <configuration>
+                            
<outputDirectory>${project.build.directory}/dependency/hook/falcon</outputDirectory>
+                            <overWriteReleases>false</overWriteReleases>
+                            <overWriteSnapshots>false</overWriteSnapshots>
+                            <overWriteIfNewer>true</overWriteIfNewer>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>falcon-bridge-shim</artifactId>
+                                    <version>${project.version}</version>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    
<artifactId>atlas-plugin-classloader</artifactId>
+                                    <version>${project.version}</version>
+                                </artifactItem>
                             </artifactItems>
                         </configuration>
                     </execution>

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/addons/hive-bridge-shim/pom.xml
----------------------------------------------------------------------
diff --git a/addons/hive-bridge-shim/pom.xml b/addons/hive-bridge-shim/pom.xml
new file mode 100755
index 0000000..c699b29
--- /dev/null
+++ b/addons/hive-bridge-shim/pom.xml
@@ -0,0 +1,53 @@
+<?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>
+    <parent>
+        <artifactId>apache-atlas</artifactId>
+        <groupId>org.apache.atlas</groupId>
+        <version>0.8-incubating-SNAPSHOT</version>
+        <relativePath>../../</relativePath>
+    </parent>
+    <artifactId>hive-bridge-shim</artifactId>
+    <description>Apache Atlas Hive Bridge Shim Module</description>
+    <name>Apache Atlas Hive Bridge Shim</name>
+    <packaging>jar</packaging>
+
+    <properties>
+        <hive.version>1.2.1</hive.version>
+        <calcite.version>0.9.2-incubating</calcite.version>
+        <checkstyle.failOnViolation>true</checkstyle.failOnViolation>
+    </properties>
+
+    <dependencies>
+        <!-- Logging -->
+        <dependency>
+            <groupId>org.apache.atlas</groupId>
+            <artifactId>atlas-plugin-classloader</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.hive</groupId>
+            <artifactId>hive-exec</artifactId>
+            <version>${hive.version}</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/addons/hive-bridge-shim/src/main/java/org/apache/atlas/hive/hook/HiveHook.java
----------------------------------------------------------------------
diff --git 
a/addons/hive-bridge-shim/src/main/java/org/apache/atlas/hive/hook/HiveHook.java
 
b/addons/hive-bridge-shim/src/main/java/org/apache/atlas/hive/hook/HiveHook.java
new file mode 100755
index 0000000..f4ca94f
--- /dev/null
+++ 
b/addons/hive-bridge-shim/src/main/java/org/apache/atlas/hive/hook/HiveHook.java
@@ -0,0 +1,99 @@
+/**
+ * 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.atlas.hive.hook;
+
+
+import org.apache.atlas.plugin.classloader.AtlasPluginClassLoader;
+import org.apache.hadoop.hive.ql.hooks.ExecuteWithHookContext;
+import org.apache.hadoop.hive.ql.hooks.HookContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Hive hook used for atlas entity registration.
+ */
+public class HiveHook implements ExecuteWithHookContext {
+    private static final Logger LOG = LoggerFactory.getLogger(HiveHook.class);
+
+    private static final String ATLAS_PLUGIN_TYPE = "hive";
+    private static final String ATLAS_HIVE_HOOK_IMPL_CLASSNAME = 
"org.apache.atlas.hive.hook.HiveHook";
+
+    private AtlasPluginClassLoader atlasPluginClassLoader = null;
+    private ExecuteWithHookContext hiveHookImpl = null;
+
+    public HiveHook() {
+        this.initialize();
+    }
+
+    @Override
+    public void run(final HookContext hookContext) throws Exception {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> HiveHook.run(" + hookContext + ")");
+        }
+
+        try {
+            activatePluginClassLoader();
+            hiveHookImpl.run(hookContext);
+        } finally {
+            deactivatePluginClassLoader();
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== HiveHook.run(" + hookContext + ")");
+        }
+    }
+
+    private void initialize() {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> HiveHook.initialize()");
+        }
+
+        try {
+            atlasPluginClassLoader = 
AtlasPluginClassLoader.getInstance(ATLAS_PLUGIN_TYPE, this.getClass());
+
+            @SuppressWarnings("unchecked")
+            Class<ExecuteWithHookContext> cls = 
(Class<ExecuteWithHookContext>) Class
+                    .forName(ATLAS_HIVE_HOOK_IMPL_CLASSNAME, true, 
atlasPluginClassLoader);
+
+            activatePluginClassLoader();
+
+            hiveHookImpl = cls.newInstance();
+        } catch (Exception excp) {
+            LOG.error("Error instantiating Atlas hook implementation", excp);
+        } finally {
+            deactivatePluginClassLoader();
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== HiveHook.initialize()");
+        }
+    }
+
+    private void activatePluginClassLoader() {
+        if (atlasPluginClassLoader != null) {
+            atlasPluginClassLoader.activate();
+        }
+    }
+
+    private void deactivatePluginClassLoader() {
+        if (atlasPluginClassLoader != null) {
+            atlasPluginClassLoader.deactivate();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/addons/hive-bridge/pom.xml
----------------------------------------------------------------------
diff --git a/addons/hive-bridge/pom.xml b/addons/hive-bridge/pom.xml
index ddefdc2..2d0fb14 100755
--- a/addons/hive-bridge/pom.xml
+++ b/addons/hive-bridge/pom.xml
@@ -168,25 +168,7 @@
                             <goal>copy</goal>
                         </goals>
                         <configuration>
-                            <artifactItems>
-                                <artifactItem>
-                                    <groupId>${project.groupId}</groupId>
-                                    
<artifactId>${project.artifactId}</artifactId>
-                                    <version>${project.version}</version>
-                                    <overWrite>true</overWrite>
-                                    
<outputDirectory>${project.build.directory}/dependency/hook/hive</outputDirectory>
-                                </artifactItem>
-                            </artifactItems>
-                        </configuration>
-                    </execution>
-                    <execution>
-                        <id>copy-hook-dependencies</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>copy</goal>
-                        </goals>
-                        <configuration>
-                            
<outputDirectory>${project.build.directory}/dependency/hook/hive</outputDirectory>
+                            
<outputDirectory>${project.build.directory}/dependency/hook/hive/atlas-hive-plugin-impl</outputDirectory>
                             <overWriteReleases>false</overWriteReleases>
                             <overWriteSnapshots>false</overWriteSnapshots>
                             <overWriteIfNewer>true</overWriteIfNewer>
@@ -271,6 +253,46 @@
                                     <artifactId>kafka-clients</artifactId>
                                     <version>${kafka.version}</version>
                                 </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.apache.hadoop</groupId>
+                                    <artifactId>hadoop-common</artifactId>
+                                    <version>${hadoop.version}</version>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>com.google.code.gson</groupId>
+                                    <artifactId>gson</artifactId>
+                                    <version>${gson.version}</version>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>log4j</groupId>
+                                    <artifactId>log4j</artifactId>
+                                    <version>${log4j.version}</version>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>copy-hook-shim</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>copy</goal>
+                        </goals>
+                        <configuration>
+                            
<outputDirectory>${project.build.directory}/dependency/hook/hive</outputDirectory>
+                            <overWriteReleases>false</overWriteReleases>
+                            <overWriteSnapshots>false</overWriteSnapshots>
+                            <overWriteIfNewer>true</overWriteIfNewer>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>hive-bridge-shim</artifactId>
+                                    <version>${project.version}</version>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    
<artifactId>atlas-plugin-classloader</artifactId>
+                                    <version>${project.version}</version>
+                                </artifactItem>
                             </artifactItems>
                         </configuration>
                     </execution>

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/addons/sqoop-bridge-shim/pom.xml
----------------------------------------------------------------------
diff --git a/addons/sqoop-bridge-shim/pom.xml b/addons/sqoop-bridge-shim/pom.xml
new file mode 100755
index 0000000..efb5a11
--- /dev/null
+++ b/addons/sqoop-bridge-shim/pom.xml
@@ -0,0 +1,52 @@
+<?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>
+    <parent>
+        <artifactId>apache-atlas</artifactId>
+        <groupId>org.apache.atlas</groupId>
+        <version>0.8-incubating-SNAPSHOT</version>
+        <relativePath>../../</relativePath>
+    </parent>
+    <artifactId>sqoop-bridge-shim</artifactId>
+    <description>Apache Atlas Sqoop Bridge Shim Module</description>
+    <name>Apache Atlas Sqoop Bridge Shim</name>
+    <packaging>jar</packaging>
+
+    <properties>
+        <sqoop.version>1.4.6.2.3.99.0-195</sqoop.version>
+        <checkstyle.failOnViolation>true</checkstyle.failOnViolation>
+    </properties>
+
+    <dependencies>
+        <!-- Logging -->
+        <dependency>
+            <groupId>org.apache.atlas</groupId>
+            <artifactId>atlas-plugin-classloader</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.sqoop</groupId>
+            <artifactId>sqoop</artifactId>
+            <version>${sqoop.version}</version>
+            <scope>compile</scope>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/addons/sqoop-bridge-shim/src/main/java/org/apache/atlas/sqoop/hook/SqoopHook.java
----------------------------------------------------------------------
diff --git 
a/addons/sqoop-bridge-shim/src/main/java/org/apache/atlas/sqoop/hook/SqoopHook.java
 
b/addons/sqoop-bridge-shim/src/main/java/org/apache/atlas/sqoop/hook/SqoopHook.java
new file mode 100644
index 0000000..1170cb6
--- /dev/null
+++ 
b/addons/sqoop-bridge-shim/src/main/java/org/apache/atlas/sqoop/hook/SqoopHook.java
@@ -0,0 +1,98 @@
+/**
+ * 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.atlas.sqoop.hook;
+
+
+import org.apache.atlas.plugin.classloader.AtlasPluginClassLoader;
+import org.apache.sqoop.SqoopJobDataPublisher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Sqoop hook used for atlas entity registration.
+ */
+public class SqoopHook extends SqoopJobDataPublisher {
+    private static final Logger LOG = LoggerFactory.getLogger(SqoopHook.class);
+
+    private static final String ATLAS_PLUGIN_TYPE = "sqoop";
+    private static final String ATLAS_SQOOP_HOOK_IMPL_CLASSNAME = 
"org.apache.atlas.sqoop.hook.SqoopHook";
+
+    private AtlasPluginClassLoader atlasPluginClassLoader = null;
+    private SqoopJobDataPublisher sqoopHookImpl = null;
+
+    public SqoopHook() {
+        this.initialize();
+    }
+
+    @Override
+    public void publish(SqoopJobDataPublisher.Data data) throws Exception {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> SqoopHook.run(" + data + ")");
+        }
+
+        try {
+            activatePluginClassLoader();
+            sqoopHookImpl.publish(data);
+        } finally {
+            deactivatePluginClassLoader();
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== SqoopHook.run(" + data + ")");
+        }
+    }
+
+    private void initialize() {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> HiveHook.initialize()");
+        }
+
+        try {
+            atlasPluginClassLoader = 
AtlasPluginClassLoader.getInstance(ATLAS_PLUGIN_TYPE, this.getClass());
+
+            @SuppressWarnings("unchecked")
+            Class<SqoopJobDataPublisher> cls = (Class<SqoopJobDataPublisher>) 
Class
+                    .forName(ATLAS_SQOOP_HOOK_IMPL_CLASSNAME, true, 
atlasPluginClassLoader);
+
+            activatePluginClassLoader();
+
+            sqoopHookImpl = cls.newInstance();
+        } catch (Exception excp) {
+            LOG.error("Error instantiating Atlas hook implementation", excp);
+        } finally {
+            deactivatePluginClassLoader();
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== HiveHook.initialize()");
+        }
+    }
+
+    private void activatePluginClassLoader() {
+        if (atlasPluginClassLoader != null) {
+            atlasPluginClassLoader.activate();
+        }
+    }
+
+    private void deactivatePluginClassLoader() {
+        if (atlasPluginClassLoader != null) {
+            atlasPluginClassLoader.deactivate();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/addons/sqoop-bridge/pom.xml
----------------------------------------------------------------------
diff --git a/addons/sqoop-bridge/pom.xml b/addons/sqoop-bridge/pom.xml
index c792945..ceccf36 100644
--- a/addons/sqoop-bridge/pom.xml
+++ b/addons/sqoop-bridge/pom.xml
@@ -170,29 +170,16 @@
                             <goal>copy</goal>
                         </goals>
                         <configuration>
+                            
<outputDirectory>${project.build.directory}/dependency/hook/sqoop/atlas-sqoop-plugin-impl</outputDirectory>
+                            <overWriteReleases>false</overWriteReleases>
+                            <overWriteSnapshots>false</overWriteSnapshots>
+                            <overWriteIfNewer>true</overWriteIfNewer>
                             <artifactItems>
                                 <artifactItem>
                                     <groupId>${project.groupId}</groupId>
                                     
<artifactId>${project.artifactId}</artifactId>
                                     <version>${project.version}</version>
-                                    <overWrite>true</overWrite>
-                                    
<outputDirectory>${project.build.directory}/dependency/hook/sqoop</outputDirectory>
                                 </artifactItem>
-                            </artifactItems>
-                        </configuration>
-                    </execution>
-                    <execution>
-                        <id>copy-hook-dependencies</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>copy</goal>
-                        </goals>
-                        <configuration>
-                            
<outputDirectory>${project.build.directory}/dependency/hook/sqoop</outputDirectory>
-                            <overWriteReleases>false</overWriteReleases>
-                            <overWriteSnapshots>false</overWriteSnapshots>
-                            <overWriteIfNewer>true</overWriteIfNewer>
-                            <artifactItems>
                                 <artifactItem>
                                     <groupId>${project.groupId}</groupId>
                                     
<artifactId>${project.artifactId}</artifactId>
@@ -273,6 +260,46 @@
                                     <artifactId>kafka-clients</artifactId>
                                     <version>${kafka.version}</version>
                                 </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.apache.hadoop</groupId>
+                                    <artifactId>hadoop-common</artifactId>
+                                    <version>${hadoop.version}</version>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>com.google.code.gson</groupId>
+                                    <artifactId>gson</artifactId>
+                                    <version>${gson.version}</version>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>log4j</groupId>
+                                    <artifactId>log4j</artifactId>
+                                    <version>${log4j.version}</version>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>copy-hook-shim</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>copy</goal>
+                        </goals>
+                        <configuration>
+                            
<outputDirectory>${project.build.directory}/dependency/hook/sqoop</outputDirectory>
+                            <overWriteReleases>false</overWriteReleases>
+                            <overWriteSnapshots>false</overWriteSnapshots>
+                            <overWriteIfNewer>true</overWriteIfNewer>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>sqoop-bridge-shim</artifactId>
+                                    <version>${project.version}</version>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    
<artifactId>atlas-plugin-classloader</artifactId>
+                                    <version>${project.version}</version>
+                                </artifactItem>
                             </artifactItems>
                         </configuration>
                     </execution>

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/addons/storm-bridge-shim/pom.xml
----------------------------------------------------------------------
diff --git a/addons/storm-bridge-shim/pom.xml b/addons/storm-bridge-shim/pom.xml
new file mode 100755
index 0000000..49c56e0
--- /dev/null
+++ b/addons/storm-bridge-shim/pom.xml
@@ -0,0 +1,58 @@
+<?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>
+    <parent>
+        <artifactId>apache-atlas</artifactId>
+        <groupId>org.apache.atlas</groupId>
+        <version>0.8-incubating-SNAPSHOT</version>
+        <relativePath>../../</relativePath>
+    </parent>
+    <artifactId>storm-bridge-shim</artifactId>
+    <description>Apache Atlas Storm Bridge Shim Module</description>
+    <name>Apache Atlas Storm Bridge Shim</name>
+    <packaging>jar</packaging>
+
+    <properties>
+        <storm.version>1.0.0</storm.version>
+        <checkstyle.failOnViolation>true</checkstyle.failOnViolation>
+    </properties>
+
+    <dependencies>
+        <!-- Logging -->
+        <dependency>
+            <groupId>org.apache.atlas</groupId>
+            <artifactId>atlas-plugin-classloader</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.storm</groupId>
+            <artifactId>storm-core</artifactId>
+            <version>${storm.version}</version>
+            <type>jar</type>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/addons/storm-bridge-shim/src/main/java/org/apache/atlas/storm/hook/StormAtlasHook.java
----------------------------------------------------------------------
diff --git 
a/addons/storm-bridge-shim/src/main/java/org/apache/atlas/storm/hook/StormAtlasHook.java
 
b/addons/storm-bridge-shim/src/main/java/org/apache/atlas/storm/hook/StormAtlasHook.java
new file mode 100644
index 0000000..2d304c5
--- /dev/null
+++ 
b/addons/storm-bridge-shim/src/main/java/org/apache/atlas/storm/hook/StormAtlasHook.java
@@ -0,0 +1,104 @@
+/**
+ * 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.atlas.storm.hook;
+
+
+import org.apache.atlas.plugin.classloader.AtlasPluginClassLoader;
+import org.apache.storm.ISubmitterHook;
+import org.apache.storm.generated.StormTopology;
+import org.apache.storm.generated.TopologyInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+
+/**
+ * Storm hook used for atlas entity registration.
+ */
+public class StormAtlasHook implements ISubmitterHook {
+    private static final Logger LOG = 
LoggerFactory.getLogger(StormAtlasHook.class);
+
+    private static final String ATLAS_PLUGIN_TYPE = "storm";
+    private static final String ATLAS_STORM_HOOK_IMPL_CLASSNAME = 
"org.apache.atlas.storm.hook.StormAtlasHook";
+
+    private AtlasPluginClassLoader atlasPluginClassLoader = null;
+    private ISubmitterHook stormHook = null;
+
+
+    public StormAtlasHook() {
+        this.initialize();
+    }
+
+    @Override
+    public void notify(TopologyInfo topologyInfo, Map stormConf, StormTopology 
stormTopology)
+        throws IllegalAccessException {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> StormAtlasHook.notify(" + topologyInfo + ", " + 
stormConf + ", " + stormTopology + ")");
+        }
+
+        try {
+            activatePluginClassLoader();
+            stormHook.notify(topologyInfo, stormConf, stormTopology);
+        } finally {
+            deactivatePluginClassLoader();
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== StormAtlasHook.notify(" + topologyInfo + ", " + 
stormConf + ", " + stormTopology + ")");
+        }
+    }
+
+    private void initialize() {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> StormAtlasHook.initialize()");
+        }
+
+        try {
+            atlasPluginClassLoader = 
AtlasPluginClassLoader.getInstance(ATLAS_PLUGIN_TYPE, this.getClass());
+
+            @SuppressWarnings("unchecked")
+            Class<ISubmitterHook> cls = (Class<ISubmitterHook>) Class
+                    .forName(ATLAS_STORM_HOOK_IMPL_CLASSNAME, true, 
atlasPluginClassLoader);
+
+            activatePluginClassLoader();
+
+            stormHook = cls.newInstance();
+        } catch (Exception excp) {
+            LOG.error("Error instantiating Atlas hook implementation", excp);
+        } finally {
+            deactivatePluginClassLoader();
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== StormAtlasHook.initialize()");
+        }
+    }
+
+    private void activatePluginClassLoader() {
+        if (atlasPluginClassLoader != null) {
+            atlasPluginClassLoader.activate();
+        }
+    }
+
+    private void deactivatePluginClassLoader() {
+        if (atlasPluginClassLoader != null) {
+            atlasPluginClassLoader.deactivate();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/addons/storm-bridge/pom.xml
----------------------------------------------------------------------
diff --git a/addons/storm-bridge/pom.xml b/addons/storm-bridge/pom.xml
index 9e8bf2f..12c1208 100644
--- a/addons/storm-bridge/pom.xml
+++ b/addons/storm-bridge/pom.xml
@@ -139,13 +139,13 @@
                 <artifactId>maven-dependency-plugin</artifactId>
                 <executions>
                     <execution>
-                        <id>copy-hook-dependencies</id>
+                        <id>copy-hook</id>
                         <phase>package</phase>
                         <goals>
                             <goal>copy</goal>
                         </goals>
                         <configuration>
-                            
<outputDirectory>${project.build.directory}/dependency/hook/storm</outputDirectory>
+                            
<outputDirectory>${project.build.directory}/dependency/hook/storm/atlas-storm-plugin-impl</outputDirectory>
                             <overWriteReleases>false</overWriteReleases>
                             <overWriteSnapshots>false</overWriteSnapshots>
                             <overWriteIfNewer>true</overWriteIfNewer>
@@ -315,6 +315,46 @@
                                     <artifactId>hbase-common</artifactId>
                                     <version>${hbase.version}</version>
                                 </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.apache.hadoop</groupId>
+                                    <artifactId>hadoop-common</artifactId>
+                                    <version>${hadoop.version}</version>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>com.google.code.gson</groupId>
+                                    <artifactId>gson</artifactId>
+                                    <version>${gson.version}</version>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>log4j</groupId>
+                                    <artifactId>log4j</artifactId>
+                                    <version>${log4j.version}</version>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>copy-hook-shim</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>copy</goal>
+                        </goals>
+                        <configuration>
+                            
<outputDirectory>${project.build.directory}/dependency/hook/storm</outputDirectory>
+                            <overWriteReleases>false</overWriteReleases>
+                            <overWriteSnapshots>false</overWriteSnapshots>
+                            <overWriteIfNewer>true</overWriteIfNewer>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    <artifactId>storm-bridge-shim</artifactId>
+                                    <version>${project.version}</version>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>${project.groupId}</groupId>
+                                    
<artifactId>atlas-plugin-classloader</artifactId>
+                                    <version>${project.version}</version>
+                                </artifactItem>
                             </artifactItems>
                         </configuration>
                     </execution>

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/plugin-classloader/pom.xml
----------------------------------------------------------------------
diff --git a/plugin-classloader/pom.xml b/plugin-classloader/pom.xml
new file mode 100644
index 0000000..c41b309
--- /dev/null
+++ b/plugin-classloader/pom.xml
@@ -0,0 +1,42 @@
+<?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>
+    <parent>
+        <artifactId>apache-atlas</artifactId>
+        <groupId>org.apache.atlas</groupId>
+        <version>0.8-incubating-SNAPSHOT</version>
+    </parent>
+    <artifactId>atlas-plugin-classloader</artifactId>
+    <description>Apache Atlas Plugin Classloader</description>
+    <name>Apache Atlas Plugin Classloader</name>
+    <packaging>jar</packaging>
+
+    <properties>
+        <checkstyle.failOnViolation>true</checkstyle.failOnViolation>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/plugin-classloader/src/main/java/org/apache/atlas/plugin/classloader/AtlasPluginClassLoader.java
----------------------------------------------------------------------
diff --git 
a/plugin-classloader/src/main/java/org/apache/atlas/plugin/classloader/AtlasPluginClassLoader.java
 
b/plugin-classloader/src/main/java/org/apache/atlas/plugin/classloader/AtlasPluginClassLoader.java
new file mode 100644
index 0000000..c5214bd
--- /dev/null
+++ 
b/plugin-classloader/src/main/java/org/apache/atlas/plugin/classloader/AtlasPluginClassLoader.java
@@ -0,0 +1,327 @@
+/**
+ * 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.atlas.plugin.classloader;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.util.Enumeration;
+
+/**
+ * AtlasPluginClassLoader to use plugin classpath first, before component 
classpath.
+ */
+public final class AtlasPluginClassLoader extends URLClassLoader {
+    private static final Logger LOG = 
LoggerFactory.getLogger(AtlasPluginClassLoader.class);
+
+    private final MyClassLoader componentClassLoader;
+
+    private AtlasPluginClassLoader(String pluginType, Class<?> pluginClass) 
throws Exception {
+        this(AtlasPluginClassLoaderUtil.getPluginImplLibPath(pluginType, 
pluginClass));
+    }
+
+    //visible for testing
+    AtlasPluginClassLoader(String libraryPath) throws Exception {
+        super(AtlasPluginClassLoaderUtil.getFilesInDirectories(new 
String[]{libraryPath}), null);
+
+        componentClassLoader = AccessController.doPrivileged(new 
PrivilegedAction<MyClassLoader>() {
+            public MyClassLoader run() {
+                return new 
MyClassLoader(Thread.currentThread().getContextClassLoader());
+            }
+        });
+    }
+
+    public static AtlasPluginClassLoader getInstance(final String pluginType, 
final Class<?> pluginClass)
+        throws Exception {
+        AtlasPluginClassLoader ret =
+                AccessController.doPrivileged(new 
PrivilegedExceptionAction<AtlasPluginClassLoader>() {
+                    public AtlasPluginClassLoader run() throws Exception {
+                        return new AtlasPluginClassLoader(pluginType, 
pluginClass);
+                    }
+                });
+
+        return ret;
+    }
+
+    @Override
+    public Class<?> findClass(String name) throws ClassNotFoundException {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasPluginClassLoader.findClass(" + name + ")");
+        }
+
+        Class<?> ret = null;
+
+        try {
+            // first try to find the class in pluginClassloader
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("AtlasPluginClassLoader.findClass(" + name + "): 
calling pluginClassLoader.findClass()");
+            }
+
+            ret = super.findClass(name);
+        } catch (Throwable e) {
+            // on failure to find in pluginClassLoader, try to find in 
componentClassLoader
+            MyClassLoader savedClassLoader = getComponentClassLoader();
+
+            if (savedClassLoader != null) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug(
+                            "AtlasPluginClassLoader.findClass(" + name + "): 
calling componentClassLoader.findClass()");
+                }
+
+                ret = savedClassLoader.findClass(name);
+            }
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasPluginClassLoader.findClass(" + name + "): " + 
ret);
+        }
+
+        return ret;
+    }
+
+    @Override
+    public Class<?> loadClass(String name) throws ClassNotFoundException {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasPluginClassLoader.loadClass(" + name + ")");
+        }
+
+        Class<?> ret = null;
+
+        try {
+            // first try to load the class from pluginClassloader
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("AtlasPluginClassLoader.loadClass(" + name + "): 
calling pluginClassLoader.loadClass()");
+            }
+
+            ret = super.loadClass(name);
+        } catch (Throwable e) {
+            // on failure to load from pluginClassLoader, try to load from 
componentClassLoader
+            MyClassLoader savedClassLoader = getComponentClassLoader();
+
+            if (savedClassLoader != null) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug(
+                            "AtlasPluginClassLoader.loadClass(" + name + "): 
calling componentClassLoader.loadClass()");
+                }
+
+                ret = savedClassLoader.loadClass(name);
+            }
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasPluginClassLoader.loadClass(" + name + "): " + 
ret);
+        }
+
+        return ret;
+    }
+
+    @Override
+    public URL findResource(String name) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasPluginClassLoader.findResource(" + name + ") 
");
+        }
+
+        // first try to find the resource from pluginClassloader
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("AtlasPluginClassLoader.findResource(" + name + "): 
calling pluginClassLoader.findResource()");
+        }
+
+        URL ret = super.findResource(name);
+
+        if (ret == null) {
+            MyClassLoader savedClassLoader = getComponentClassLoader();
+
+            if (savedClassLoader != null) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("AtlasPluginClassLoader.findResource(" + name
+                            + "): calling componentClassLoader.getResource()");
+                }
+
+                ret = savedClassLoader.getResource(name);
+            }
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasPluginClassLoader.findResource(" + name + "): 
" + ret);
+        }
+
+        return ret;
+    }
+
+    @Override
+    public Enumeration<URL> findResources(String name) throws IOException {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasPluginClassLoader.findResources(" + name + 
")");
+        }
+
+        Enumeration<URL> ret = null;
+
+        Enumeration<URL> resourcesInPluginClsLoader = 
findResourcesUsingPluginClassLoader(name);
+        Enumeration<URL> resourcesInComponentClsLoader = 
findResourcesUsingComponentClassLoader(name);
+
+        if (resourcesInPluginClsLoader != null && 
resourcesInComponentClsLoader != null) {
+            ret = new MergeEnumeration(resourcesInPluginClsLoader, 
resourcesInComponentClsLoader);
+        } else if (resourcesInPluginClsLoader != null) {
+            ret = resourcesInPluginClsLoader;
+        } else {
+            ret = resourcesInComponentClsLoader;
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasPluginClassLoader.findResources(" + name + "): 
" + ret);
+        }
+
+        return ret;
+    }
+
+    public void activate() {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasPluginClassLoader.activate()");
+        }
+
+        Thread.currentThread().setContextClassLoader(this);
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasPluginClassLoader.activate()");
+        }
+    }
+
+    public void deactivate() {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasPluginClassLoader.deactivate()");
+        }
+
+        MyClassLoader savedClassLoader = getComponentClassLoader();
+
+        if (savedClassLoader != null && savedClassLoader.getParent() != null) {
+            
Thread.currentThread().setContextClassLoader(savedClassLoader.getParent());
+        } else {
+            LOG.warn("AtlasPluginClassLoader.deactivate() was not 
successful.Couldn't not get the saved "
+                    + "componentClassLoader...");
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasPluginClassLoader.deactivate()");
+        }
+    }
+
+    private MyClassLoader getComponentClassLoader() {
+        return componentClassLoader;
+    }
+
+    private Enumeration<URL> findResourcesUsingPluginClassLoader(String name) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> 
AtlasPluginClassLoader.findResourcesUsingPluginClassLoader(" + name + ")");
+        }
+
+        Enumeration<URL> ret = null;
+
+        try {
+            ret = super.findResources(name);
+        } catch (Throwable excp) {
+            // Ignore exceptions
+            if (LOG.isDebugEnabled()) {
+                
LOG.debug("AtlasPluginClassLoader.findResourcesUsingPluginClassLoader(" + name
+                        + "): resource not found in plugin", excp);
+            }
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== 
AtlasPluginClassLoader.findResourcesUsingPluginClassLoader(" + name + "): " + 
ret);
+        }
+
+        return ret;
+    }
+
+    private Enumeration<URL> findResourcesUsingComponentClassLoader(String 
name) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> 
AtlasPluginClassLoader.findResourcesUsingComponentClassLoader(" + name + ")");
+        }
+
+        Enumeration<URL> ret = null;
+
+        try {
+            MyClassLoader savedClassLoader = getComponentClassLoader();
+
+            if (savedClassLoader != null) {
+                if (LOG.isDebugEnabled()) {
+                    
LOG.debug("AtlasPluginClassLoader.findResourcesUsingComponentClassLoader(" + 
name
+                            + "): calling 
componentClassLoader.getResources()");
+                }
+
+                ret = savedClassLoader.getResources(name);
+            }
+
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("<== 
AtlasPluginClassLoader.findResourcesUsingComponentClassLoader(" + name + "): " 
+ ret);
+            }
+        } catch (Throwable t) {
+            if (LOG.isDebugEnabled()) {
+                
LOG.debug("AtlasPluginClassLoader.findResourcesUsingComponentClassLoader(" + 
name
+                        + "): class not found in componentClassLoader.", t);
+            }
+        }
+
+        return ret;
+    }
+
+    static class MergeEnumeration implements Enumeration<URL> { //NOPMD
+        private Enumeration<URL> e1 = null;
+        private Enumeration<URL> e2 = null;
+
+        public MergeEnumeration(Enumeration<URL> e1, Enumeration<URL> e2) {
+            this.e1 = e1;
+            this.e2 = e2;
+        }
+
+        @Override
+        public boolean hasMoreElements() {
+            return ((e1 != null && e1.hasMoreElements()) || (e2 != null && 
e2.hasMoreElements()));
+        }
+
+        @Override
+        public URL nextElement() {
+            URL ret = null;
+
+            if (e1 != null && e1.hasMoreElements()) {
+                ret = e1.nextElement();
+            } else if (e2 != null && e2.hasMoreElements()) {
+                ret = e2.nextElement();
+            }
+
+            return ret;
+        }
+    }
+
+    static class MyClassLoader extends ClassLoader {
+        public MyClassLoader(ClassLoader realClassLoader) {
+            super(realClassLoader);
+        }
+
+        @Override
+        public Class<?> findClass(String name) throws ClassNotFoundException { 
//NOPMD
+            return super.findClass(name);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/plugin-classloader/src/main/java/org/apache/atlas/plugin/classloader/AtlasPluginClassLoaderUtil.java
----------------------------------------------------------------------
diff --git 
a/plugin-classloader/src/main/java/org/apache/atlas/plugin/classloader/AtlasPluginClassLoaderUtil.java
 
b/plugin-classloader/src/main/java/org/apache/atlas/plugin/classloader/AtlasPluginClassLoaderUtil.java
new file mode 100644
index 0000000..c3ec5e2
--- /dev/null
+++ 
b/plugin-classloader/src/main/java/org/apache/atlas/plugin/classloader/AtlasPluginClassLoaderUtil.java
@@ -0,0 +1,115 @@
+/**
+ * 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.atlas.plugin.classloader;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * AtlasPluginClassLoaderUtil used by AtlasPluginClassLoader.
+ */
+final class AtlasPluginClassLoaderUtil {
+    private static final Logger LOG = 
LoggerFactory.getLogger(AtlasPluginClassLoaderUtil.class);
+
+    private static final String ATLAS_PLUGIN_LIBDIR = "atlas-%-plugin-impl";
+
+    private AtlasPluginClassLoaderUtil(){ }
+
+    public static URL[] getFilesInDirectories(String[] libDirs) throws 
Exception {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> 
AtlasPluginClassLoaderUtil.getFilesInDirectories()");
+        }
+
+        List<URL> ret = new ArrayList<URL>();
+
+        for (String libDir : libDirs) {
+            getFilesInDirectory(libDir, ret);
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasPluginClassLoaderUtil.getFilesInDirectories(): 
" + ret.size() + " files");
+        }
+
+        return ret.toArray(new URL[]{});
+    }
+
+    private static void getFilesInDirectory(String dirPath, List<URL> files) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasPluginClassLoaderUtil.getPluginFiles()");
+        }
+
+        if (dirPath != null) {
+            try {
+                File[] dirFiles = new File(dirPath).listFiles();
+
+                if (dirFiles != null) {
+                    for (File dirFile : dirFiles) {
+                        try {
+                            URL jarPath = dirFile.toURI().toURL();
+
+                            if (LOG.isDebugEnabled()) {
+                                LOG.debug(
+                                        "getFilesInDirectory('" + dirPath + 
"'): adding " + dirFile.getAbsolutePath());
+                            }
+
+                            files.add(jarPath);
+                        } catch (Exception excp) {
+                            LOG.warn("getFilesInDirectory('" + dirPath + "'): 
failed to get URI for file " + dirFile
+                                    .getAbsolutePath(), excp);
+                        }
+                    }
+                }
+            } catch (Exception excp) {
+                LOG.warn("getFilesInDirectory('" + dirPath + "'): error", 
excp);
+            }
+        } else {
+            LOG.warn("getFilesInDirectory('" + dirPath + "'): could not find 
directory in path " + dirPath);
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasPluginClassLoaderUtil.getFilesInDirectory(" + 
dirPath + ")");
+        }
+    }
+
+    public static String getPluginImplLibPath(String pluginType, Class<?> 
pluginClass) throws Exception {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> AtlasPluginClassLoaderUtil.getPluginImplLibPath for 
Class (" + pluginClass.getName() + ")");
+        }
+
+        URI uri = 
pluginClass.getProtectionDomain().getCodeSource().getLocation().toURI();
+        Path path = Paths.get(URI.create(uri.toString()));
+        String ret = path.getParent().toString() + File.separatorChar + 
ATLAS_PLUGIN_LIBDIR.replaceAll("%", pluginType);
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== AtlasPluginClassLoaderUtil.getPluginImplLibPath for 
Class " + pluginClass.getName() + "): "
+                    + ret + ")");
+        }
+
+        return ret;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/plugin-classloader/src/test/java/org/apache/atlas/plugin/classloader/AtlasPluginClassLoaderTest.java
----------------------------------------------------------------------
diff --git 
a/plugin-classloader/src/test/java/org/apache/atlas/plugin/classloader/AtlasPluginClassLoaderTest.java
 
b/plugin-classloader/src/test/java/org/apache/atlas/plugin/classloader/AtlasPluginClassLoaderTest.java
new file mode 100644
index 0000000..6139a00
--- /dev/null
+++ 
b/plugin-classloader/src/test/java/org/apache/atlas/plugin/classloader/AtlasPluginClassLoaderTest.java
@@ -0,0 +1,66 @@
+/**
+ * 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.atlas.plugin.classloader;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class AtlasPluginClassLoaderTest {
+
+    @Test
+    public void testClassLoader() throws Exception {
+        String cls = "org.apache.atlas.service.Services";
+
+        try {
+            loadClass(cls, null);
+            Assert.fail("Expected ClassNotFoundException");
+        } catch (ClassNotFoundException e) {
+            //expected
+        }
+
+        AtlasPluginClassLoader classLoader = new 
AtlasPluginClassLoader("../common/target");
+
+        classLoader.activate();
+
+        //org.apache.atlas.service.Services class should be loadable now
+        //should also load org.apache.atlas.service.Service
+        Class<?> servicesCls = loadClass(cls, null);
+        loadClass("org.apache.atlas.service.Service", 
servicesCls.getClassLoader());
+
+        //Fall back to current class loader should also work
+        loadClass(AtlasPluginClassLoaderUtil.class.getName(), null);
+
+        classLoader.deactivate();
+
+        //After disable, class loading should fail again
+        try {
+            loadClass(cls, null);
+            Assert.fail("Expected ClassNotFoundException");
+        } catch (ClassNotFoundException e) {
+            //expected
+        }
+    }
+
+    private Class<?> loadClass(String cls, ClassLoader classLoader) throws 
ClassNotFoundException {
+        if (classLoader == null) {
+            classLoader = Thread.currentThread().getContextClassLoader();
+        }
+        return Class.forName(cls, true, classLoader);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index f119525..2224450 100755
--- a/pom.xml
+++ b/pom.xml
@@ -378,6 +378,7 @@
         <log4j.version>1.2.17</log4j.version>
         <akka.version>2.3.7</akka.version>
         <spray.version>1.3.1</spray.version>
+        <gson.version>2.5</gson.version>
         <guava.version>14.0</guava.version>
         <fastutil.version>6.5.16</fastutil.version>
         <guice.version>4.0</guice.version>
@@ -470,12 +471,17 @@
         <module>catalog</module>
         <module>dashboardv2</module>
         <module>webapp</module>
-       
         <module>docs</module>
+        
         <module>addons/hdfs-model</module>
+        <module>plugin-classloader</module>
+        <module>addons/hive-bridge-shim</module>
         <module>addons/hive-bridge</module>
+        <module>addons/falcon-bridge-shim</module>
         <module>addons/falcon-bridge</module>
+        <module>addons/sqoop-bridge-shim</module>
         <module>addons/sqoop-bridge</module>
+        <module>addons/storm-bridge-shim</module>
         <module>addons/storm-bridge</module>
        
         <module>distro</module>
@@ -1111,6 +1117,30 @@
                 <version>${project.version}</version>
             </dependency>         
 
+            <dependency>
+                <groupId>org.apache.atlas</groupId>
+                <artifactId>hive-bridge-shim</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.apache.atlas</groupId>
+                <artifactId>storm-bridge-shim</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.apache.atlas</groupId>
+                <artifactId>falcon-bridge-shim</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.apache.atlas</groupId>
+                <artifactId>sqoop-bridge-shim</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
             <!--Scala dependencies-->
             <dependency>
                 <groupId>org.scala-lang</groupId>
@@ -1223,7 +1253,7 @@
             <dependency>
                 <groupId>com.google.code.gson</groupId>
                 <artifactId>gson</artifactId>
-                <version>2.5</version>
+                <version>${gson.version}</version>
             </dependency>
 
             <dependency>
@@ -1303,6 +1333,12 @@
                     </exclusion>
                 </exclusions>
             </dependency>
+
+            <dependency>
+                <groupId>org.apache.atlas</groupId>
+                <artifactId>atlas-plugin-classloader</artifactId>
+                <version>${project.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/043d2aa6/release-log.txt
----------------------------------------------------------------------
diff --git a/release-log.txt b/release-log.txt
index d700596..8c9c1eb 100644
--- a/release-log.txt
+++ b/release-log.txt
@@ -6,6 +6,7 @@ INCOMPATIBLE CHANGES:
 
 
 ALL CHANGES:
+ATLAS-987 Atlas hooks should avoid adding dependent libraries to component 
CLASSPATH (madhan.neethiraj via shwethags)
 ATLAS-993 If condition in DSL order by clause is not defined then dsl query 
fails (guptaneeru via shwethags)
 ATLAS-968 Set group information from UGI for Ldap authentication 
(nixonrodrigues via shwethags)
 ATLAS-584 Integrate CSRF prevention filter (kevalbhatt18 via shwethags)

Reply via email to