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.cli.impl.descriptor.CommandDescriptorImpl;
022 import org.crsh.cli.Argument;
023 import org.crsh.cli.Command;
024 import org.crsh.cli.Option;
025 import org.crsh.cli.impl.lang.CommandFactory;
026 import org.crsh.cli.impl.invocation.InvocationMatch;
027 import org.crsh.cli.impl.invocation.InvocationMatcher;
028 import org.crsh.shell.Shell;
029 import org.crsh.shell.ShellFactory;
030 import org.crsh.shell.impl.remoting.RemoteClient;
031
032 import java.io.File;
033 import java.lang.instrument.Instrumentation;
034 import java.util.Collections;
035 import java.util.List;
036 import java.util.Map;
037 import java.util.Properties;
038 import java.util.logging.Level;
039 import java.util.logging.Logger;
040
041 public class Agent {
042
043 /** . */
044 private static Logger log = Logger.getLogger(Agent.class.getName());
045
046 public static void agentmain(final String agentArgs, final Instrumentation inst) throws Exception {
047 log.log(Level.INFO, "CRaSH agent loaded");
048
049 //
050 Thread t = new Thread() {
051 @Override
052 public void run() {
053 try {
054 CommandDescriptorImpl<Agent> c = CommandFactory.DEFAULT.create(Agent.class);
055 InvocationMatcher<Agent> matcher = c.invoker("main");
056 InvocationMatch<Agent> match = matcher.match(agentArgs);
057 match.invoke(new Agent(inst));
058 } catch (Exception e) {
059 e.printStackTrace();
060 }
061 }
062 };
063
064 //
065 t.start();
066 log.log(Level.INFO, "Spawned CRaSH thread " + t.getId() + " for further processing");
067 }
068
069 /** . */
070 private final Instrumentation instrumentation;
071
072 public Agent(Instrumentation instrumentation) {
073 this.instrumentation = instrumentation;
074 }
075
076 @Command
077 public void main(
078 @Option(names={"c","cmd"})
079 List<String> cmds,
080 @Option(names={"conf"})
081 List<String> confs,
082 @Option(names={"p","property"})
083 List<String> properties,
084 @Argument(name = "port")
085 Integer port) throws Exception {
086
087 //
088 Bootstrap bootstrap = new Bootstrap(Thread.currentThread().getContextClassLoader());
089
090 //
091 if (cmds != null) {
092 for (String cmd : cmds) {
093 File cmdPath = new File(cmd);
094 bootstrap.addToCmdPath(cmdPath);
095 }
096 }
097
098 //
099 if (confs != null) {
100 for (String conf : confs) {
101 File confPath = new File(conf);
102 bootstrap.addToConfPath(confPath);
103 }
104 }
105
106 //
107 if (properties != null) {
108 Properties config = new Properties();
109 for (String property : properties) {
110 int index = property.indexOf('=');
111 if (index == -1) {
112 config.setProperty(property, "");
113 } else {
114 config.setProperty(property.substring(0, index), property.substring(index + 1));
115 }
116 }
117 bootstrap.setConfig(config);
118 }
119
120 // Set the instrumentation available as an attribute
121 Map<String, Object> attributes = Collections.<String, Object>singletonMap("instrumentation", instrumentation);
122 bootstrap.setAttributes(attributes);
123
124 // Do bootstrap
125 bootstrap.bootstrap();
126
127 //
128 try {
129 ShellFactory factory = bootstrap.getContext().getPlugin(ShellFactory.class);
130 Shell shell = factory.create(null);
131 RemoteClient client = new RemoteClient(port, shell);
132 log.log(Level.INFO, "Callback back remote on port " + port);
133 client.connect();
134 client.getRunnable().run();
135 }
136 finally {
137 bootstrap.shutdown();
138 }
139 }
140 }