{"action":"created","comment":{"url":"https://api.github.com/repos/mulesoft/mule/pulls/comments/77689232","id":77689232,"diff_hunk":"@@ -0,0 +1,692 @@\n+/*\n+ * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com\n+ * The software in this package is published under the terms of the CPAL v1.0\n+ * license, a copy of which has been included with this distribution in the\n+ * LICENSE.txt file.\n+ */\n+\n+package org.mule.functional.api.classloading.isolation;\n+\n+import static com.google.common.collect.Lists.newArrayList;\n+import static java.io.File.separator;\n+import static java.util.stream.Collectors.toList;\n+import static org.eclipse.aether.util.artifact.ArtifactIdUtils.toId;\n+import static org.eclipse.aether.util.artifact.JavaScopes.COMPILE;\n+import static org.eclipse.aether.util.artifact.JavaScopes.PROVIDED;\n+import static org.eclipse.aether.util.artifact.JavaScopes.TEST;\n+import static org.eclipse.aether.util.filter.DependencyFilterUtils.classpathFilter;\n+import static org.eclipse.aether.util.filter.DependencyFilterUtils.orFilter;\n+import static org.mule.runtime.core.util.Preconditions.checkNotNull;\n+import org.mule.functional.classloading.isolation.classification.PatternInclusionsDependencyFilter;\n+import org.mule.functional.classloading.isolation.maven.MavenModelFactory;\n+import org.mule.functional.junit4.infrastructure.ExtensionsTestInfrastructureDiscoverer;\n+import org.mule.runtime.core.DefaultMuleContext;\n+import org.mule.runtime.core.api.lifecycle.InitialisationException;\n+import org.mule.runtime.core.api.registry.MuleRegistry;\n+import org.mule.runtime.core.registry.DefaultRegistryBroker;\n+import org.mule.runtime.core.registry.MuleRegistryHelper;\n+import org.mule.runtime.extension.api.annotation.Extension;\n+import org.mule.runtime.module.extension.internal.introspection.version.StaticVersionResolver;\n+import org.mule.runtime.module.extension.internal.manager.DefaultExtensionManager;\n+import org.mule.runtime.module.extension.internal.manager.ExtensionManagerAdapter;\n+\n+import com.google.common.collect.Lists;\n+import com.google.common.collect.Maps;\n+\n+import java.io.File;\n+import java.io.FileFilter;\n+import java.net.MalformedURLException;\n+import java.net.URL;\n+import java.net.URLClassLoader;\n+import java.util.Collection;\n+import java.util.Collections;\n+import java.util.List;\n+import java.util.ListIterator;\n+import java.util.Map;\n+import java.util.Optional;\n+import java.util.Set;\n+import java.util.stream.Collectors;\n+\n+import org.apache.commons.io.filefilter.WildcardFileFilter;\n+import org.apache.maven.model.Model;\n+import org.eclipse.aether.artifact.Artifact;\n+import org.eclipse.aether.artifact.DefaultArtifact;\n+import org.eclipse.aether.graph.Dependency;\n+import org.eclipse.aether.graph.DependencyFilter;\n+import org.eclipse.aether.util.filter.PatternExclusionsDependencyFilter;\n+import org.slf4j.Logger;\n+import org.slf4j.LoggerFactory;\n+import org.springframework.beans.factory.config.BeanDefinition;\n+import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;\n+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;\n+import org.springframework.core.type.filter.AnnotationTypeFilter;\n+\n+/**\n+ * Creates the {@link ArtifactUrlClassification} based on the Maven dependencies declared by the rootArtifact using Eclipse\n+ * Aether. Uses a {@link DependencyResolver} to resolve Maven dependencies.\n+ * <p/>\n+ * The classification process classifies the rootArtifact dependencies in three groups: {@code provided}, {@code compile} and\n+ * {@code test} scopes. It resolves dependencies graph for each group applying filters and exclusions and classifies the list of\n+ * {@link URL}s that would define each class loader container, plugins and application.\n+ * <p/>\n+ * Dependencies resolution uses dependencies management declared by these artifacts while resolving the dependency graph.\n+ * <p/>\n+ * Plugins are discovered as {@link Extension} if they do have a annotated a {@link Class}. It generates the {@link Extension}\n+ * metadata in order to later register it to an {@link org.mule.runtime.extension.api.ExtensionManager}.\n+ *\n+ * @since 4.0\n+ */\n+public class AetherClassPathClassifier implements ClassPathClassifier {\n+\n+  public static final String POM = \"pom\";\n+  public static final String POM_XML = POM + \".xml\";\n+  public static final String MAVEN_COORDINATES_SEPARATOR = \":\";\n+  public static final String JAR_EXTENSION = \"jar\";\n+  public static final String SNAPSHOT_WILCARD_FILE_FILTER = \"*-SNAPSHOT*.*\";\n+  public static final String MULE_EXTENSION = \"mule-extension\";\n+  public static final String GENERATED_TEST_RESOURCES = \"generated-test-resources\";\n+  public static final String TESTS_CLASSIFIER = \"tests\";\n+\n+  protected final Logger logger = LoggerFactory.getLogger(this.getClass());\n+\n+  private DependencyResolver dependencyResolver;\n+\n+  /**\n+   * Creates an instance of the classifier.\n+   *\n+   * @param dependencyResolver {@link DependencyResolver} to resolve dependencies\n+   */\n+  public AetherClassPathClassifier(DependencyResolver dependencyResolver) {\n+    checkNotNull(dependencyResolver, \"dependencyResolver cannot be null\");\n+    this.dependencyResolver = dependencyResolver;\n+  }\n+\n+  /**\n+   * Classifies {@link URL}s and {@link Dependency}s to define how the container, plugins and application class loaders should be\n+   * created.\n+   *\n+   * @param context {@link ClassPathClassifierContext} to be used during the classification\n+   * @return {@link ArtifactUrlClassification} as result with the classification\n+   */\n+  @Override\n+  public ArtifactUrlClassification classify(ClassPathClassifierContext context) {\n+    Artifact rootArtifact = getRootArtifact(context);\n+    if (logger.isDebugEnabled()) {\n+      logger.debug(\"Building class loaders for rootArtifact: {}\", rootArtifact);\n+    }\n+    List<Dependency> directDependencies = dependencyResolver\n+        .getDirectDependencies(rootArtifact);\n+\n+    List<PluginUrlClassification> pluginUrlClassifications =\n+        buildPluginUrlClassifications(context, rootArtifact, directDependencies);\n+\n+    List<URL> containerUrls =\n+        buildContainerUrlClassification(context, directDependencies, pluginUrlClassifications);\n+    List<URL> applicationUrls = buildApplicationUrlClassification(context, rootArtifact, directDependencies,\n+                                                                  pluginUrlClassifications);\n+\n+    return new ArtifactUrlClassification(containerUrls, pluginUrlClassifications,\n+                                         applicationUrls);\n+  }\n+\n+  /**\n+   * Gets the Maven artifact for located at {@link ClassPathClassifierContext#getRootArtifactClassesFolder()}\n+   *\n+   * @param context {@link ClassPathClassifierContext} for classification process\n+   * @return {@link Artifact} that represents the rootArtifact\n+   */\n+  private Artifact getRootArtifact(ClassPathClassifierContext context) {\n+    File pomFile = new File(context.getRootArtifactClassesFolder().getParentFile().getParentFile(), POM_XML);\n+    if (logger.isDebugEnabled()) {\n+      logger.debug(\"Reading rootArtifact from pom file: {}\", pomFile);\n+    }\n+    Model model = MavenModelFactory.createMavenProject(pomFile);\n+\n+    return new DefaultArtifact(model.getGroupId() != null ? model.getGroupId() : model.getParent().getGroupId(),\n+                               model.getArtifactId(), model.getPackaging(),\n+                               model.getVersion() != null ? model.getVersion() : model.getParent().getVersion());\n+  }\n+\n+  /**\n+   * Container classification is being done by resolving the {@value org.eclipse.aether.util.artifact.JavaScopes#PROVIDED} direct\n+   * dependencies of the rootArtifact. Is uses the exclusions defined in\n+   * {@link ClassPathClassifierContext#getProvidedExclusions()} to filter the dependency graph plus\n+   * {@link ClassPathClassifierContext#getExcludedArtifacts()}.\n+   * <p/>\n+   * In order to resolve correctly the {@value org.eclipse.aether.util.artifact.JavaScopes#PROVIDED} direct dependencies it will\n+   * get for each one the manage dependencies and use that list to resolve the graph.\n+   *\n+   * @param context {@link ClassPathClassifierContext} with settings for the classification process\n+   * @param pluginUrlClassifications {@link PluginUrlClassification}s to check if rootArtifact was classified as plugin\n+   * @return {@link List} of {@link URL}s for the container class loader\n+   */\n+  private List<URL> buildContainerUrlClassification(ClassPathClassifierContext context,\n+                                                    List<Dependency> directDependencies,\n+                                                    List<PluginUrlClassification> pluginUrlClassifications) {\n+    directDependencies = directDependencies.stream()\n+        .filter(directDep -> directDep.getScope().equals(PROVIDED))\n+        .map(depToTransform -> depToTransform.setScope(COMPILE)).collect(toList());\n+\n+    if (logger.isDebugEnabled()) {\n+      logger.debug(\n+                   \"Selected direct dependencies to be used for resolving container dependency graph (changed to compile in order to resolve the graph): {}\",\n+                   directDependencies);\n+    }\n+\n+    Set<Dependency> managedDependencies = directDependencies.stream()\n+        .map(directDep -> dependencyResolver.readArtifactDescriptor(directDep.getArtifact()).getManagedDependencies())\n+        .flatMap(l -> l.stream()).collect(\n+                                          Collectors.toSet());\n+\n+    if (logger.isDebugEnabled()) {\n+      logger.debug(\n+                   \"Collected managed dependencies from direct provided dependencies to be used for resolving container dependency graph: {}\",\n+                   managedDependencies);\n+    }\n+\n+    List<String> excludedFilterPattern = newArrayList(context.getProvidedExclusions());\n+    excludedFilterPattern.addAll(context.getExcludedArtifacts());\n+    if (!pluginUrlClassifications.isEmpty()) {\n+      excludedFilterPattern.addAll(pluginUrlClassifications.stream()\n+          .map(pluginUrlClassification -> pluginUrlClassification.getName()).collect(toList()));\n+    }\n+\n+    if (logger.isDebugEnabled()) {\n+      logger.debug(\"Resolving dependencies for container using exclusion filter patterns: {}\", excludedFilterPattern);\n+    }\n+    if (!context.getProvidedInclusions().isEmpty()) {\n+      if (logger.isDebugEnabled()) {\n+        logger.debug(\"Resolving dependencies for container using inclusion filter patterns: {}\", context.getProvidedInclusions());\n+      }\n+    }\n+\n+    List<URL> containerUrls = toUrl(dependencyResolver\n+        .resolveDependencies(null, directDependencies, newArrayList(managedDependencies),\n+                             orFilter(new org.eclipse.aether.util.filter.PatternInclusionsDependencyFilter(context\n+                                 .getProvidedInclusions()),\n+                                      new PatternExclusionsDependencyFilter(excludedFilterPattern))));\n+\n+    containerUrls = containerUrls.stream().filter(url -> !url.getFile().endsWith(POM_XML)).collect(toList());\n+\n+    resolveSnapshotVersionsFromClasspath(containerUrls, context.getClassPathURLs());\n+\n+    return containerUrls;\n+  }\n+\n+  /**\n+   * Plugin classifications are being done by resolving the dependencies for each plugin coordinates defined at\n+   * {@link ClassPathClassifierContext#getPluginCoordinates()}. These artifacts should be defined as\n+   * {@value org.eclipse.aether.util.artifact.JavaScopes#PROVIDED} in the rootArtifact and if these coordinates don't have a\n+   * version the rootArtifact version would be used to look for the Maven plugin artifact.\n+   * <p/>\n+   * While resolving the dependencies for the plugin artifact, only {@value org.eclipse.aether.util.artifact.JavaScopes#COMPILE}\n+   * dependencies will be selected. {@link ClassPathClassifierContext#getExcludedArtifacts()} will be exluded too.\n+   * <p/>\n+   * The resulting {@link PluginUrlClassification} for each plugin will have as name the Maven artifact id coordinates:\n+   * {@code <groupId>:<artifactId>:<extension>[:<classifier>]:<version>}.\n+   *\n+   * @param context {@link ClassPathClassifierContext} with settings for the classification process\n+   * @param rootArtifact {@link Artifact} that defines the current artifact that requested to build this class loaders\n+   * @param directDependencies {@link List} of {@link Dependency} with direct dependencies for the rootArtifact\n+   * @return {@link List} of {@link PluginUrlClassification}s for plugins class loaders\n+   */\n+  private List<PluginUrlClassification> buildPluginUrlClassifications(ClassPathClassifierContext context,\n+                                                                      Artifact rootArtifact,\n+                                                                      List<Dependency> directDependencies) {\n+    List<PluginUrlClassification> pluginUrlClassifications = newArrayList();\n+    File baseResourcesFolder = getGeneratedResourcesBase(context.getRootArtifactTestClassesFolder());\n+\n+    ExtensionsTestInfrastructureDiscoverer extensionsInfrastructure =\n+        new ExtensionsTestInfrastructureDiscoverer(createExtensionManager());\n+\n+    if (isExtensionPlugin(rootArtifact)) {\n+      if (logger.isDebugEnabled()) {\n+        logger.debug(\"rootArtifact '{}' identified as Extension plugin\", rootArtifact);\n+      }\n+      pluginUrlClassifications\n+          .add(buildPluginUrlClassification(rootArtifact, context, baseResourcesFolder,\n+                                            extensionsInfrastructure));\n+    }\n+\n+    if (context.getPluginCoordinates() != null) {\n+      for (String pluginCoords : context.getPluginCoordinates()) {\n+        if (logger.isDebugEnabled()) {","path":"tests/functional/src/main/java/org/mule/functional/api/classloading/isolation/AetherClassPathClassifier.java","position":253,"original_position":253,"commit_id":"ca6f592a9cbf001d041f501d7cbac6d1778f9c3b","original_commit_id":"ca6f592a9cbf001d041f501d7cbac6d1778f9c3b","user":{"login":"pablokraan","id":561399,"avatar_url":"https://avatars.githubusercontent.com/u/561399?v=3","gravatar_id":"","url":"https://api.github.com/users/pablokraan","html_url":"https://github.com/pablokraan","followers_url":"https://api.github.com/users/pablokraan/followers","following_url":"https://api.github.com/users/pablokraan/following{/other_user}","gists_url":"https://api.github.com/users/pablokraan/gists{/gist_id}","starred_url":"https://api.github.com/users/pablokraan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pablokraan/subscriptions","organizations_url":"https://api.github.com/users/pablokraan/orgs","repos_url":"https://api.github.com/users/pablokraan/repos","events_url":"https://api.github.com/users/pablokraan/events{/privacy}","received_events_url":"https://api.github.com/users/pablokraan/received_events","type":"User","site_admin":false},"body":"Extract a new method from this block","created_at":"2016-09-06T18:14:19Z","updated_at":"2016-09-06T18:14:19Z","html_url":"https://github.com/mulesoft/mule/pull/3236#discussion_r77689232","pull_request_url":"https://api.github.com/repos/mulesoft/mule/pulls/3236","_links":{"self":{"href":"https://api.github.com/repos/mulesoft/mule/pulls/comments/77689232"},"html":{"href":"https://github.com/mulesoft/mule/pull/3236#discussion_r77689232"},"pull_request":{"href":"https://api.github.com/repos/mulesoft/mule/pulls/3236"}}},"pull_request":{"url":"https://api.github.com/repos/mulesoft/mule/pulls/3236","id":84119042,"html_url":"https://github.com/mulesoft/mule/pull/3236","diff_url":"https://github.com/mulesoft/mule/pull/3236.diff","patch_url":"https://github.com/mulesoft/mule/pull/3236.patch","issue_url":"https://api.github.com/repos/mulesoft/mule/issues/3236","number":3236,"state":"open","locked":false,"title":"MULE-10126: ArtifactClassLoaderRunner - Add support for artifacts with different versions","user":{"login":"gsfernandes","id":7305769,"avatar_url":"https://avatars.githubusercontent.com/u/7305769?v=3","gravatar_id":"","url":"https://api.github.com/users/gsfernandes","html_url":"https://github.com/gsfernandes","followers_url":"https://api.github.com/users/gsfernandes/followers","following_url":"https://api.github.com/users/gsfernandes/following{/other_user}","gists_url":"https://api.github.com/users/gsfernandes/gists{/gist_id}","starred_url":"https://api.github.com/users/gsfernandes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gsfernandes/subscriptions","organizations_url":"https://api.github.com/users/gsfernandes/orgs","repos_url":"https://api.github.com/users/gsfernandes/repos","events_url":"https://api.github.com/users/gsfernandes/events{/privacy}","received_events_url":"https://api.github.com/users/gsfernandes/received_events","type":"User","site_admin":false},"body":"- Use eclipse aether to resolve dependencies\r\n- Support different versions of artifacts at plugin/container level\r\n- Allow to be used from maven plugins\r\n- Avoid hard coded reactor for resolving multi module references","created_at":"2016-09-06T13:09:41Z","updated_at":"2016-09-06T18:14:19Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7c6c26254e349677b3ef3621b0950686662de188","assignee":{"login":"pablokraan","id":561399,"avatar_url":"https://avatars.githubusercontent.com/u/561399?v=3","gravatar_id":"","url":"https://api.github.com/users/pablokraan","html_url":"https://github.com/pablokraan","followers_url":"https://api.github.com/users/pablokraan/followers","following_url":"https://api.github.com/users/pablokraan/following{/other_user}","gists_url":"https://api.github.com/users/pablokraan/gists{/gist_id}","starred_url":"https://api.github.com/users/pablokraan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pablokraan/subscriptions","organizations_url":"https://api.github.com/users/pablokraan/orgs","repos_url":"https://api.github.com/users/pablokraan/repos","events_url":"https://api.github.com/users/pablokraan/events{/privacy}","received_events_url":"https://api.github.com/users/pablokraan/received_events","type":"User","site_admin":false},"assignees":[{"login":"pablokraan","id":561399,"avatar_url":"https://avatars.githubusercontent.com/u/561399?v=3","gravatar_id":"","url":"https://api.github.com/users/pablokraan","html_url":"https://github.com/pablokraan","followers_url":"https://api.github.com/users/pablokraan/followers","following_url":"https://api.github.com/users/pablokraan/following{/other_user}","gists_url":"https://api.github.com/users/pablokraan/gists{/gist_id}","starred_url":"https://api.github.com/users/pablokraan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pablokraan/subscriptions","organizations_url":"https://api.github.com/users/pablokraan/orgs","repos_url":"https://api.github.com/users/pablokraan/repos","events_url":"https://api.github.com/users/pablokraan/events{/privacy}","received_events_url":"https://api.github.com/users/pablokraan/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/mulesoft/mule/pulls/3236/commits","review_comments_url":"https://api.github.com/repos/mulesoft/mule/pulls/3236/comments","review_comment_url":"https://api.github.com/repos/mulesoft/mule/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mulesoft/mule/issues/3236/comments","statuses_url":"https://api.github.com/repos/mulesoft/mule/statuses/ca6f592a9cbf001d041f501d7cbac6d1778f9c3b","head":{"label":"mulesoft:MULE-10126","ref":"MULE-10126","sha":"ca6f592a9cbf001d041f501d7cbac6d1778f9c3b","user":{"login":"mulesoft","id":185740,"avatar_url":"https://avatars.githubusercontent.com/u/185740?v=3","gravatar_id":"","url":"https://api.github.com/users/mulesoft","html_url":"https://github.com/mulesoft","followers_url":"https://api.github.com/users/mulesoft/followers","following_url":"https://api.github.com/users/mulesoft/following{/other_user}","gists_url":"https://api.github.com/users/mulesoft/gists{/gist_id}","starred_url":"https://api.github.com/users/mulesoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mulesoft/subscriptions","organizations_url":"https://api.github.com/users/mulesoft/orgs","repos_url":"https://api.github.com/users/mulesoft/repos","events_url":"https://api.github.com/users/mulesoft/events{/privacy}","received_events_url":"https://api.github.com/users/mulesoft/received_events","type":"Organization","site_admin":false},"repo":{"id":7058562,"name":"mule","full_name":"mulesoft/mule","owner":{"login":"mulesoft","id":185740,"avatar_url":"https://avatars.githubusercontent.com/u/185740?v=3","gravatar_id":"","url":"https://api.github.com/users/mulesoft","html_url":"https://github.com/mulesoft","followers_url":"https://api.github.com/users/mulesoft/followers","following_url":"https://api.github.com/users/mulesoft/following{/other_user}","gists_url":"https://api.github.com/users/mulesoft/gists{/gist_id}","starred_url":"https://api.github.com/users/mulesoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mulesoft/subscriptions","organizations_url":"https://api.github.com/users/mulesoft/orgs","repos_url":"https://api.github.com/users/mulesoft/repos","events_url":"https://api.github.com/users/mulesoft/events{/privacy}","received_events_url":"https://api.github.com/users/mulesoft/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mulesoft/mule","description":"Mule Community Edition","fork":false,"url":"https://api.github.com/repos/mulesoft/mule","forks_url":"https://api.github.com/repos/mulesoft/mule/forks","keys_url":"https://api.github.com/repos/mulesoft/mule/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mulesoft/mule/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mulesoft/mule/teams","hooks_url":"https://api.github.com/repos/mulesoft/mule/hooks","issue_events_url":"https://api.github.com/repos/mulesoft/mule/issues/events{/number}","events_url":"https://api.github.com/repos/mulesoft/mule/events","assignees_url":"https://api.github.com/repos/mulesoft/mule/assignees{/user}","branches_url":"https://api.github.com/repos/mulesoft/mule/branches{/branch}","tags_url":"https://api.github.com/repos/mulesoft/mule/tags","blobs_url":"https://api.github.com/repos/mulesoft/mule/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mulesoft/mule/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mulesoft/mule/git/refs{/sha}","trees_url":"https://api.github.com/repos/mulesoft/mule/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mulesoft/mule/statuses/{sha}","languages_url":"https://api.github.com/repos/mulesoft/mule/languages","stargazers_url":"https://api.github.com/repos/mulesoft/mule/stargazers","contributors_url":"https://api.github.com/repos/mulesoft/mule/contributors","subscribers_url":"https://api.github.com/repos/mulesoft/mule/subscribers","subscription_url":"https://api.github.com/repos/mulesoft/mule/subscription","commits_url":"https://api.github.com/repos/mulesoft/mule/commits{/sha}","git_commits_url":"https://api.github.com/repos/mulesoft/mule/git/commits{/sha}","comments_url":"https://api.github.com/repos/mulesoft/mule/comments{/number}","issue_comment_url":"https://api.github.com/repos/mulesoft/mule/issues/comments{/number}","contents_url":"https://api.github.com/repos/mulesoft/mule/contents/{+path}","compare_url":"https://api.github.com/repos/mulesoft/mule/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mulesoft/mule/merges","archive_url":"https://api.github.com/repos/mulesoft/mule/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mulesoft/mule/downloads","issues_url":"https://api.github.com/repos/mulesoft/mule/issues{/number}","pulls_url":"https://api.github.com/repos/mulesoft/mule/pulls{/number}","milestones_url":"https://api.github.com/repos/mulesoft/mule/milestones{/number}","notifications_url":"https://api.github.com/repos/mulesoft/mule/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mulesoft/mule/labels{/name}","releases_url":"https://api.github.com/repos/mulesoft/mule/releases{/id}","deployments_url":"https://api.github.com/repos/mulesoft/mule/deployments","created_at":"2012-12-07T19:23:06Z","updated_at":"2016-09-03T22:45:30Z","pushed_at":"2016-09-06T18:06:27Z","git_url":"git://github.com/mulesoft/mule.git","ssh_url":"git@github.com:mulesoft/mule.git","clone_url":"https://github.com/mulesoft/mule.git","svn_url":"https://github.com/mulesoft/mule","homepage":null,"size":269706,"stargazers_count":365,"watchers_count":365,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":379,"mirror_url":null,"open_issues_count":19,"forks":379,"open_issues":19,"watchers":365,"default_branch":"mule-4.x"}},"base":{"label":"mulesoft:mule-4.x","ref":"mule-4.x","sha":"c7d47805aa69d3d4f24441244c75326e4b11f6ec","user":{"login":"mulesoft","id":185740,"avatar_url":"https://avatars.githubusercontent.com/u/185740?v=3","gravatar_id":"","url":"https://api.github.com/users/mulesoft","html_url":"https://github.com/mulesoft","followers_url":"https://api.github.com/users/mulesoft/followers","following_url":"https://api.github.com/users/mulesoft/following{/other_user}","gists_url":"https://api.github.com/users/mulesoft/gists{/gist_id}","starred_url":"https://api.github.com/users/mulesoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mulesoft/subscriptions","organizations_url":"https://api.github.com/users/mulesoft/orgs","repos_url":"https://api.github.com/users/mulesoft/repos","events_url":"https://api.github.com/users/mulesoft/events{/privacy}","received_events_url":"https://api.github.com/users/mulesoft/received_events","type":"Organization","site_admin":false},"repo":{"id":7058562,"name":"mule","full_name":"mulesoft/mule","owner":{"login":"mulesoft","id":185740,"avatar_url":"https://avatars.githubusercontent.com/u/185740?v=3","gravatar_id":"","url":"https://api.github.com/users/mulesoft","html_url":"https://github.com/mulesoft","followers_url":"https://api.github.com/users/mulesoft/followers","following_url":"https://api.github.com/users/mulesoft/following{/other_user}","gists_url":"https://api.github.com/users/mulesoft/gists{/gist_id}","starred_url":"https://api.github.com/users/mulesoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mulesoft/subscriptions","organizations_url":"https://api.github.com/users/mulesoft/orgs","repos_url":"https://api.github.com/users/mulesoft/repos","events_url":"https://api.github.com/users/mulesoft/events{/privacy}","received_events_url":"https://api.github.com/users/mulesoft/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mulesoft/mule","description":"Mule Community Edition","fork":false,"url":"https://api.github.com/repos/mulesoft/mule","forks_url":"https://api.github.com/repos/mulesoft/mule/forks","keys_url":"https://api.github.com/repos/mulesoft/mule/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mulesoft/mule/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mulesoft/mule/teams","hooks_url":"https://api.github.com/repos/mulesoft/mule/hooks","issue_events_url":"https://api.github.com/repos/mulesoft/mule/issues/events{/number}","events_url":"https://api.github.com/repos/mulesoft/mule/events","assignees_url":"https://api.github.com/repos/mulesoft/mule/assignees{/user}","branches_url":"https://api.github.com/repos/mulesoft/mule/branches{/branch}","tags_url":"https://api.github.com/repos/mulesoft/mule/tags","blobs_url":"https://api.github.com/repos/mulesoft/mule/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mulesoft/mule/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mulesoft/mule/git/refs{/sha}","trees_url":"https://api.github.com/repos/mulesoft/mule/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mulesoft/mule/statuses/{sha}","languages_url":"https://api.github.com/repos/mulesoft/mule/languages","stargazers_url":"https://api.github.com/repos/mulesoft/mule/stargazers","contributors_url":"https://api.github.com/repos/mulesoft/mule/contributors","subscribers_url":"https://api.github.com/repos/mulesoft/mule/subscribers","subscription_url":"https://api.github.com/repos/mulesoft/mule/subscription","commits_url":"https://api.github.com/repos/mulesoft/mule/commits{/sha}","git_commits_url":"https://api.github.com/repos/mulesoft/mule/git/commits{/sha}","comments_url":"https://api.github.com/repos/mulesoft/mule/comments{/number}","issue_comment_url":"https://api.github.com/repos/mulesoft/mule/issues/comments{/number}","contents_url":"https://api.github.com/repos/mulesoft/mule/contents/{+path}","compare_url":"https://api.github.com/repos/mulesoft/mule/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mulesoft/mule/merges","archive_url":"https://api.github.com/repos/mulesoft/mule/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mulesoft/mule/downloads","issues_url":"https://api.github.com/repos/mulesoft/mule/issues{/number}","pulls_url":"https://api.github.com/repos/mulesoft/mule/pulls{/number}","milestones_url":"https://api.github.com/repos/mulesoft/mule/milestones{/number}","notifications_url":"https://api.github.com/repos/mulesoft/mule/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mulesoft/mule/labels{/name}","releases_url":"https://api.github.com/repos/mulesoft/mule/releases{/id}","deployments_url":"https://api.github.com/repos/mulesoft/mule/deployments","created_at":"2012-12-07T19:23:06Z","updated_at":"2016-09-03T22:45:30Z","pushed_at":"2016-09-06T18:06:27Z","git_url":"git://github.com/mulesoft/mule.git","ssh_url":"git@github.com:mulesoft/mule.git","clone_url":"https://github.com/mulesoft/mule.git","svn_url":"https://github.com/mulesoft/mule","homepage":null,"size":269706,"stargazers_count":365,"watchers_count":365,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":379,"mirror_url":null,"open_issues_count":19,"forks":379,"open_issues":19,"watchers":365,"default_branch":"mule-4.x"}},"_links":{"self":{"href":"https://api.github.com/repos/mulesoft/mule/pulls/3236"},"html":{"href":"https://github.com/mulesoft/mule/pull/3236"},"issue":{"href":"https://api.github.com/repos/mulesoft/mule/issues/3236"},"comments":{"href":"https://api.github.com/repos/mulesoft/mule/issues/3236/comments"},"review_comments":{"href":"https://api.github.com/repos/mulesoft/mule/pulls/3236/comments"},"review_comment":{"href":"https://api.github.com/repos/mulesoft/mule/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mulesoft/mule/pulls/3236/commits"},"statuses":{"href":"https://api.github.com/repos/mulesoft/mule/statuses/ca6f592a9cbf001d041f501d7cbac6d1778f9c3b"}}}}
{"actor":{"display_login":"pablokraan"}}