All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.jxta.impl.shell.ShellCmds Maven / Gradle / Ivy

Go to download

The JXTA Shell is a sample application that demonstrates key concepts of JXTA JXSE. The JXTA Shell enables users to interact with the JXTA platform through a command-line interpreter. Much like the UNIX® shell, the JXTA Shell is useful for accessing and managing core platform objects (peers, groups, pipes), debugging communications problems, checking the status of peers and/or peer groups, and communicating with other JXTA services and applications. As in UNIX®, the JXTA shell allows users to "pipe" shell commands together connecting commands "on-the-fly." Pipes in Project JXTA are useful for collecting information at one peer and perhaps processing the command at another.

The newest version!
/*
 * Copyright (c) 2001 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *       Sun Microsystems, Inc. for Project JXTA."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact Project JXTA at http://www.jxta.org.
 *
 * 5. Products derived from this software may not be called "JXTA",
 *    nor may "JXTA" appear in their name, without prior written
 *    permission of Sun.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL SUN MICROSYSTEMS OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of Project JXTA.  For more
 * information on Project JXTA, please see
 * .
 *
 * This license is based on the BSD license adopted by the Apache Foundation.
 *
 * $Id: ShellCmds.java,v 1.23 2007/05/23 22:37:54 bondolo Exp $
 */


package net.jxta.impl.shell;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.*;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.logging.Level;

