001 /*
002 * Copyright (C) 2012 eXo Platform SAS.
003 *
004 * This is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU Lesser General Public License as
006 * published by the Free Software Foundation; either version 2.1 of
007 * the License, or (at your option) any later version.
008 *
009 * This software is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public
015 * License along with this software; if not, write to the Free
016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018 */
019 package org.crsh.standalone;
020
021 import org.crsh.cmdline.ClassDescriptor;
022 import org.crsh.cmdline.CommandFactory;
023 import org.crsh.cmdline.annotations.Argument;
024 import org.crsh.cmdline.annotations.Command;
025 import org.crsh.cmdline.annotations.Option;
026 import org.crsh.cmdline.matcher.CommandMatch;
027 import org.crsh.cmdline.matcher.Matcher;
028 import org.crsh.shell.Shell;
029 import org.crsh.shell.ShellFactory;
030 import org.crsh.shell.impl.async.AsyncShell;
031 import org.crsh.shell.impl.remoting.RemoteClient;
032 import org.slf4j.Logger;
033 import org.slf4j.LoggerFactory;
034
035 import java.io.File;
036 import java.lang.instrument.Instrumentation;
037 import java.util.Collections;
038 import java.util.List;
039 import java.util.Map;
040 import java.util.Properties;
041
042 public class Agent {
043
044 /** . */
045 private static Logger log = LoggerFactory.getLogger(Agent.class);
046
047 public static void agentmain(final String agentArgs, final Instrumentation inst) throws Exception {
048 log.info("CRaSH agent loaded");
049
050 //
051 Thread t = new Thread() {
052 @Override
053 public void run() {
054 try {
055 ClassDescriptor<Agent> c = CommandFactory.create(Agent.class);
056 Matcher<Agent> matcher = c.matcher("main");
057 CommandMatch<Agent, ?, ?> match = matcher.match(agentArgs);
058 match.invoke(new Agent(inst));
059 } catch (Exception e) {
060 e.printStackTrace();
061 }
062 }
063 };
064
065 //
066 t.start();
067 log.info("Spawned CRaSH thread " + t.getId() + " for further processing");
068 }
069
070 /** . */
071 private final Instrumentation instrumentation;
072
073 public Agent(Instrumentation instrumentation) {
074 this.instrumentation = instrumentation;
075 }
076
077 @Command
078 public void main(
079 @Option(names={"j","jar"})
080 List<String> jars,
081 @Option(names={"c","cmd"})
082 List<String> cmds,
083 @Option(names={"conf"})
084 List<String> confs,
085 @Option(names={"p","property"})
086 List<String> properties,
087 @Argument(name = "port")
088 Integer port) throws Exception {
089
090 //
091 Bootstrap bootstrap = new Bootstrap(Thread.currentThread().getContextClassLoader());
092
093 //
094 if (cmds != null) {
095 for (String cmd : cmds) {
096 File cmdPath = new File(cmd);
097 bootstrap.addCmdPath(cmdPath);
098 }
099 }
100
101 //
102 if (confs != null) {
103 for (String conf : confs) {
104 File confPath = new File(conf);
105 bootstrap.addConfPath(confPath);
106 }
107 }
108
109 //
110 if (jars != null) {
111 for (String jar : jars) {
112 File jarFile = new File(jar);
113 bootstrap.addJarPath(jarFile);
114 }
115 }
116
117 //
118 if (properties != null) {
119 Properties config = new Properties();
120 for (String property : properties) {
121 int index = property.indexOf('=');
122 if (index == -1) {
123 config.setProperty(property, "");
124 } else {
125 config.setProperty(property.substring(0, index), property.substring(index + 1));
126 }
127 }
128 bootstrap.setConfig(config);
129 }
130
131 // Set the instrumentation available as an attribute
132 Map<String, Object> attributes = Collections.<String, Object>singletonMap("instrumentation", instrumentation);
133 bootstrap.setAttributes(attributes);
134
135 // Do bootstrap
136 bootstrap.bootstrap();
137
138 //
139 try {
140 ShellFactory factory = bootstrap.getContext().getPlugin(ShellFactory.class);
141 Shell shell = factory.create(null);
142 AsyncShell async = new AsyncShell(bootstrap.getContext().getExecutor(), shell);
143 RemoteClient client = new RemoteClient(port, async);
144 log.info("Callback back remote on port " + port);
145 client.connect();
146 client.getRunnable().run();
147 }
148 finally {
149 bootstrap.shutdown();
150 }
151 }
152 }