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