/**
 * This  class has methods for getting an array of all available Shell commands
 * and for instantiating of a specific Shell command (the standard constructor is used!).
 * It uses a ClassLoader that can load class-files from an arbitrary number of jar-files.
 * The list of jar-files is encoded in the INST_JARS environment variable of the ShellApp
 * that instantiated this class.
 * The encoded String has following format:
 * ...
 * 

* Whenever a ShellApp needs access to the Shell commands this class should be used. * For example to get all available Shell commands use the following code: * * ShellCmds cmds = new ShellCmds((ShellApp)this); * String[] cmdList = cmds.list(); * * To instantiate a command you could use following code: * * // Instantiate the 'man' command. * ShellApp app = cmds.getInstance("man"); * // Now set the group and the input and output pipes if neccessary. * ... * // For example we want to print the short description of the app. * println(app.getDescription()); * */ public final class ShellCmds { /** * For debugging purposes. */ private static final java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(ShellCmds.class.getName()); /** * Name of environment variable. */ public static final String INST_JARS = "instjars"; /** * Char used to separate paths. */ public static final String PATH_SEPARATOR = System.getProperty("path.separator"); static final String BIN_PACKAGE = "net.jxta.impl.shell.bin"; static final String BIN_PATH = "net/jxta/impl/shell/bin/"; static final int BIN_PATH_LEN = BIN_PATH.length(); /** * Reference to the ShellApp that instantiated this class. */ private final ShellEnv env; /** * Initializes a newly created ShellCmds object with a reference to the instantiating ShellApp. * This reference will be used to obtain its current ShellEnv object which serves for reading * and storing the INST_JARS environment variable. * * @param env the environment to use. */ public ShellCmds(ShellEnv env) { this.env = env; } /** * Static method to extract the list of paths out of a String. The format of the String is: * ... * Only correct paths are added to the later returned list. * * @param pathList the String the paths will be extracted from. * @return an array of all valid paths. If the given parameter contains no path or none * of the given paths is valid then an empty list is returned. */ public static URL[] parseClassPath(String pathList) { List pathURLS = new ArrayList(); StringTokenizer tok = new StringTokenizer(pathList, PATH_SEPARATOR, false); while (tok.hasMoreTokens()) { String fileName = tok.nextToken(); File file = new File(fileName); try { pathURLS.add(file.toURI().toURL()); } catch (MalformedURLException bad) { //ignored } } return pathURLS.toArray(new URL[pathURLS.size()]); } /** * Static method to encode a list of paths into its corresponding String representation. * The format of the String is: ... * * @param pathList the list of paths to be encoded. * @return a String representation of the given list. */ public static String encodeInstJars(List pathList) { StringBuilder buf = new StringBuilder(); for (int i = 0, size = pathList.size(); i < size; i++) { buf.append(pathList.get(i)); if (i < size - 1) buf.append(PATH_SEPARATOR); } return buf.toString(); } /** * Stores the String representation of the given list of paths in the environment * of the ShellApp. * * @param pathList list of paths to be stored in the environment of the ShellApp. */ public void setInstJars(List pathList) { // Convert list into its corresponding String representation, String instJars = encodeInstJars(pathList); // and set the new value of environment variable INST_JARS. env.add(INST_JARS, new ShellObject("Installed Jar Files", instJars)); } /** * Retrieves the list of paths encoded as a String from the ShellApp's environment. * * @return a list of path objects. */ public URL[] getInstJars() { if (env.contains(INST_JARS)) { // If environment variable INST_JARS already exists, then // get environment variable INST_JARS, and // extract zip-files and directories and construct a list containing them. String instJars = (String) env.get(INST_JARS).getObject(); return parseClassPath(instJars); } else { // else return an empty list. return new URL[0]; } } /** * Returns an array of all available Shell commands. *

*

The current implementation tries to locate commands on the classpath * pf the classloader * * @return an array of the names of all the available shell commands. */ public String[] list() { List list = cmdlist(); return list.toArray(new String[list.size()]); } /** * Returns a list of all available Shell commands. *

*

The current implementation tries to locate commands on the classpath * pf the classloader * * @return list of the names of all the available shell commands. */ public List cmdlist() { List classpath = new ArrayList(); // Retrieve the list of paths representing jar-files. classpath.addAll(Arrays.asList(parseClassPath(System.getProperty("java.class.path")))); classpath.addAll(Arrays.asList(getInstJars())); // Initialize a ClassLoader that also searches jar-files for classes. URLClassLoader scl = new URLClassLoader(new URL[0], this.getClass().getClassLoader()); List cmds = new ArrayList(); classpath.addAll(Arrays.asList(scl.getURLs())); for (URL aURL : classpath) { try { if (aURL.toString().endsWith("/")) { // A Directory if (!"file".equalsIgnoreCase(aURL.getProtocol())) { continue; } File dir = new File(new File(aURL.getPath()), BIN_PATH); if (dir.exists()) { File[] dirCmds = dir.listFiles(); for (File file : Arrays.asList(dirCmds)) { try { if (file.isDirectory()) { File[] someCmds = file.listFiles(); for (File file1 : Arrays.asList(someCmds)) { if (file1.getName().endsWith(".class")) { String filename = file1.getName(); filename = filename.substring(0, filename.length() - 6); if (file.getName().equals(filename)) { if (null != getInstance(filename)) { cmds.add(filename); } } else { if (null != getInstance(file.getName() + "." + filename)) { cmds.add(file.getName() + "." + filename); } } } } } } catch (Exception ignored) { //ignored } } } } else { // A class or Jar String entryName = aURL.getPath(); if (entryName.endsWith(".class")) { // A class file entryName = entryName.substring(0, entryName.length() - 6); int cmdPath = entryName.indexOf(BIN_PATH); if (-1 != cmdPath) { String cmdName = entryName.substring(cmdPath + BIN_PATH_LEN); cmds.add(cmdName); } } else if (entryName.endsWith(".jar")) { // A jar file Enumeration eachEntry; if ("jar".equalsIgnoreCase(aURL.getProtocol())) { JarURLConnection jar = (JarURLConnection) aURL.openConnection(); JarFile jarfile = jar.getJarFile(); eachEntry = jarfile.entries(); } else { URLConnection jar = aURL.openConnection(); JarInputStream jis = new JarInputStream(jar.getInputStream()); List allEntries = new ArrayList(); JarEntry anEntry = jis.getNextJarEntry(); while (null != anEntry) { allEntries.add(anEntry); anEntry = jis.getNextJarEntry(); } eachEntry = Collections.enumeration(allEntries); } while (eachEntry.hasMoreElements()) { JarEntry anEntry = eachEntry.nextElement(); entryName = anEntry.getName(); if (entryName.endsWith(".class")) { entryName = entryName.substring(0, entryName.length() - 6); int cmdPath = entryName.indexOf(BIN_PATH); if (-1 != cmdPath) { String leafPath = entryName.substring(cmdPath + BIN_PATH_LEN); String pkgName = leafPath.substring(0, leafPath.indexOf('/')); String cmdName = leafPath.substring(leafPath.indexOf('/') + 1); if (pkgName.equals(cmdName)) { cmds.add(cmdName); } else { cmds.add(pkgName + "." + cmdName); } } } } } else { // Unknown file } } } catch (Exception failure) { if (LOG.isLoggable(Level.WARNING)) { LOG.log(Level.WARNING, " Failure processing : " + ((null != aURL) ? aURL.toString() : ""), failure); } } } Collections.sort(cmds); return cmds; } /** * Instantiates a given Command and returns its reference. For this purpose this implementation * tries to load the class 'net.jxta.impl.shell.bin.pkg.cmd'. This class is then instantiated through * the standard constructor. No other initialization is done, so the caller of this method should * set the group, outputPipe, etc. * * @param cmd The command to execute. In the form "." . * @return an instance of the specified Shell command. */ public ShellApp getInstance(String cmd) { URL[] pathURLs = getInstJars(); // Initialize a ClassLoader that also searches jar-files for classes. URLClassLoader scl = new URLClassLoader(pathURLs, this.getClass().getClassLoader()); // Make sure that the Context loader of the current thread // is properly set, so if the shell commands creates its own // thread, the Shell class loader will also be used. Thread.currentThread().setContextClassLoader(scl); // try just loading the class by name Class appClass = null; try { appClass = (Class) scl.loadClass(cmd); } catch (NoClassDefFoundError notFound) { //ignored } catch (ClassNotFoundException notFound) { //ignored } if (null == appClass) { String cmdPkg; String cmdcmdName; if (-1 == cmd.indexOf('.')) { cmdPkg = cmd; cmdcmdName = cmd; } else { cmdPkg = cmd.substring(0, cmd.lastIndexOf('.')); cmdcmdName = cmd.substring(cmd.lastIndexOf('.') + 1); } String cmdclassName = BIN_PACKAGE + "." + cmdPkg + "." + cmdcmdName; if (LOG.isLoggable(java.util.logging.Level.FINE)) LOG.finer("Loading command : " + cmdclassName); // Load the class with the help of scl. try { appClass = (Class) Class.forName(cmdclassName, true, scl); } catch (ClassNotFoundException failed) { return null; } if (!ShellApp.class.isAssignableFrom(appClass)) { return null; } try { if (null == appClass.getConstructor()) { // missing required constructor. return null; } } catch (NoSuchMethodException missingConstructor) { return null; } } // Instantiate loaded command class and return it. try { ShellApp app = appClass.newInstance(); return app; } catch (java.lang.InstantiationException failed) { throw new UndeclaredThrowableException(failed); } catch (java.lang.IllegalAccessException failed) { return null; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy