pax_global_header00006660000000000000000000000064116555471060014524gustar00rootroot0000000000000052 comment=abd857429450805e1a6f3f386653aee4e6462eb0 felix-gogo-shell-0.10.0/000077500000000000000000000000001165554710600147475ustar00rootroot00000000000000felix-gogo-shell-0.10.0/DEPENDENCIES000066400000000000000000000010121165554710600165120ustar00rootroot00000000000000Apache Felix Gogo Shell Copyright 2011 The Apache Software Foundation This software was developed at the Apache Software Foundation (http://www.apache.org) and may have dependencies on other Apache software licensed under Apache License 2.0. I. Included Third-Party Software None. II. Used Third-Party Software This product uses software developed at The OSGi Alliance (http://www.osgi.org/). Copyright (c) OSGi Alliance (2000, 2009). Licensed under the Apache License 2.0. III. License Summary - Apache License 2.0 felix-gogo-shell-0.10.0/LICENSE000066400000000000000000000261361165554710600157640ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. felix-gogo-shell-0.10.0/NOTICE000066400000000000000000000003231165554710600156510ustar00rootroot00000000000000Apache Felix Gogo Shell Copyright 2011 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). Licensed under the Apache License 2.0. felix-gogo-shell-0.10.0/doc/000077500000000000000000000000001165554710600155145ustar00rootroot00000000000000felix-gogo-shell-0.10.0/doc/changelog.txt000066400000000000000000000044031165554710600202050ustar00rootroot00000000000000Changes from 0.8.0 to 0.10.0 ---------------------------- ** Improvement * Added gosh_profile work around for issue with OSGi R4.3 API ambiguity. Changes from 0.6.1 to 0.8.0 --------------------------- ** Bug * [FELIX-2651] - [Gogo] MOTD formatting is broken under Windows ** Improvement * [FELIX-2661] - [Gogo] It should be easier to start Gogo shell non-interactively ** New Feature * [FELIX-2767] - gogo telnet IP address Changes from 0.6.0 to 0.6.1 --------------------------- ** Bug * [FELIX-2446] - [Gogo] The bundle context command is not used with a scope in gosh_profile * [FELIX-2477] - [gogo] shell procedural commands don't inherit closure arguments ** Improvement * [FELIX-2445] - [Gogo] Default gosh_profile should be updated to use system bundle to load java.lang.System * [FELIX-2543] - [Gogo] Should avoid using System.getProperty() to get configuration properties Gogo Shell 0.6.0 ---------------- ** Bug * [FELIX-1473] - [gogo] The syntax does not provide a way to call methods on a string * [FELIX-1474] - [gogo] result of commands is implicitly written to pipe * [FELIX-1493] - [gogo] automatic expansion of $args in Closure stops direct access to $args list * [FELIX-2337] - [gogo] no way to access array[] elements produced by assignment * [FELIX-2375] - [gogo] when supplied args can't be coerced, the error message prints the arg values, rather than their types * [FELIX-2380] - [gogo] lock contention in piped writer when reader doesn't read all input ** Improvement * [FELIX-1487] - Support for commands on multiple lines * [FELIX-2328] - [gogo] tidy-up runtime to remove optional code etc * [FELIX-2339] - [gogo] add support for running scripts * [FELIX-2342] - [gogo] remove old felix command adaptor ** New Feature * [FELIX-2363] - [Gogo] Add annotations for creating commands with optional and out-of-order arguments ** Task * [FELIX-1670] - [gogo] launcher bundle not required * [FELIX-1889] - Gogo should depend on the official OSGi jars * [FELIX-2334] - [Gogo] Use org.apache.felix as Maven groupId * [FELIX-2367] - [Gogo] Use org.apache.felix namespace to avoid any perceived legal issues felix-gogo-shell-0.10.0/pom.xml000066400000000000000000000113771165554710600162750ustar00rootroot00000000000000 org.apache.felix gogo-parent 0.6.0 ../gogo-parent/pom.xml 4.0.0 bundle Apache Felix Gogo Shell org.apache.felix.gogo.shell 0.10.0 org.osgi org.osgi.core 4.2.0 provided org.osgi org.osgi.compendium 4.0.0 provided org.apache.felix org.apache.felix.gogo.runtime 0.10.0 org.apache.felix maven-bundle-plugin true org.apache.felix.service.command; status="provisional", * org.apache.felix.gogo.shell, org.apache.felix.gogo.options ${pom.artifactId} The Apache Software Foundation org.apache.felix.gogo.shell.Activator {maven-resources},META-INF/LICENSE=LICENSE,META-INF/NOTICE=NOTICE,META-INF/DEPENDENCIES=DEPENDENCIES <_versionpolicy>[$(version;==;$(@)),$(version;+;$(@))) <_removeheaders>Private-Package,Ignore-Package,Include-Resource org.codehaus.mojo rat-maven-plugin false true true doc/* maven-eclipse.xml .checkstyle .externalToolBuilders/* maven-compiler-plugin 1.5 1.5 scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.apache.felix.gogo.shell-0.10.0 scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.apache.felix.gogo.shell-0.10.0 scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.apache.felix.gogo.shell-0.10.0 felix-gogo-shell-0.10.0/src/000077500000000000000000000000001165554710600155365ustar00rootroot00000000000000felix-gogo-shell-0.10.0/src/main/000077500000000000000000000000001165554710600164625ustar00rootroot00000000000000felix-gogo-shell-0.10.0/src/main/java/000077500000000000000000000000001165554710600174035ustar00rootroot00000000000000felix-gogo-shell-0.10.0/src/main/java/org/000077500000000000000000000000001165554710600201725ustar00rootroot00000000000000felix-gogo-shell-0.10.0/src/main/java/org/apache/000077500000000000000000000000001165554710600214135ustar00rootroot00000000000000felix-gogo-shell-0.10.0/src/main/java/org/apache/felix/000077500000000000000000000000001165554710600225225ustar00rootroot00000000000000felix-gogo-shell-0.10.0/src/main/java/org/apache/felix/gogo/000077500000000000000000000000001165554710600234555ustar00rootroot00000000000000felix-gogo-shell-0.10.0/src/main/java/org/apache/felix/gogo/options/000077500000000000000000000000001165554710600251505ustar00rootroot00000000000000felix-gogo-shell-0.10.0/src/main/java/org/apache/felix/gogo/options/Option.java000066400000000000000000000101001165554710600272530ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.felix.gogo.options; import java.util.List; public interface Option { /** * stop parsing on the first unknown option. This allows one parser to get its own options and * then pass the remaining options to another parser. * * @param stopOnBadOption */ Option setStopOnBadOption(boolean stopOnBadOption); /** * require options to precede args. Default is false, so options can appear between or after * args. * * @param optionsFirst */ Option setOptionsFirst(boolean optionsFirst); /** * parse arguments. If skipArgv0 is true, then parsing begins at arg1. This allows for commands * where argv0 is the command name rather than a real argument. * * @param argv * @param skipArg0 * @return */ Option parse(List argv, boolean skipArg0); /** * parse arguments. * * @see {@link #parse(List, boolean) */ Option parse(List argv); /** * parse arguments. * * @see {@link #parse(List, boolean) */ Option parse(Object[] argv, boolean skipArg0); /** * parse arguments. * * @see {@link #parse(List, boolean) */ Option parse(Object[] argv); /** * test whether specified option has been explicitly set. * * @param name * @return */ boolean isSet(String name); /** * get value of named option. If multiple options given, this method returns the last one. Use * {@link #getList(String)} to get all values. * * @param name * @return * @throws IllegalArgumentException * if value is not a String. */ String get(String name); /** * get list of all values for named option. * * @param name * @return empty list if option not given and no default specified. * @throws IllegalArgumentException * if all values are not Strings. */ List getList(String name); /** * get value of named option as an Object. If multiple options given, this method returns the * last one. Use {@link #getObjectList(String)} to get all values. * * @param name * @return */ Object getObject(String name); /** * get list of all Object values for named option. * * @param name * @return */ List getObjectList(String name); /** * get value of named option as a Number. * * @param name * @return * @throws IllegalArgumentException * if argument is not a Number. */ int getNumber(String name); /** * get remaining non-options args as Strings. * * @return * @throws IllegalArgumentException * if args are not Strings. */ List args(); /** * get remaining non-options args as Objects. * * @return */ List argObjects(); /** * print usage message to System.err. */ void usage(); /** * print specified usage error to System.err. You should explicitly throw the returned * exception. * * @param error * @return IllegalArgumentException */ IllegalArgumentException usageError(String error); } felix-gogo-shell-0.10.0/src/main/java/org/apache/felix/gogo/options/Options.java000066400000000000000000000433701165554710600274550ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.felix.gogo.options; import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Yet another GNU long options parser. This one is configured by parsing its Usage string. */ public class Options implements Option { public static void main(String[] args) { final String[] usage = { "test - test Options usage", " text before Usage: is displayed when usage() is called and no error has occurred.", " so can be used as a simple help message.", "", "Usage: testOptions [OPTION]... PATTERN [FILES]...", " Output control: arbitary non-option text can be included.", " -? --help show help", " -c --count=COUNT show COUNT lines", " -h --no-filename suppress the prefixing filename on output", " -q --quiet, --silent suppress all normal output", " --binary-files=TYPE assume that binary files are TYPE", " TYPE is 'binary', 'text', or 'without-match'", " -I equivalent to --binary-files=without-match", " -d --directories=ACTION how to handle directories (default=skip)", " ACTION is 'read', 'recurse', or 'skip'", " -D --devices=ACTION how to handle devices, FIFOs and sockets", " ACTION is 'read' or 'skip'", " -R, -r --recursive equivalent to --directories=recurse" }; Option opt = Options.compile(usage).parse(args); if (opt.isSet("help")) { opt.usage(); // includes text before Usage: return; } if (opt.args().size() == 0) throw opt.usageError("PATTERN not specified"); System.out.println(opt); if (opt.isSet("count")) System.out.println("count = " + opt.getNumber("count")); System.out.println("--directories specified: " + opt.isSet("directories")); System.out.println("directories=" + opt.get("directories")); } public static final String NL = System.getProperty("line.separator", "\n"); // Note: need to double \ within "" private static final String regex = "(?x)\\s*" + "(?:-([^-]))?" + // 1: short-opt-1 "(?:,?\\s*-(\\w))?" + // 2: short-opt-2 "(?:,?\\s*--(\\w[\\w-]*)(=\\w+)?)?" + // 3: long-opt-1 and 4:arg-1 "(?:,?\\s*--(\\w[\\w-]*))?" + // 5: long-opt-2 ".*?(?:\\(default=(.*)\\))?\\s*"; // 6: default private static final int GROUP_SHORT_OPT_1 = 1; private static final int GROUP_SHORT_OPT_2 = 2; private static final int GROUP_LONG_OPT_1 = 3; private static final int GROUP_ARG_1 = 4; private static final int GROUP_LONG_OPT_2 = 5; private static final int GROUP_DEFAULT = 6; private final Pattern parser = Pattern.compile(regex); private final Pattern uname = Pattern.compile("^Usage:\\s+(\\w+)"); private final Map unmodifiableOptSet; private final Map unmodifiableOptArg; private final Map optSet = new HashMap(); private final Map optArg = new HashMap(); private final Map optName = new HashMap(); private final Map optAlias = new HashMap(); private final List xargs = new ArrayList(); private List args = null; private static final String UNKNOWN = "unknown"; private String usageName = UNKNOWN; private int usageIndex = 0; private final String[] spec; private final String[] gspec; private final String defOpts; private final String[] defArgs; private PrintStream errStream = System.err; private String error = null; private boolean optionsFirst = false; private boolean stopOnBadOption = false; public static Option compile(String[] optSpec) { return new Options(optSpec, null, null); } public static Option compile(String optSpec) { return compile(optSpec.split("\\n")); } public static Option compile(String[] optSpec, Option gopt) { return new Options(optSpec, null, gopt); } public static Option compile(String[] optSpec, String[] gspec) { return new Options(optSpec, gspec, null); } public Option setStopOnBadOption(boolean stopOnBadOption) { this.stopOnBadOption = stopOnBadOption; return this; } public Option setOptionsFirst(boolean optionsFirst) { this.optionsFirst = optionsFirst; return this; } public boolean isSet(String name) { if (!optSet.containsKey(name)) throw new IllegalArgumentException("option not defined in spec: " + name); return optSet.get(name); } public Object getObject(String name) { if (!optArg.containsKey(name)) throw new IllegalArgumentException("option not defined with argument: " + name); List list = getObjectList(name); return list.isEmpty() ? "" : list.get(list.size() - 1); } @SuppressWarnings("unchecked") public List getObjectList(String name) { List list; Object arg = optArg.get(name); if ( arg == null ) { throw new IllegalArgumentException("option not defined with argument: " + name); } if (arg instanceof String) { // default value list = new ArrayList(); if (!"".equals(arg)) list.add(arg); } else { list = (List) arg; } return list; } public List getList(String name) { ArrayList list = new ArrayList(); for (Object o : getObjectList(name)) { try { list.add((String) o); } catch (ClassCastException e) { throw new IllegalArgumentException("option not String: " + name); } } return list; } @SuppressWarnings("unchecked") private void addArg(String name, Object value) { List list; Object arg = optArg.get(name); if (arg instanceof String) { // default value list = new ArrayList(); optArg.put(name, list); } else { list = (List) arg; } list.add(value); } public String get(String name) { try { return (String) getObject(name); } catch (ClassCastException e) { throw new IllegalArgumentException("option not String: " + name); } } public int getNumber(String name) { String number = get(name); try { if (number != null) return Integer.parseInt(number); return 0; } catch (NumberFormatException e) { throw new IllegalArgumentException("option '" + name + "' not Number: " + number); } } public List argObjects() { return xargs; } public List args() { if (args == null) { args = new ArrayList(); for (Object arg : xargs) { args.add(arg == null ? "null" : arg.toString()); } } return args; } public void usage() { StringBuilder buf = new StringBuilder(); int index = 0; if (error != null) { buf.append(error); buf.append(NL); index = usageIndex; } for (int i = index; i < spec.length; ++i) { buf.append(spec[i]); buf.append(NL); } String msg = buf.toString(); if (errStream != null) { errStream.print(msg); } } /** * prints usage message and returns IllegalArgumentException, for you to throw. */ public IllegalArgumentException usageError(String s) { error = usageName + ": " + s; usage(); return new IllegalArgumentException(error); } // internal constructor private Options(String[] spec, String[] gspec, Option opt) { this.gspec = gspec; Options gopt = (Options) opt; if (gspec == null && gopt == null) { this.spec = spec; } else { ArrayList list = new ArrayList(); list.addAll(Arrays.asList(spec)); list.addAll(Arrays.asList(gspec != null ? gspec : gopt.gspec)); this.spec = list.toArray(new String[0]); } Map myOptSet = new HashMap(); Map myOptArg = new HashMap(); parseSpec(myOptSet, myOptArg); if (gopt != null) { for (Entry e : gopt.optSet.entrySet()) { if (e.getValue()) myOptSet.put(e.getKey(), true); } for (Entry e : gopt.optArg.entrySet()) { if (!e.getValue().equals("")) myOptArg.put(e.getKey(), e.getValue()); } gopt.reset(); } unmodifiableOptSet = Collections.unmodifiableMap(myOptSet); unmodifiableOptArg = Collections.unmodifiableMap(myOptArg); defOpts = System.getenv(usageName.toUpperCase() + "_OPTS"); defArgs = (defOpts != null) ? defOpts.split("\\s+") : new String[0]; } /** * parse option spec. */ private void parseSpec(Map myOptSet, Map myOptArg) { int index = 0; for (String line : spec) { Matcher m = parser.matcher(line); if (m.matches()) { final String opt = m.group(GROUP_LONG_OPT_1); final String name = (opt != null) ? opt : m.group(GROUP_SHORT_OPT_1); if (name != null) { if (myOptSet.containsKey(name)) throw new IllegalArgumentException("duplicate option in spec: --" + name); myOptSet.put(name, false); } String dflt = (m.group(GROUP_DEFAULT) != null) ? m.group(GROUP_DEFAULT) : ""; if (m.group(GROUP_ARG_1) != null) myOptArg.put(opt, dflt); String opt2 = m.group(GROUP_LONG_OPT_2); if (opt2 != null) { optAlias.put(opt2, opt); myOptSet.put(opt2, false); if (m.group(GROUP_ARG_1) != null) myOptArg.put(opt2, ""); } for (int i = 0; i < 2; ++i) { String sopt = m.group(i == 0 ? GROUP_SHORT_OPT_1 : GROUP_SHORT_OPT_2); if (sopt != null) { if (optName.containsKey(sopt)) throw new IllegalArgumentException("duplicate option in spec: -" + sopt); optName.put(sopt, name); } } } if (usageName == UNKNOWN) { Matcher u = uname.matcher(line); if (u.find()) { usageName = u.group(1); usageIndex = index; } } index++; } } private void reset() { optSet.clear(); optSet.putAll(unmodifiableOptSet); optArg.clear(); optArg.putAll(unmodifiableOptArg); xargs.clear(); args = null; error = null; } public Option parse(Object[] argv) { return parse(argv, false); } public Option parse(List argv) { return parse(argv, false); } public Option parse(Object[] argv, boolean skipArg0) { if (null == argv) throw new IllegalArgumentException("argv is null"); return parse(Arrays.asList(argv), skipArg0); } public Option parse(List argv, boolean skipArg0) { reset(); List args = new ArrayList(); args.addAll(Arrays.asList(defArgs)); for (Object arg : argv) { if (skipArg0) { skipArg0 = false; usageName = arg.toString(); } else { args.add(arg); } } String needArg = null; String needOpt = null; boolean endOpt = false; for (Object oarg : args) { String arg = oarg == null ? "null" : oarg.toString(); if (endOpt) { xargs.add(oarg); } else if (needArg != null) { addArg(needArg, oarg); needArg = null; needOpt = null; } else if (!arg.startsWith("-") || "-".equals(oarg)) { if (optionsFirst) endOpt = true; xargs.add(oarg); } else { if (arg.equals("--")) endOpt = true; else if (arg.startsWith("--")) { int eq = arg.indexOf("="); String value = (eq == -1) ? null : arg.substring(eq + 1); String name = arg.substring(2, ((eq == -1) ? arg.length() : eq)); List names = new ArrayList(); if (optSet.containsKey(name)) { names.add(name); } else { for (String k : optSet.keySet()) { if (k.startsWith(name)) names.add(k); } } switch (names.size()) { case 1: name = names.get(0); optSet.put(name, true); if (optArg.containsKey(name)) { if (value != null) addArg(name, value); else needArg = name; } else if (value != null) { throw usageError("option '--" + name + "' doesn't allow an argument"); } break; case 0: if (stopOnBadOption) { endOpt = true; xargs.add(oarg); break; } else throw usageError("invalid option '--" + name + "'"); default: throw usageError("option '--" + name + "' is ambiguous: " + names); } } else { int i = 0; for (String c : arg.substring(1).split("")) { if (i++ == 0) continue; if (optName.containsKey(c)) { String name = optName.get(c); optSet.put(name, true); if (optArg.containsKey(name)) { if (i < arg.length()) { addArg(name, arg.substring(i)); } else { needOpt = c; needArg = name; } break; } } else { if (stopOnBadOption) { xargs.add("-" + c); endOpt = true; } else throw usageError("invalid option '" + c + "'"); } } } } } if (needArg != null) { String name = (needOpt != null) ? needOpt : "--" + needArg; throw usageError("option '" + name + "' requires an argument"); } // remove long option aliases for (Entry alias : optAlias.entrySet()) { if (optSet.get(alias.getKey())) { optSet.put(alias.getValue(), true); if (optArg.containsKey(alias.getKey())) optArg.put(alias.getValue(), optArg.get(alias.getKey())); } optSet.remove(alias.getKey()); optArg.remove(alias.getKey()); } return this; } @Override public String toString() { return "isSet" + optSet + "\nArg" + optArg + "\nargs" + xargs; } } felix-gogo-shell-0.10.0/src/main/java/org/apache/felix/gogo/shell/000077500000000000000000000000001165554710600245645ustar00rootroot00000000000000felix-gogo-shell-0.10.0/src/main/java/org/apache/felix/gogo/shell/Activator.java000066400000000000000000000122311165554710600273620ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.felix.gogo.shell; import java.util.Dictionary; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.Set; import org.apache.felix.service.command.CommandProcessor; import org.apache.felix.service.command.CommandSession; import org.apache.felix.service.command.Converter; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.util.tracker.ServiceTracker; public class Activator implements BundleActivator, Runnable { private BundleContext context; private ServiceTracker commandProcessorTracker; private Set regs = new HashSet(); private CommandSession session; private Shell shell; private Thread thread; public void start(final BundleContext ctxt) throws Exception { context = ctxt; commandProcessorTracker = processorTracker(); } public void stop(BundleContext context) throws Exception { if (thread != null) { thread.interrupt(); } commandProcessorTracker.close(); Iterator iterator = regs.iterator(); while (iterator.hasNext()) { ServiceRegistration reg = iterator.next(); reg.unregister(); iterator.remove(); } } public void run() { try { Thread.sleep(100); // wait for gosh command to be registered String args = context.getProperty("gosh.args"); args = (args == null) ? "" : args; session.execute("gosh --login " + args); } catch (Exception e) { Object loc = session.get(".location"); if (null == loc || !loc.toString().contains(":")) { loc = "gogo"; } System.err.println(loc + ": " + e.getClass().getSimpleName() + ": " + e.getMessage()); e.printStackTrace(); } finally { session.close(); } } private void startShell(BundleContext context, CommandProcessor processor) { Dictionary dict = new Hashtable(); dict.put(CommandProcessor.COMMAND_SCOPE, "gogo"); // register converters regs.add(context.registerService(Converter.class.getName(), new Converters(context), null)); // register commands dict.put(CommandProcessor.COMMAND_FUNCTION, Builtin.functions); regs.add(context.registerService(Builtin.class.getName(), new Builtin(), dict)); dict.put(CommandProcessor.COMMAND_FUNCTION, Procedural.functions); regs.add(context.registerService(Procedural.class.getName(), new Procedural(), dict)); dict.put(CommandProcessor.COMMAND_FUNCTION, Posix.functions); regs.add(context.registerService(Posix.class.getName(), new Posix(), dict)); dict.put(CommandProcessor.COMMAND_FUNCTION, Telnet.functions); regs.add(context.registerService(Telnet.class.getName(), new Telnet(processor), dict)); shell = new Shell(context, processor); dict.put(CommandProcessor.COMMAND_FUNCTION, Shell.functions); regs.add(context.registerService(Shell.class.getName(), shell, dict)); // start shell session = processor.createSession(System.in, System.out, System.err); thread = new Thread(this, "Gogo shell"); thread.start(); } private ServiceTracker processorTracker() { ServiceTracker t = new ServiceTracker(context, CommandProcessor.class.getName(), null) { @Override public Object addingService(ServiceReference reference) { CommandProcessor processor = (CommandProcessor) super.addingService(reference); startShell(context, processor); return processor; } @Override public void removedService(ServiceReference reference, Object service) { if (thread != null) { thread.interrupt(); } super.removedService(reference, service); } }; t.open(); return t; } }felix-gogo-shell-0.10.0/src/main/java/org/apache/felix/gogo/shell/Builtin.java000066400000000000000000000424531165554710600270450ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.felix.gogo.shell; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.StringWriter; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.Map.Entry; import org.apache.felix.gogo.options.Option; import org.apache.felix.gogo.options.Options; import org.apache.felix.service.command.CommandSession; import org.apache.felix.service.command.Converter; /** * gosh built-in commands. */ public class Builtin { static final String[] functions = { "format", "getopt", "new", "set", "tac", "type" }; private static final String[] packages = { "java.lang", "java.io", "java.net", "java.util" }; public CharSequence format(CommandSession session) { return format(session, session.get("_")); // last result } public CharSequence format(CommandSession session, Object arg) { CharSequence result = session.format(arg, Converter.INSPECT); System.out.println(result); return result; } /** * script access to Options. */ public Option getopt(List spec, Object[] args) { String[] optSpec = new String[spec.size()]; for (int i = 0; i < optSpec.length; ++i) { optSpec[i] = spec.get(i).toString(); } return Options.compile(optSpec).parse(args); } // FIXME: the "new" command should be provided by runtime, // so it can leverage same argument coercion mechanism, used to invoke methods. public Object _new(Object name, Object[] argv) throws Exception { Class clazz = null; if (name instanceof Class) { clazz = (Class) name; } else { clazz = loadClass(name.toString()); } for (Constructor c : clazz.getConstructors()) { Class[] types = c.getParameterTypes(); if (types.length != argv.length) { continue; } boolean match = true; for (int i = 0; i < argv.length; ++i) { if (!types[i].isAssignableFrom(argv[i].getClass())) { if (!types[i].isAssignableFrom(String.class)) { match = false; break; } argv[i] = argv[i].toString(); } } if (!match) { continue; } try { return c.newInstance(argv); } catch (InvocationTargetException ite) { Throwable cause = ite.getCause(); if (cause instanceof Exception) { throw (Exception) cause; } throw ite; } } throw new IllegalArgumentException("can't coerce " + Arrays.asList(argv) + " to any of " + Arrays.asList(clazz.getConstructors())); } private Class loadClass(String name) throws ClassNotFoundException { if (!name.contains(".")) { for (String p : packages) { String pkg = p + "." + name; try { return Class.forName(pkg); } catch (ClassNotFoundException e) { } } } return Class.forName(name); } public void set(CommandSession session, String[] argv) throws Exception { final String[] usage = { "set - show session variables", "Usage: set [OPTIONS] [PREFIX]", " -? --help show help", " -a --all show all variables, including those starting with .", " -x set xtrace option", " +x unset xtrace option", "If PREFIX given, then only show variable(s) starting with PREFIX" }; Option opt = Options.compile(usage).parse(argv); if (opt.isSet("help")) { opt.usage(); return; } List args = opt.args(); String prefix = (args.isEmpty() ? "" : args.get(0)); if (opt.isSet("x")) { session.put("echo", true); } else if ("+x".equals(prefix)) { session.put("echo", null); } else { boolean all = opt.isSet("all"); for (String key : new TreeSet(Shell.getVariables(session))) { if (!key.startsWith(prefix)) continue; if (key.startsWith(".") && !(all || prefix.length() > 0)) continue; Object target = session.get(key); String type = null; String value = null; if (target != null) { Class clazz = target.getClass(); type = clazz.getSimpleName(); value = target.toString(); } String trunc = value == null || value.length() < 55 ? "" : "..."; System.out.println(String.format("%-15.15s %-15s %.45s%s", type, key, value, trunc)); } } } public Object tac(CommandSession session, String[] argv) throws IOException { final String[] usage = { "tac - capture stdin as String or List and optionally write to file.", "Usage: tac [-al] [FILE]", " -a --append append to FILE", " -l --list return List", " -? --help show help" }; Option opt = Options.compile(usage).parse(argv); if (opt.isSet("help")) { opt.usage(); return null; } List args = opt.args(); BufferedWriter fw = null; if (args.size() == 1) { String path = args.get(0); File file = new File(Shell.cwd(session).resolve(path)); fw = new BufferedWriter(new FileWriter(file, opt.isSet("append"))); } StringWriter sw = new StringWriter(); BufferedReader rdr = new BufferedReader(new InputStreamReader(System.in)); ArrayList list = null; if (opt.isSet("list")) { list = new ArrayList(); } boolean first = true; String s; while ((s = rdr.readLine()) != null) { if (list != null) { list.add(s); } else { if (!first) { sw.write(' '); } first = false; sw.write(s); } if (fw != null) { fw.write(s); fw.newLine(); } } if (fw != null) { fw.close(); } return list != null ? list : sw.toString(); } // FIXME: expose API in runtime so type command doesn't have to duplicate the runtime // command search strategy. public boolean type(CommandSession session, String[] argv) throws Exception { final String[] usage = { "type - show command type", "Usage: type [OPTIONS] [name[:]]", " -a --all show all matches", " -? --help show help", " -q --quiet don't print anything, just return status", " -s --scope=NAME list all commands in named scope", " -t --types show full java type names" }; Option opt = Options.compile(usage).parse(argv); List args = opt.args(); if (opt.isSet("help")) { opt.usage(); return true; } boolean all = opt.isSet("all"); String optScope = null; if (opt.isSet("scope")) { optScope = opt.get("scope"); } if (args.size() == 1) { String arg = args.get(0); if (arg.endsWith(":")) { optScope = args.remove(0); } } if (optScope != null || (args.isEmpty() && all)) { Set snames = new TreeSet(); for (String sname : (getCommands(session))) { if ((optScope == null) || sname.startsWith(optScope)) { snames.add(sname); } } for (String sname : snames) { System.out.println(sname); } return true; } if (args.size() == 0) { Map scopes = new TreeMap(); for (String sname : getCommands(session)) { int colon = sname.indexOf(':'); String scope = sname.substring(0, colon); Integer count = scopes.get(scope); if (count == null) { count = 0; } scopes.put(scope, ++count); } for (Entry entry : scopes.entrySet()) { System.out.println(entry.getKey() + ":" + entry.getValue()); } return true; } final String name = args.get(0).toLowerCase(); final int colon = name.indexOf(':'); final String MAIN = "_main"; // FIXME: must match Reflective.java StringBuilder buf = new StringBuilder(); Set cmds = new LinkedHashSet(); // get all commands if ((colon != -1) || (session.get(name) != null)) { cmds.add(name); } else if (session.get(MAIN) != null) { cmds.add(MAIN); } else { String path = session.get("SCOPE") != null ? session.get("SCOPE").toString() : "*"; for (String s : path.split(":")) { if (s.equals("*")) { for (String sname : getCommands(session)) { if (sname.endsWith(":" + name)) { cmds.add(sname); if (!all) { break; } } } } else { String sname = s + ":" + name; if (session.get(sname) != null) { cmds.add(sname); if (!all) { break; } } } } } for (String key : cmds) { Object target = session.get(key); if (target == null) { continue; } CharSequence source = getClosureSource(session, key); if (source != null) { buf.append(name); buf.append(" is function {"); buf.append(source); buf.append("}"); continue; } for (Method m : getMethods(session, key)) { StringBuilder params = new StringBuilder(); for (Class type : m.getParameterTypes()) { if (params.length() > 0) { params.append(", "); } params.append(type.getSimpleName()); } String rtype = m.getReturnType().getSimpleName(); if (buf.length() > 0) { buf.append("\n"); } if (opt.isSet("types")) { String cname = m.getDeclaringClass().getName(); buf.append(String.format("%s %s.%s(%s)", rtype, cname, m.getName(), params)); } else { buf.append(String.format("%s is %s %s(%s)", name, rtype, key, params)); } } } if (buf.length() > 0) { if (!opt.isSet("quiet")) { System.out.println(buf); } return true; } if (!opt.isSet("quiet")) { System.err.println("type: " + name + " not found."); } return false; } /* * the following methods depend on the internals of the runtime implementation. * ideally, they should be available via some API. */ @SuppressWarnings("unchecked") static Set getCommands(CommandSession session) { return (Set) session.get(".commands"); } private boolean isClosure(Object target) { return target.getClass().getSimpleName().equals("Closure"); } private boolean isCommand(Object target) { return target.getClass().getSimpleName().equals("CommandProxy"); } private CharSequence getClosureSource(CommandSession session, String name) throws Exception { Object target = session.get(name); if (target == null) { return null; } if (!isClosure(target)) { return null; } Field sourceField = target.getClass().getDeclaredField("source"); sourceField.setAccessible(true); return (CharSequence) sourceField.get(target); } private List getMethods(CommandSession session, String scmd) throws Exception { final int colon = scmd.indexOf(':'); final String function = colon == -1 ? scmd : scmd.substring(colon + 1); final String name = KEYWORDS.contains(function) ? ("_" + function) : function; final String get = "get" + function; final String is = "is" + function; final String set = "set" + function; final String MAIN = "_main"; // FIXME: must match Reflective.java Object target = session.get(scmd); if (target == null) { return null; } if (isClosure(target)) { return null; } if (isCommand(target)) { Method method = target.getClass().getMethod("getTarget", (Class[])null); method.setAccessible(true); target = method.invoke(target, (Object[])null); } ArrayList list = new ArrayList(); Class tc = (target instanceof Class) ? (Class) target : target.getClass(); Method[] methods = tc.getMethods(); for (Method m : methods) { String mname = m.getName().toLowerCase(); if (mname.equals(name) || mname.equals(get) || mname.equals(set) || mname.equals(is) || mname.equals(MAIN)) { list.add(m); } } return list; } private final static Set KEYWORDS = new HashSet( Arrays.asList(new String[] { "abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package", "synchronized", "boolean", "do", "if", "private", "this", "break", "double", "implements", "protected", "throw", "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", "finally", "long", "strictfp", "volatile", "const", "float", "native", "super", "while" })); } felix-gogo-shell-0.10.0/src/main/java/org/apache/felix/gogo/shell/Console.java000066400000000000000000000111621165554710600270320ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.felix.gogo.shell; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import org.apache.felix.service.command.CommandSession; import org.apache.felix.service.command.Converter; public class Console implements Runnable { private final CommandSession session; private final InputStream in; private final PrintStream out; private boolean quit; public Console(CommandSession session) { this.session = session; in = session.getKeyboard(); out = session.getConsole(); } public void run() { try { while (!quit) { Object prompt = session.get("prompt"); if (prompt == null) { prompt = "g! "; } CharSequence line = getLine(prompt.toString()); if (line == null) { break; } try { Object result = session.execute(line); session.put("_", result); // set $_ to last result if (result != null && !Boolean.FALSE.equals(session.get(".Gogo.format"))) { out.println(session.format(result, Converter.INSPECT)); } } catch (Throwable e) { final String SESSION_CLOSED = "session is closed"; if ((e instanceof IllegalStateException) && SESSION_CLOSED.equals(e.getMessage())) { // FIXME: we assume IllegalStateException is because the session is closed; // but it may be for another reason, so we also check the message (yuk). // It would be better if the RFC-147 API threw a unique exception, such as // org.osgi.service.command.SessionClosedException out.println("gosh: " + e); quit = true; } if (!quit) { session.put("exception", e); Object loc = session.get(".location"); if (null == loc || !loc.toString().contains(":")) { loc = "gogo"; } out.println(loc + ": " + e.getClass().getSimpleName() + ": " + e.getMessage()); } } } } catch (Exception e) { if (!quit) { e.printStackTrace(); } } } private CharSequence getLine(String prompt) throws IOException { StringBuilder sb = new StringBuilder(); out.print(prompt); while (!quit) { out.flush(); int c = in.read(); switch (c) { case -1: case 4: // EOT, ^D from telnet quit = true; break; case '\r': break; case '\n': if (sb.length() > 0) { return sb; } out.print(prompt); break; case '\b': if (sb.length() > 0) { out.print("\b \b"); sb.deleteCharAt(sb.length() - 1); } break; default: sb.append((char) c); break; } } return null; } } felix-gogo-shell-0.10.0/src/main/java/org/apache/felix/gogo/shell/Converters.java000066400000000000000000000200131165554710600275550ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.felix.gogo.shell; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.Formatter; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.apache.felix.service.command.Converter; import org.apache.felix.service.command.Function; import org.osgi.service.startlevel.StartLevel; public class Converters implements Converter { private final BundleContext context; public Converters(BundleContext context) { this.context = context; } private CharSequence print(Bundle bundle) { // [ ID ] [STATE ] [ SL ] symname StartLevel sl = null; ServiceReference ref = context.getServiceReference(StartLevel.class.getName()); if (ref != null) { sl = (StartLevel) context.getService(ref); } if (sl == null) { return String.format("%5d|%-11s|%s (%s)", bundle.getBundleId(), getState(bundle), bundle.getSymbolicName(), bundle.getVersion()); } int level = sl.getBundleStartLevel(bundle); context.ungetService(ref); return String.format("%5d|%-11s|%5d|%s (%s)", bundle.getBundleId(), getState(bundle), level, bundle.getSymbolicName(), bundle.getVersion()); } private CharSequence print(ServiceReference ref) { StringBuilder sb = new StringBuilder(); Formatter f = new Formatter(sb); String spid = ""; Object pid = ref.getProperty("service.pid"); if (pid != null) { spid = pid.toString(); } f.format("%06d %3s %-40s %s", ref.getProperty("service.id"), ref.getBundle().getBundleId(), getShortNames((String[]) ref.getProperty("objectclass")), spid); return sb; } private CharSequence getShortNames(String[] list) { StringBuilder sb = new StringBuilder(); String del = ""; for (String s : list) { sb.append(del + getShortName(s)); del = " | "; } return sb; } private CharSequence getShortName(String name) { int n = name.lastIndexOf('.'); if (n < 0) { n = 0; } else { n++; } return name.subSequence(n, name.length()); } private String getState(Bundle bundle) { switch (bundle.getState()) { case Bundle.ACTIVE: return "Active"; case Bundle.INSTALLED: return "Installed"; case Bundle.RESOLVED: return "Resolved"; case Bundle.STARTING: return "Starting"; case Bundle.STOPPING: return "Stopping"; case Bundle.UNINSTALLED: return "Uninstalled "; } return null; } public Bundle bundle(Bundle i) { return i; } public Object convert(Class desiredType, final Object in) throws Exception { if (desiredType == Bundle.class) { return convertBundle(in); } if (desiredType == ServiceReference.class) { return convertServiceReference(in); } if (desiredType == Class.class) { try { return Class.forName(in.toString()); } catch (ClassNotFoundException e) { return null; } } if (desiredType.isAssignableFrom(String.class) && in instanceof InputStream) { return read(((InputStream) in)); } if (in instanceof Function && desiredType.isInterface() && desiredType.getDeclaredMethods().length == 1) { return Proxy.newProxyInstance(desiredType.getClassLoader(), new Class[] { desiredType }, new InvocationHandler() { Function command = ((Function) in); public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return command.execute(null, Arrays.asList(args)); } }); } return null; } private Object convertServiceReference(Object in) throws InvalidSyntaxException { String s = in.toString(); if (s.startsWith("(") && s.endsWith(")")) { ServiceReference refs[] = context.getServiceReferences(null, String.format( "(|(service.id=%s)(service.pid=%s))", in, in)); if (refs != null && refs.length > 0) { return refs[0]; } } ServiceReference refs[] = context.getServiceReferences(null, String.format( "(|(service.id=%s)(service.pid=%s))", in, in)); if (refs != null && refs.length > 0) { return refs[0]; } return null; } private Object convertBundle(Object in) { String s = in.toString(); try { long id = Long.parseLong(s); return context.getBundle(id); } catch (NumberFormatException nfe) { // Ignore } Bundle bundles[] = context.getBundles(); for (Bundle b : bundles) { if (b.getLocation().equals(s)) { return b; } if (b.getSymbolicName().equals(s)) { return b; } } return null; } public CharSequence format(Object target, int level, Converter converter) throws IOException { if (level == INSPECT && target instanceof InputStream) { return read(((InputStream) target)); } if (level == LINE && target instanceof Bundle) { return print((Bundle) target); } if (level == LINE && target instanceof ServiceReference) { return print((ServiceReference) target); } if (level == PART && target instanceof Bundle) { return ((Bundle) target).getSymbolicName(); } if (level == PART && target instanceof ServiceReference) { return getShortNames((String[]) ((ServiceReference) target).getProperty("objectclass")); } return null; } private CharSequence read(InputStream in) throws IOException { int c; StringBuffer sb = new StringBuffer(); while ((c = in.read()) > 0) { if (c >= 32 && c <= 0x7F || c == '\n' || c == '\r') { sb.append((char) c); } else { String s = Integer.toHexString(c).toUpperCase(); sb.append("\\"); if (s.length() < 1) { sb.append(0); } sb.append(s); } } return sb; } } felix-gogo-shell-0.10.0/src/main/java/org/apache/felix/gogo/shell/Posix.java000066400000000000000000000130271165554710600265340ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.felix.gogo.shell; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.URI; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.felix.gogo.options.Option; import org.apache.felix.gogo.options.Options; import org.apache.felix.service.command.CommandSession; /** * Posix-like utilities. * * @see http://www.opengroup.org/onlinepubs/009695399/utilities/contents.html */ public class Posix { static final String[] functions = { "cat", "echo", "grep" }; public void cat(CommandSession session, String[] args) throws Exception { if (args.length == 0) { copy(System.in, System.out); return; } URI cwd = Shell.cwd(session); for (String arg : args) { copy(cwd.resolve(arg), System.out); } } public void echo(Object[] args) { StringBuilder buf = new StringBuilder(); if (args == null) { System.out.println("Null"); return; } for (Object arg : args) { if (buf.length() > 0) buf.append(' '); buf.append(String.valueOf(arg)); } System.out.println(buf); } public boolean grep(CommandSession session, String[] argv) throws IOException { final String[] usage = { "grep - search for PATTERN in each FILE or standard input.", "Usage: grep [OPTIONS] PATTERN [FILES]", " -? --help show help", " -i --ignore-case ignore case distinctions", " -n --line-number prefix each line with line number within its input file", " -q --quiet, --silent suppress all normal output", " -v --invert-match select non-matching lines" }; Option opt = Options.compile(usage).parse(argv); if (opt.isSet("help")) { opt.usage(); return true; } List args = opt.args(); if (args.size() == 0) { throw opt.usageError("no pattern supplied."); } String regex = args.remove(0); if (opt.isSet("ignore-case")) { regex = "(?i)" + regex; } if (args.isEmpty()) { args.add(null); } StringBuilder buf = new StringBuilder(); if (args.size() > 1) { buf.append("%1$s:"); } if (opt.isSet("line-number")) { buf.append("%2$s:"); } buf.append("%3$s"); String format = buf.toString(); Pattern pattern = Pattern.compile(regex); boolean status = true; boolean match = false; for (String arg : args) { InputStream in = null; try { URI cwd = Shell.cwd(session); in = (arg == null) ? System.in : cwd.resolve(arg).toURL().openStream(); BufferedReader rdr = new BufferedReader(new InputStreamReader(in)); int line = 0; String s; while ((s = rdr.readLine()) != null) { line++; Matcher matcher = pattern.matcher(s); if (!(matcher.find() ^ !opt.isSet("invert-match"))) { match = true; if (opt.isSet("quiet")) break; System.out.println(String.format(format, arg, line, s)); } } if (match && opt.isSet("quiet")) { break; } } catch (IOException e) { System.err.println("grep: " + e.getMessage()); status = false; } finally { if (arg != null && in != null) { in.close(); } } } return match && status; } public static void copy(URI source, OutputStream out) throws IOException { InputStream in = source.toURL().openStream(); try { copy(in, out); } finally { in.close(); } } public static void copy(InputStream in, OutputStream out) throws IOException { byte buf[] = new byte[10240]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } out.flush(); } } felix-gogo-shell-0.10.0/src/main/java/org/apache/felix/gogo/shell/Procedural.java000066400000000000000000000113641165554710600275340ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.felix.gogo.shell; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apache.felix.service.command.CommandSession; import org.apache.felix.service.command.Function; public class Procedural { static final String[] functions = { "each", "if", "not", "throw", "try", "until", "while" }; public List each(CommandSession session, Collection list, Function closure) throws Exception { List args = new ArrayList(); List results = new ArrayList(); args.add(null); for (Object x : list) { checkInterrupt(); args.set(0, x); results.add(closure.execute(session, args)); } return results; } public Object _if(CommandSession session, Function[] fns) throws Exception { int length = fns.length; if (length < 2) { throw new IllegalArgumentException( "Usage: if {condition} {if-action} ... {else-action}"); } for (int i = 0; i < length; ++i) { if (i == length - 1 || isTrue(fns[i++].execute(session, null))) { return fns[i].execute(session, null); } } return null; } public boolean not(CommandSession session, Function condition) throws Exception { if (null == condition) { return true; } return !isTrue(condition.execute(session, null)); } // Reflective.coerce() prefers to construct a new Throwable(String) // than to call this method directly. public void _throw(String message) { throw new IllegalArgumentException(message); } public void _throw(Exception e) throws Exception { throw e; } public void _throw(CommandSession session) throws Throwable { Object exception = session.get("exception"); if (exception instanceof Throwable) throw (Throwable) exception; else throw new IllegalArgumentException("exception not set or not Throwable."); } public Object _try(CommandSession session, Function func) throws Exception { try { return func.execute(session, null); } catch (Exception e) { session.put("exception", e); return null; } } public Object _try(CommandSession session, Function func, Function error) throws Exception { try { return func.execute(session, null); } catch (Exception e) { session.put("exception", e); return error.execute(session, null); } } public void _while(CommandSession session, Function condition, Function ifTrue) throws Exception { while (isTrue(condition.execute(session, null))) { ifTrue.execute(session, null); } } public void until(CommandSession session, Function condition, Function ifTrue) throws Exception { while (!isTrue(condition.execute(session, null))) { ifTrue.execute(session, null); } } private boolean isTrue(Object result) throws InterruptedException { checkInterrupt(); if (result == null) return false; if (result instanceof Boolean) return ((Boolean) result).booleanValue(); if (result instanceof Number) { if (0 == ((Number) result).intValue()) return false; } if ("".equals(result)) return false; if ("0".equals(result)) return false; return true; } private void checkInterrupt() throws InterruptedException { if (Thread.currentThread().isInterrupted()) throw new InterruptedException("loop interrupted"); } } felix-gogo-shell-0.10.0/src/main/java/org/apache/felix/gogo/shell/Shell.java000066400000000000000000000166021165554710600265030ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.felix.gogo.shell; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.net.URI; import java.net.URLConnection; import java.nio.CharBuffer; import java.util.List; import java.util.Set; import org.apache.felix.gogo.options.Option; import org.apache.felix.gogo.options.Options; import org.apache.felix.service.command.CommandProcessor; import org.apache.felix.service.command.CommandSession; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; public class Shell { static final String[] functions = { "gosh", "sh", "source" }; private final static URI CWD = new File(".").toURI(); private final URI baseURI; private final BundleContext context; private final CommandProcessor processor; public Shell(BundleContext context, CommandProcessor processor) { this.context = context; this.processor = processor; String baseDir = context.getProperty("gosh.home"); baseDir = (baseDir == null) ? context.getProperty("user.dir") : baseDir; baseURI = new File(baseDir).toURI(); } public Object gosh(final CommandSession session, String[] argv) throws Exception { final String[] usage = { "gosh - execute script with arguments in a new session", " args are available as session variables $1..$9 and $args.", "Usage: gosh [OPTIONS] [script-file [args..]]", " -c --command pass all remaining args to sub-shell", " --nointeractive don't start interactive session", " --login login shell (same session, reads etc/gosh_profile)", " -s --noshutdown don't shutdown framework when script completes", " -x --xtrace echo commands before execution", " -? --help show help", "If no script-file, an interactive shell is started, type $D to exit." }; Option opt = Options.compile(usage).setOptionsFirst(true).parse(argv); List args = opt.args(); boolean login = opt.isSet("login"); boolean interactive = !opt.isSet("nointeractive"); if (opt.isSet("help")) { opt.usage(); if (login && !opt.isSet("noshutdown")) { shutdown(); } return null; } if (opt.isSet("command") && args.isEmpty()) { throw opt.usageError("option --command requires argument(s)"); } CommandSession newSession = (login ? session : processor.createSession( session.getKeyboard(), session.getConsole(), System.err)); if (opt.isSet("xtrace")) { newSession.put("echo", true); } if (login && interactive) { URI uri = baseURI.resolve("etc/gosh_profile"); if (!new File(uri).exists()) { uri = getClass().getResource("/gosh_profile").toURI(); } if (uri != null) { source(session, uri.toString()); } } // export variables starting with upper-case to newSession for (String key : getVariables(session)) { if (key.matches("[.]?[A-Z].*")) { newSession.put(key, session.get(key)); } } Object result = null; if (args.isEmpty()) { if (interactive) { result = console(newSession); } } else { CharSequence program; if (opt.isSet("command")) { StringBuilder buf = new StringBuilder(); for (String arg : args) { if (buf.length() > 0) { buf.append(' '); } buf.append(arg); } program = buf; } else { URI script = cwd(session).resolve(args.remove(0)); // set script arguments newSession.put("0", script); newSession.put("args", args); for (int i = 0; i < args.size(); ++i) { newSession.put(String.valueOf(i + 1), args.get(i)); } program = readScript(script); } result = newSession.execute(program); } if (login && interactive && !opt.isSet("noshutdown")) { System.out.println("gosh: stopping framework"); shutdown(); } return result; } public Object sh(final CommandSession session, String[] argv) throws Exception { return gosh(session, argv); } private void shutdown() throws BundleException { context.getBundle(0).stop(); } public Object source(CommandSession session, String script) throws Exception { URI uri = cwd(session).resolve(script); session.put("0", uri); try { return session.execute(readScript(uri)); } finally { session.put("0", null); // API doesn't support remove } } private Object console(CommandSession session) { Console console = new Console(session); console.run(); return null; } private CharSequence readScript(URI script) throws Exception { URLConnection conn = script.toURL().openConnection(); int length = conn.getContentLength(); if (length == -1) { System.err.println("eek! unknown Contentlength for: " + script); length = 10240; } InputStream in = conn.getInputStream(); CharBuffer cbuf = CharBuffer.allocate(length); Reader reader = new InputStreamReader(in); reader.read(cbuf); in.close(); cbuf.rewind(); return cbuf; } @SuppressWarnings("unchecked") static Set getVariables(CommandSession session) { return (Set) session.get(".variables"); } static URI cwd(CommandSession session) { Object cwd = session.get("_cwd"); // _cwd is set by felixcommands:cd if (cwd instanceof URI) { return (URI) cwd; } else if (cwd instanceof File) { return ((File) cwd).toURI(); } else { return CWD; } } } felix-gogo-shell-0.10.0/src/main/java/org/apache/felix/gogo/shell/Telnet.java000066400000000000000000000124761165554710600266740ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.felix.gogo.shell; import java.io.IOException; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.net.InetAddress; import java.util.List; import org.apache.felix.gogo.options.Option; import org.apache.felix.gogo.options.Options; import org.apache.felix.service.command.CommandProcessor; import org.apache.felix.service.command.CommandSession; /* * a very simple Telnet server. * real remote access should be via ssh. */ public class Telnet implements Runnable { static final String[] functions = { "telnetd" }; private static final int defaultPort = 2019; private final CommandProcessor processor; private ServerSocket server; private Thread thread; private boolean quit; private int port; private String ip; public Telnet(CommandProcessor procesor) { this.processor = procesor; } public void telnetd(String[] argv) throws IOException { final String[] usage = { "telnetd - start simple telnet server", "Usage: telnetd [-i ip] [-p port] start | stop | status", " -i --ip=INTERFACE listen interface (default=127.0.0.1)", " -p --port=PORT listen port (default=" + defaultPort + ")", " -? --help show help" }; Option opt = Options.compile(usage).parse(argv); List args = opt.args(); if (opt.isSet("help") || args.isEmpty()) { opt.usage(); return; } String command = args.get(0); if ("start".equals(command)) { if (server != null) { throw new IllegalStateException("telnetd is already running on port " + port); } ip = opt.get("ip"); port = opt.getNumber("port"); start(); status(); } else if ("stop".equals(command)) { if (server == null) { throw new IllegalStateException("telnetd is not running."); } stop(); } else if ("status".equals(command)) { status(); } else { throw opt.usageError("bad command: " + command); } } private void status() { if (server != null) { System.out.println("telnetd is running on " + ip + ":" + port); } else { System.out.println("telnetd is not running."); } } private void start() throws IOException { quit = false; server = new ServerSocket(port, 0, InetAddress.getByName(ip)); thread = new Thread(this, "gogo telnet"); thread.start(); } private void stop() throws IOException { quit = true; server.close(); server = null; thread.interrupt(); } public void run() { try { while (!quit) { final Socket socket = server.accept(); PrintStream out = new PrintStream(socket.getOutputStream()); final CommandSession session = processor.createSession( socket.getInputStream(), out, out); Thread handler = new Thread() { public void run() { try { session.execute("gosh --login --noshutdown"); } catch (Exception e) { e.printStackTrace(); } finally { session.close(); try { socket.close(); } catch (IOException e) { } } } }; handler.start(); } } catch (IOException e) { if (!quit) { e.printStackTrace(); } } finally { try { if (server != null) { server.close(); } } catch (IOException e) { } } } } felix-gogo-shell-0.10.0/src/main/resources/000077500000000000000000000000001165554710600204745ustar00rootroot00000000000000felix-gogo-shell-0.10.0/src/main/resources/gosh_profile000066400000000000000000000021601165554710600230760ustar00rootroot00000000000000# default gosh_profile # only read if etc/gosh_profile doesn't exist relative to the System property # gosh.home or failing that the current directory. # catch all exceptions from this script to avoid it aborting startup try { # ensure gogo commands are found first SCOPE = gogo:* # add methods on BundleContext object as commands #addcommand context ${.context} (${.context} class) # bug: above invokes (String, Object, String) instead of (String, Object, Class) addcommand context ${.context} # add methods on System object as commands addcommand system (((${.context} bundles) 0) loadclass java.lang.System) # alias to print full stack trace e = { $exception printStackTrace } ## disable console auto-formatting of each result # you will then need to explicitly use the 'format' command # to print the result of commands that don't write to stdout. #.Gogo.format = false ## disable printing the formatted result of a command into pipelines #.Format.Pipe = false # set prompt prompt = 'g! ' # print welcome message cat ($0 resolve motd) } { echo "$0: ERROR: $exception" } # end felix-gogo-shell-0.10.0/src/main/resources/motd000066400000000000000000000000761165554710600213650ustar00rootroot00000000000000____________________________ Welcome to Apache Felix Gogo