diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/boot/AgentPackageNotFoundException.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/boot/AgentPackageNotFoundException.java new file mode 100644 index 0000000000000000000000000000000000000000..b356c3ca985f8d47ba0391d25e6c5fac416ad7ee --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/boot/AgentPackageNotFoundException.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.agent.core.boot; + +/** + * @author wusheng + */ +public class AgentPackageNotFoundException extends Exception { + public AgentPackageNotFoundException(String message) { + super(message); + } +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/boot/AgentPackagePath.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/boot/AgentPackagePath.java new file mode 100644 index 0000000000000000000000000000000000000000..186c876a2ccc8d01575753cce1bd4c3e37b79012 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/boot/AgentPackagePath.java @@ -0,0 +1,71 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.agent.core.boot; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import org.skywalking.apm.agent.core.logging.SystemOutWriter; +import org.skywalking.apm.logging.ILog; +import org.skywalking.apm.logging.LogManager; + +/** + * @author wusheng + */ +public class AgentPackagePath { + private static final ILog logger = LogManager.getLogger(AgentPackagePath.class); + + private static File AGENT_PACKAGE_PATH; + + public static File getPath() throws AgentPackageNotFoundException { + if (AGENT_PACKAGE_PATH == null) { + AGENT_PACKAGE_PATH = findPath(); + } + return AGENT_PACKAGE_PATH; + } + + private static File findPath() throws AgentPackageNotFoundException { + String classResourcePath = AgentPackagePath.class.getName().replaceAll("\\.", "/") + ".class"; + + URL resource = AgentPackagePath.class.getClassLoader().getSystemClassLoader().getResource(classResourcePath); + if (resource != null) { + String urlString = resource.toString(); + + SystemOutWriter.INSTANCE.write(urlString); + logger.debug(urlString); + + urlString = urlString.substring(urlString.indexOf("file:"), urlString.indexOf('!')); + File agentJarFile = null; + try { + agentJarFile = new File(new URL(urlString).getFile()); + } catch (MalformedURLException e) { + SystemOutWriter.INSTANCE.write("Can not locate agent jar file by url:" + urlString); + logger.error(e, "Can not locate agent jar file by url: {}", urlString); + } + if (agentJarFile.exists()) { + return agentJarFile.getParentFile(); + } + } + + SystemOutWriter.INSTANCE.write("Can not locate agent jar file."); + logger.info("Can not locate agent jar file."); + throw new AgentPackageNotFoundException("Can not locate agent jar file."); + } + +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/conf/ConfigNotFoundException.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/conf/ConfigNotFoundException.java new file mode 100644 index 0000000000000000000000000000000000000000..6c8dffac0e57909e4d7474740cbdf1bcccb1275e --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/conf/ConfigNotFoundException.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.agent.core.conf; + +/** + * @author wusheng + */ +public class ConfigNotFoundException extends Exception { + public ConfigNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public ConfigNotFoundException(String message) { + super(message); + } +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java index 1d62349f7c5b3bcbb8cebc0977310045a81f918e..560b176ebafdf00b6adda148314e4cedd1b3f375 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java @@ -22,9 +22,9 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; import java.util.Properties; +import org.skywalking.apm.agent.core.boot.AgentPackageNotFoundException; +import org.skywalking.apm.agent.core.boot.AgentPackagePath; import org.skywalking.apm.logging.ILog; import org.skywalking.apm.logging.LogManager; import org.skywalking.apm.util.ConfigInitializer; @@ -52,32 +52,17 @@ public class SnifferConfigInitializer { * 1. applicationCode. "-DapplicationCode=" or {@link Config.Agent#APPLICATION_CODE} * 2. servers. "-Dservers=" or {@link Config.Collector#SERVERS} */ - public static void initialize() { + public static void initialize() throws ConfigNotFoundException, AgentPackageNotFoundException { InputStream configFileStream; - configFileStream = loadConfigBySystemProperty(); + configFileStream = loadConfigFromAgentFolder(); - if (configFileStream == null) { - configFileStream = SnifferConfigInitializer.class.getResourceAsStream(CONFIG_FILE_NAME); - - if (configFileStream == null) { - logger.info("No config file found, according system property '-Dconfig'."); - configFileStream = loadConfigFromAgentFolder(); - } else { - logger.info("{} file found in class path.", CONFIG_FILE_NAME); - } - } - - if (configFileStream == null) { - logger.info("No {} found, sky-walking is going to run in default config.", CONFIG_FILE_NAME); - } else { - try { - Properties properties = new Properties(); - properties.load(configFileStream); - ConfigInitializer.initialize(properties, Config.class); - } catch (Exception e) { - logger.error("Failed to read the config file, sky-walking is going to run in default config.", e); - } + try { + Properties properties = new Properties(); + properties.load(configFileStream); + ConfigInitializer.initialize(properties, Config.class); + } catch (Exception e) { + logger.error("Failed to read the config file, sky-walking is going to run in default config.", e); } String applicationCode = System.getProperty("applicationCode"); @@ -131,50 +116,16 @@ public class SnifferConfigInitializer { * * @return the config file {@link InputStream}, or null if not needEnhance. */ - private static InputStream loadConfigFromAgentFolder() { - String agentBasePath = initAgentBasePath(); - if (!StringUtil.isEmpty(agentBasePath)) { - File configFile = new File(agentBasePath, CONFIG_FILE_NAME); - if (configFile.exists() && configFile.isFile()) { - try { - logger.info("{} file found in agent folder.", CONFIG_FILE_NAME); - return new FileInputStream(configFile); - } catch (FileNotFoundException e) { - logger.error(e, "Fail to load {} in path {}, according auto-agent-folder mechanism.", CONFIG_FILE_NAME, agentBasePath); - } - } - } - - logger.info("No {} file found in agent folder.", CONFIG_FILE_NAME); - return null; - } - - /** - * Try to allocate the skywalking-agent.jar - * Some config files or output resources are from this path. - * - * @return he path, where the skywalking-agent.jar is - */ - private static String initAgentBasePath() { - String classResourcePath = SnifferConfigInitializer.class.getName().replaceAll("\\.", "/") + ".class"; - - URL resource = SnifferConfigInitializer.class.getClassLoader().getSystemClassLoader().getResource(classResourcePath); - if (resource != null) { - String urlString = resource.toString(); - logger.debug(urlString); - urlString = urlString.substring(urlString.indexOf("file:"), urlString.indexOf('!')); - File agentJarFile = null; + private static InputStream loadConfigFromAgentFolder() throws AgentPackageNotFoundException, ConfigNotFoundException { + File configFile = new File(AgentPackagePath.getPath(), CONFIG_FILE_NAME); + if (configFile.exists() && configFile.isFile()) { try { - agentJarFile = new File(new URL(urlString).getFile()); - } catch (MalformedURLException e) { - logger.error(e, "Can not locate agent jar file by url:", urlString); - } - if (agentJarFile.exists()) { - return agentJarFile.getParentFile().getAbsolutePath(); + logger.info("{} file found in agent folder.", CONFIG_FILE_NAME); + return new FileInputStream(configFile); + } catch (FileNotFoundException e) { + throw new ConfigNotFoundException("Fail to load agent.config", e); } } - - logger.info("Can not locate agent jar file."); - return null; + throw new ConfigNotFoundException("Fail to load agent.config"); } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginBootstrap.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginBootstrap.java index 44011537f7d28d9cbc18de14fd21ebec83e655a1..c3e01d98e6805aadbb0b96f8b420e7de25e54813 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginBootstrap.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginBootstrap.java @@ -21,6 +21,9 @@ package org.skywalking.apm.agent.core.plugin; import java.net.URL; import java.util.ArrayList; import java.util.List; +import org.skywalking.apm.agent.core.boot.AgentPackageNotFoundException; +import org.skywalking.apm.agent.core.boot.AgentPackagePath; +import org.skywalking.apm.agent.core.plugin.loader.PluginClassLoader; import org.skywalking.apm.logging.ILog; import org.skywalking.apm.logging.LogManager; @@ -39,7 +42,9 @@ public class PluginBootstrap { * * @return plugin definition list. */ - public List loadPlugins() { + public List loadPlugins() throws AgentPackageNotFoundException { + PluginClassLoader.initAndGet(AgentPackagePath.getPath()); + PluginResourcesResolver resolver = new PluginResourcesResolver(); List resources = resolver.getResources(); diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/loader/PluginClassLoader.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/loader/PluginClassLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..e1cdef4d8ab5c8eaab1f3a62b79506984f994372 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/loader/PluginClassLoader.java @@ -0,0 +1,104 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.agent.core.plugin.loader; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.net.URL; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.locks.ReentrantLock; +import java.util.jar.JarFile; +import org.skywalking.apm.logging.ILog; +import org.skywalking.apm.logging.LogManager; + +/** + * The PluginClassLoader represents a classloader, + * which is in charge of finding plugins and interceptors. + * + * @author wusheng + */ +public class PluginClassLoader extends ClassLoader { + private static final ILog logger = LogManager.getLogger(PluginClassLoader.class); + private static PluginClassLoader LOADER; + + private List classpath; + private List allJars; + private ReentrantLock jarScanLock = new ReentrantLock(); + + public static PluginClassLoader get() { + return LOADER; + } + + public static PluginClassLoader initAndGet(File agentDictionary) { + LOADER = new PluginClassLoader(agentDictionary); + return get(); + } + + private PluginClassLoader(File agentDictionary) { + super(PluginClassLoader.class.getClassLoader()); + classpath = new LinkedList(); + classpath.add(new File(agentDictionary, "plugins")); + classpath.add(new File(agentDictionary, "activations")); + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(name); + } + + @Override + protected URL findResource(String name) { + getAllJars(); + throw new RuntimeException(""); + } + + private List getAllJars() { + if (allJars == null) { + jarScanLock.lock(); + try { + if (allJars == null) { + allJars = new LinkedList(); + for (File path : classpath) { + if (path.exists() && path.isDirectory()) { + String[] jarFileNames = path.list(new FilenameFilter() { + @Override public boolean accept(File dir, String name) { + return name.endsWith(".jar"); + } + }); + for (String fileName : jarFileNames) { + try { + JarFile jar = new JarFile(fileName); + allJars.add(jar); + } catch (IOException e) { + logger.error(e, "{} jar file can't be resolved", fileName); + } + } + } + } + } + } finally { + jarScanLock.unlock(); + } + } + + return allJars; + } +} diff --git a/apm-sniffer/apm-agent/src/main/java/org/skywalking/apm/agent/SkyWalkingAgent.java b/apm-sniffer/apm-agent/src/main/java/org/skywalking/apm/agent/SkyWalkingAgent.java index c776e4bab36b73be9c39f7acfee7a13edaa729d0..c0a9bdad79e7cde38c356e5d7890ac7fc08cf8b9 100644 --- a/apm-sniffer/apm-agent/src/main/java/org/skywalking/apm/agent/SkyWalkingAgent.java +++ b/apm-sniffer/apm-agent/src/main/java/org/skywalking/apm/agent/SkyWalkingAgent.java @@ -58,11 +58,17 @@ public class SkyWalkingAgent { * @throws PluginException */ public static void premain(String agentArgs, Instrumentation instrumentation) throws PluginException { - SnifferConfigInitializer.initialize(); + final PluginFinder pluginFinder; + try { + SnifferConfigInitializer.initialize(); - final PluginFinder pluginFinder = new PluginFinder(new PluginBootstrap().loadPlugins()); + pluginFinder = new PluginFinder(new PluginBootstrap().loadPlugins()); - ServiceManager.INSTANCE.boot(); + ServiceManager.INSTANCE.boot(); + } catch (Exception e) { + logger.error(e, "skywalking agent shutdown."); + return; + } Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() {