From 64a2a81c53eec801cb5d047c357778bcb0a0b1c1 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 11 Jul 2011 11:43:51 +0200 Subject: [PATCH 01/11] Added exploded deployment --- .../jboss/forge/dev/AS7DeployerPlugin.java | 87 ++++++++++++++++--- 1 file changed, 74 insertions(+), 13 deletions(-) diff --git a/dev-plugins/src/main/java/org/jboss/forge/dev/AS7DeployerPlugin.java b/dev-plugins/src/main/java/org/jboss/forge/dev/AS7DeployerPlugin.java index f8a7ad661a..e20e384bd2 100644 --- a/dev-plugins/src/main/java/org/jboss/forge/dev/AS7DeployerPlugin.java +++ b/dev-plugins/src/main/java/org/jboss/forge/dev/AS7DeployerPlugin.java @@ -21,8 +21,7 @@ */ package org.jboss.forge.dev; -import java.io.File; -import java.io.IOException; +import java.io.*; import java.util.Map; import javax.enterprise.context.ApplicationScoped; @@ -33,18 +32,15 @@ import org.jboss.forge.project.services.ResourceFactory; import org.jboss.forge.resources.DirectoryResource; import org.jboss.forge.resources.FileResource; +import org.jboss.forge.resources.Resource; import org.jboss.forge.shell.Shell; import org.jboss.forge.shell.ShellMessages; import org.jboss.forge.shell.ShellPrompt; -import org.jboss.forge.shell.plugins.Alias; -import org.jboss.forge.shell.plugins.Command; -import org.jboss.forge.shell.plugins.PipeOut; -import org.jboss.forge.shell.plugins.Plugin; +import org.jboss.forge.shell.plugins.*; import org.jboss.forge.shell.util.OSUtils; /** * @author Lincoln Baxter, III - * */ @Alias("as7") @ApplicationScoped @@ -80,16 +76,75 @@ public void deploy(final PipeOut out) FileResource deployedArtifact = getDeployedArtifact(); if (!deployedArtifact.exists() - || prompt.promptBoolean("Overwrite existing deployment? [" + deployedArtifact.getFullyQualifiedName() - + "]")) + || prompt.promptBoolean("Overwrite existing deployment? [" + deployedArtifact.getFullyQualifiedName() + + "]")) { deployedArtifact.setContents(finalArtifact.getResourceInputStream()); shell.execute("rm -rf " + deployedArtifact.getFullyQualifiedName() + ".*"); ShellMessages.success(out, "Deployed [" + finalArtifact + "] to [" - + getDeploymentDirectory().getFullyQualifiedName() + "]"); + + getDeploymentDirectory().getFullyQualifiedName() + "]"); } } + @Command + public void deployExploded(@Option(name = "triggerDeploy", flagOnly = true) boolean triggerDeploy, final PipeOut out) throws Exception + { + FileResource finalArtifact = getExploded(); + + String artifactName = finalArtifact.getName() + ".war"; + DirectoryResource deployDir = getDeploymentDirectory().getOrCreateChildDirectory(artifactName); + copyDirectory(finalArtifact.getUnderlyingResourceObject(), deployDir.getUnderlyingResourceObject()); + + if(triggerDeploy) { + + FileResource deployFile = (FileResource)getDeploymentDirectory().getChild(artifactName + ".dodeploy"); + + deployFile.createNewFile(); + } + + if(triggerDeploy) { + String deployMessage = "[" + finalArtifact + "] to [" + + getDeploymentDirectory().getFullyQualifiedName() + "]"; + ShellMessages.success(out, "Deployed " + deployMessage); + } else { + ShellMessages.success(out, "Copied [" + finalArtifact + "] to [" + + getDeploymentDirectory().getFullyQualifiedName() + ".war]. Use --triggerDeploy to redeploy the application"); + } + } + + private void copyDirectory(File sourceLocation, File targetLocation) throws IOException + { + if (sourceLocation.isDirectory()) + { + if (!targetLocation.exists()) + { + targetLocation.mkdir(); + } + + String[] children = sourceLocation.list(); + for (int i = 0; i < children.length; i++) + { + copyDirectory(new File(sourceLocation, children[i]), + new File(targetLocation, children[i])); + } + } else + { + + InputStream in = new FileInputStream(sourceLocation); + OutputStream out = new FileOutputStream(targetLocation); + + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) + { + out.write(buf, 0, len); + } + in.close(); + out.close(); + } + } + + @Command public void undeploy(final PipeOut out) { @@ -97,13 +152,13 @@ public void undeploy(final PipeOut out) FileResource deployedArtifact = getDeployedArtifact(); if (deployedArtifact.exists() - && prompt.promptBoolean("Really undeploy [" + deployedArtifact.getFullyQualifiedName() - + "]?")) + && prompt.promptBoolean("Really undeploy [" + deployedArtifact.getFullyQualifiedName() + + "]?")) { deployedArtifact.setContents(finalArtifact.getResourceInputStream()); shell.execute("rm -rf " + deployedArtifact.getFullyQualifiedName() + "*"); ShellMessages.success(out, "Removed deployment [" + finalArtifact + "] from [" - + getDeploymentDirectory().getFullyQualifiedName() + "]"); + + getDeploymentDirectory().getFullyQualifiedName() + "]"); } } @@ -142,6 +197,12 @@ public FileResource getFinalArtifact() return finalArtifact; } + public DirectoryResource getExploded() + { + PackagingFacet packaging = project.getFacet(PackagingFacet.class); + return project.getProjectRoot().getChildDirectory("target").getChildDirectory(packaging.getFinalName()); + } + public FileResource getDeployedArtifact() { DirectoryResource deployDir = getDeploymentDirectory(); From a38c53574a7d07d4e1867b6d15e769ed903f8048 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Wed, 13 Jul 2011 22:21:29 +0200 Subject: [PATCH 02/11] Added a build option that calls "mvn compile war:explded". --- .../main/java/org/jboss/forge/dev/AS7DeployerPlugin.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dev-plugins/src/main/java/org/jboss/forge/dev/AS7DeployerPlugin.java b/dev-plugins/src/main/java/org/jboss/forge/dev/AS7DeployerPlugin.java index e20e384bd2..47a5b88f60 100644 --- a/dev-plugins/src/main/java/org/jboss/forge/dev/AS7DeployerPlugin.java +++ b/dev-plugins/src/main/java/org/jboss/forge/dev/AS7DeployerPlugin.java @@ -87,8 +87,14 @@ public void deploy(final PipeOut out) } @Command - public void deployExploded(@Option(name = "triggerDeploy", flagOnly = true) boolean triggerDeploy, final PipeOut out) throws Exception + public void deployExploded(@Option(name = "triggerDeploy", flagOnly = true) boolean triggerDeploy, + @Option(name = "build", flagOnly = true) boolean build, + final PipeOut out) throws Exception { + if(build) { + shell.execute("mvn compile war:exploded"); + } + FileResource finalArtifact = getExploded(); String artifactName = finalArtifact.getName() + ".war"; From af8a7ce05b646667f28f45c9246aff0856b49063 Mon Sep 17 00:00:00 2001 From: "Lincoln Baxter, III" Date: Fri, 15 Jul 2011 15:52:28 -0400 Subject: [PATCH 03/11] SEAMFORGE-252, SEAMFORGE-226 --- .../java/org/jboss/forge/shell/Shell.java | 9 + .../org/jboss/forge/shell/ShellPrompt.java | 6 + .../forge/shell/command/CommandMetadata.java | 124 ++++++ .../forge/shell/command/OptionMetadata.java | 156 +++++++ .../forge/shell/command/PluginMetadata.java | 144 ++++++ .../forge/shell/command/PluginRegistry.java | 65 +++ .../shell/spi/InputStreamInterceptor.java | 37 ++ .../forge/shell/AbstractShellPrompt.java | 18 + .../java/org/jboss/forge/shell/ShellImpl.java | 18 +- .../command/CommandLibraryExtension.java | 8 +- ...Metadata.java => CommandMetadataImpl.java} | 46 +- .../jboss/forge/shell/command/Execution.java | 4 +- ...nMetadata.java => OptionMetadataImpl.java} | 36 +- ...nMetadata.java => PluginMetadataImpl.java} | 25 +- ...nRegistry.java => PluginRegistryImpl.java} | 11 +- .../shell/constraint/ConstraintEnforcer.java | 2 +- .../plugins/builtin/ListCommandsPlugin.java | 4 +- .../forge/shell/test/ShellPromptTest.java | 412 ++++++++++-------- 18 files changed, 879 insertions(+), 246 deletions(-) create mode 100644 shell-api/src/main/java/org/jboss/forge/shell/command/CommandMetadata.java create mode 100644 shell-api/src/main/java/org/jboss/forge/shell/command/OptionMetadata.java create mode 100644 shell-api/src/main/java/org/jboss/forge/shell/command/PluginMetadata.java create mode 100644 shell-api/src/main/java/org/jboss/forge/shell/command/PluginRegistry.java create mode 100644 shell-api/src/main/java/org/jboss/forge/shell/spi/InputStreamInterceptor.java rename shell/src/main/java/org/jboss/forge/shell/command/{CommandMetadata.java => CommandMetadataImpl.java} (90%) rename shell/src/main/java/org/jboss/forge/shell/command/{OptionMetadata.java => OptionMetadataImpl.java} (94%) rename shell/src/main/java/org/jboss/forge/shell/command/{PluginMetadata.java => PluginMetadataImpl.java} (94%) rename shell/src/main/java/org/jboss/forge/shell/command/{PluginRegistry.java => PluginRegistryImpl.java} (94%) diff --git a/shell-api/src/main/java/org/jboss/forge/shell/Shell.java b/shell-api/src/main/java/org/jboss/forge/shell/Shell.java index 768c1777a1..07b16f3541 100644 --- a/shell-api/src/main/java/org/jboss/forge/shell/Shell.java +++ b/shell-api/src/main/java/org/jboss/forge/shell/Shell.java @@ -192,6 +192,15 @@ public interface Shell extends ShellPrintWriter, ShellPrompt, ShellHistory */ String readLine() throws IOException; + /** + * Ask the current {@link InputStream} for input, masking keystrokes in the console with the given mask. + * + * @param mask The sequence to use for masking input + * @return any read data as a string, or null if none available. + * @throws IOException on error + */ + String readLine(String mask) throws IOException; + /** * Controls the shell's usage of ANSI escape code support. This method does not guarantee ANSI will function * properly, as the underlying Terminal must also support it. diff --git a/shell-api/src/main/java/org/jboss/forge/shell/ShellPrompt.java b/shell-api/src/main/java/org/jboss/forge/shell/ShellPrompt.java index 34f276ef90..718513eed4 100644 --- a/shell-api/src/main/java/org/jboss/forge/shell/ShellPrompt.java +++ b/shell-api/src/main/java/org/jboss/forge/shell/ShellPrompt.java @@ -214,4 +214,10 @@ public interface ShellPrompt * @param type The command completer type to instantiate and use during completion */ String promptCompleter(String string, Class type); + + /** + * First print the given message, prompt the user for input (masking keystrokes for secrecy,) then return user input. + */ + String promptSecret(String message); + } diff --git a/shell-api/src/main/java/org/jboss/forge/shell/command/CommandMetadata.java b/shell-api/src/main/java/org/jboss/forge/shell/command/CommandMetadata.java new file mode 100644 index 0000000000..8d0f3de40d --- /dev/null +++ b/shell-api/src/main/java/org/jboss/forge/shell/command/CommandMetadata.java @@ -0,0 +1,124 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.forge.shell.command; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.Set; + +import org.jboss.forge.resources.Resource; + +/** + * Defines a command. + * + * @author Lincoln Baxter, III + * + */ +public interface CommandMetadata +{ + /** + * Get the help text for this comand. + */ + String getHelp(); + + /** + * Get the {@link Method} that implements this command. + */ + Method getMethod(); + + /** + * Get the name of this command. + */ + String getName(); + + /** + * Get the option defined by the given name. + * + * @throws IllegalArgumentException if no such option exists. + */ + OptionMetadata getNamedOption(String name) throws IllegalArgumentException; + + /** + * Return the number of ordered (unnamed) options defined by this command. + */ + int getNumOrderedOptions(); + + /** + * Return the option at the given index in the plugin method signature, not the index of the option on the command + * line. + */ + OptionMetadata getOptionByAbsoluteIndex(int index); + + /** + * Return a list of all options defined by this command. + */ + List getOptions(); + + /** + * Return the option at the given index as required on the command line, not the index of the option in the + * implementing method signature. + */ + OptionMetadata getOrderedOptionByIndex(int index) throws IllegalArgumentException; + + /** + * Return the {@link PluginMetadata} containing this command. + */ + PluginMetadata getParent(); + + /** + * Return the set of {@link Resource} types for which this command is in scope, or available. + */ + @SuppressWarnings("rawtypes") + Set> getResourceScopes(); + + /** + * Return true if this command has an {@link OptionMetadata} with the given name. + */ + boolean hasOption(String name); + + /** + * Return true if this command has any options. + */ + boolean hasOptions(); + + /** + * Return true if this command accepts ordered options. + */ + boolean hasOrderedOptions(); + + /** + * Return true if this command accepts options that declare a short name. + */ + boolean hasShortOption(String name); + + /** + * Return true if this command is the default command for its declaring {@link PluginMetadata} + */ + boolean isDefault(); + + /** + * Return true if this command is usable with the given resource scope. + */ + @SuppressWarnings("rawtypes") + boolean usableWithResource(Class class1); + +} diff --git a/shell-api/src/main/java/org/jboss/forge/shell/command/OptionMetadata.java b/shell-api/src/main/java/org/jboss/forge/shell/command/OptionMetadata.java new file mode 100644 index 0000000000..07dd9d33c7 --- /dev/null +++ b/shell-api/src/main/java/org/jboss/forge/shell/command/OptionMetadata.java @@ -0,0 +1,156 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.forge.shell.command; + +import org.jboss.forge.shell.PromptType; +import org.jboss.forge.shell.completer.CommandCompleter; +import org.jboss.forge.shell.plugins.PipeIn; +import org.jboss.forge.shell.plugins.PipeOut; + +/** + * Defines an option. + * + * @author Lincoln Baxter, III + */ +public interface OptionMetadata +{ + /** + * Return the boxed type for this option. E.g: If the literal type is 'int', the boxed type is {@link Integer} + */ + Class getBoxedType(); + + /** + * Return the type of the {@link CommandCompleter} for this option. + */ + Class getCompleterType(); + + /** + * Get the default value for this option. Default values are used when no value is passed from the command line. + */ + String getDefaultValue(); + + /** + * Get the description text for this option. + */ + String getDescription(); + + /** + * Get the help text for this option. + */ + String getHelp(); + + /** + * Get the index of this option in the receiving method signature parameter list. + */ + int getIndex(); + + /** + * Get the name of this option. + */ + String getName(); + + /** + * Get the verbose description of this option. + */ + String getOptionDescriptor(); + + /** + * Get the {@link CommandMetadata} defining this option. + */ + CommandMetadata getParent(); + + /** + * Get the requested {@link PromptType} for this option. + */ + PromptType getPromptType(); + + /** + * Get the short name for this option, if it exists; otherwise, return empty string. + */ + String getShortName(); + + /** + * Get the literal type of this option. + */ + Class getType(); + + /** + * Return true if this option specifies a custom {@link CommandCompleter}. + */ + boolean hasCustomCompleter(); + + /** + * Return true if this option has a default value. + */ + boolean hasDefaultValue(); + + /** + * Return true if this option is a boolean type. + */ + boolean isBoolean(); + + /** + * Return true if this option is an enum type. + */ + boolean isEnum(); + + /** + * Return true if this option is only a flag, and only has a short name, taking no value on the command line. + */ + boolean isFlagOnly(); + + /** + * Return true if this option is named. + */ + boolean isNamed(); + + /** + * Return true if this option is not named, and must be specified by order. + */ + boolean isOrdered(); + + /** + * Return true if this option is the {@link PipeIn} + */ + boolean isPipeIn(); + + /** + * Return true if this option is the {@link PipeOut} + */ + boolean isPipeOut(); + + /** + * Return true if this option is required, and cannot be omitted on the command line. + */ + boolean isRequired(); + + /** + * Return true if this option accepts multiple values on the command line. + */ + boolean isVarargs(); + + /** + * Return true if this option is not ordered: E.g. It may be named, or may be a {@link PipeIn} or {@link PipeOut} + */ + boolean notOrdered(); + +} diff --git a/shell-api/src/main/java/org/jboss/forge/shell/command/PluginMetadata.java b/shell-api/src/main/java/org/jboss/forge/shell/command/PluginMetadata.java new file mode 100644 index 0000000000..77b4dbfbe8 --- /dev/null +++ b/shell-api/src/main/java/org/jboss/forge/shell/command/PluginMetadata.java @@ -0,0 +1,144 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.forge.shell.command; + +import java.util.List; +import java.util.Set; + +import org.jboss.forge.resources.Resource; +import org.jboss.forge.shell.Shell; +import org.jboss.forge.shell.plugins.Plugin; +import org.jboss.forge.shell.plugins.RequiresFacet; +import org.jboss.forge.shell.plugins.RequiresProject; + +/** + * Defines a plugin. + * + * @author Lincoln Baxter, III + * + */ +public interface PluginMetadata +{ + /** + * Return true if all constraints defined on this plugin (such as {@link RequiresProject} or {@link RequiresFacet}) + * are satisfied by the current project (if available) and {@link Shell#getCurrentResource()} scope. + */ + boolean constrantsSatisfied(Shell shell); + + /** + * Get a list of all commands defined by this plugin, regardless of the current {@link Shell#getCurrentResource()} + * scope or constraints. + */ + List getAllCommands(); + + /** + * Get the command with the given name, if it exists in this plugin and is not overloaded in multiple + * {@link Resource} scopes. If it does not exist, return null. + */ + CommandMetadata getCommand(String name); + + /** + * Get the command with the given name and {@link Resource} scope, if it exists in this plugin. If it does not exist, + * return null. + */ + CommandMetadata getCommand(String name, Class> scope); + + /** + * Get the command with the given name if it exists in this plugin, and is available in the current + * {@link Shell#getCurrentResource()} scope. If it does not exist, or is not in scope, return null. + */ + CommandMetadata getCommand(String name, Shell shell); + + /** + * Get a list of all commands defined by this plugin, if they are in scope. + */ + List getCommands(); + + /** + * For the {@link Shell#getCurrentResource()} scope, return a list of all available commands defined by this plugin. + */ + List getCommands(Shell shell); + + /** + * Get the default command specified by this plugin. If none exists, return null. + */ + CommandMetadata getDefaultCommand(); + + /** + * Get the help text for this plugin. + */ + String getHelp(); + + /** + * Get the name by which this plugin is referenced on the command line. + */ + String getName(); + + /** + * Get the {@link Resource} scopes for which this plugin is available. + */ + Set>> getResourceScopes(); + + /** + * Get the topic text for this plugin. + */ + String getTopic(); + + /** + * Get the implementing {@link Plugin} class type for this {@link PluginMetadata} + */ + Class getType(); + + /** + * Return true if this plugin defines a command with the given name and {@link Resource} scope. + */ + boolean hasCommand(String name, Class> scope); + + /** + * Return true if this plugin defines a command with the given name in the current + * {@link Shell#getCurrentResourceScope()} + */ + boolean hasCommand(String name, Shell shell); + + /** + * Return true if this plugin has any commands. + */ + boolean hasCommands(); + + /** + * Return true if this plugin has a default command. Default commands are executed with the name of the plugin, + * instead of the name of the command. + */ + boolean hasDefaultCommand(); + + /** + * Return true if this plugin is overloaded in multiple {@link Resource} scopes. + */ + boolean isCommandOverloaded(String name); + + /** + * Return true if this plugin is usable in the given {@link Resource} scope + */ + @SuppressWarnings("rawtypes") + boolean usableWithScope(Class scope); + +} diff --git a/shell-api/src/main/java/org/jboss/forge/shell/command/PluginRegistry.java b/shell-api/src/main/java/org/jboss/forge/shell/command/PluginRegistry.java new file mode 100644 index 0000000000..db6aa6411e --- /dev/null +++ b/shell-api/src/main/java/org/jboss/forge/shell/command/PluginRegistry.java @@ -0,0 +1,65 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.forge.shell.command; + +import java.util.List; +import java.util.Map; + +import org.jboss.forge.shell.Shell; +import org.jboss.forge.shell.plugins.Plugin; +import org.jboss.forge.shell.plugins.RequiresFacet; +import org.jboss.forge.shell.plugins.RequiresProject; + +/** + * Contains the collection of all installed and available plugins. + * + * @author Lincoln Baxter, III + */ +public interface PluginRegistry +{ + /** + * Add a plugin to the registry. Typically this will only be used by Forge itself. + */ + void addPlugin(PluginMetadata plugin); + + /** + * Get the {@link PluginMetadata} for the given plugin name. Returns an empty list if no plugins exist for the given + * name. + */ + List getPluginMetadata(String plugin); + + /** + * Resolves a single {@link PluginMetadata} instance representing the singular type that is in scope, and satisfied + * by the current project constraints such as {@link RequiresProject} or {@link RequiresFacet} + */ + PluginMetadata getPluginMetadataForScopeAndConstraints(String name, Shell shell); + + /** + * Get a map of all known plugin names and metadata. + */ + Map> getPlugins(); + + /** + * Get the {@link Plugin} instance defined by the given {@link PluginMetadata} + */ + Plugin instanceOf(PluginMetadata meta); +} diff --git a/shell-api/src/main/java/org/jboss/forge/shell/spi/InputStreamInterceptor.java b/shell-api/src/main/java/org/jboss/forge/shell/spi/InputStreamInterceptor.java new file mode 100644 index 0000000000..69143fe63d --- /dev/null +++ b/shell-api/src/main/java/org/jboss/forge/shell/spi/InputStreamInterceptor.java @@ -0,0 +1,37 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.forge.shell.spi; + +/** + * Allows the shell input stream to be intercepted, modified, or observed by extensions. + * + * @author Lincoln Baxter, III + * + */ +public interface InputStreamInterceptor +{ + /** + * Intercepts a line of input and returns it along with any modifications. The returned value will be passed to the + * Shell for invocation. + */ + public String intercept(String line); +} diff --git a/shell/src/main/java/org/jboss/forge/shell/AbstractShellPrompt.java b/shell/src/main/java/org/jboss/forge/shell/AbstractShellPrompt.java index 1d1f5de59e..85d1f3996c 100644 --- a/shell/src/main/java/org/jboss/forge/shell/AbstractShellPrompt.java +++ b/shell/src/main/java/org/jboss/forge/shell/AbstractShellPrompt.java @@ -22,6 +22,7 @@ package org.jboss.forge.shell; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -70,6 +71,23 @@ public String prompt() return prompt(""); } + @Override + public String promptSecret(String message) + { + if (!message.isEmpty() && message.matches("^.*\\S$")) + { + message = message + " "; + } + message = renderColor(ShellColor.CYAN, " ? ") + message; + + try { + return readLine("*"); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + @Override public String promptAndSwallowCR() { diff --git a/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java b/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java index 283937f8f3..5e54934639 100644 --- a/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java +++ b/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java @@ -594,7 +594,7 @@ private String formatSourcedError(final CommandMetadata cmd) String out = null; if (cmd != null) { - out = cmd.getPluginMetadata().getName(); + out = cmd.getParent().getName(); if (!cmd.isDefault()) out += " " + cmd.getName(); @@ -609,7 +609,21 @@ private String formatSourcedError(final CommandMetadata cmd) @Override public String readLine() throws IOException { - String line = reader.readLine(); + return readLine(null); + } + + @Override + public String readLine(final String mask) throws IOException + { + String line = null; + if (mask != null) + { + line = reader.readLine(mask); + } + else + { + line = reader.readLine(); + } if (isExecuting() && (line == null)) { diff --git a/shell/src/main/java/org/jboss/forge/shell/command/CommandLibraryExtension.java b/shell/src/main/java/org/jboss/forge/shell/command/CommandLibraryExtension.java index eafa06c5be..a9084f0c6e 100644 --- a/shell/src/main/java/org/jboss/forge/shell/command/CommandLibraryExtension.java +++ b/shell/src/main/java/org/jboss/forge/shell/command/CommandLibraryExtension.java @@ -84,7 +84,7 @@ public PluginMetadata getMetadataFor(final Class plugin) { String name = getPluginName(plugin); - PluginMetadata pluginMeta = new PluginMetadata(); + PluginMetadataImpl pluginMeta = new PluginMetadataImpl(); pluginMeta.setName(name); pluginMeta.setType(plugin); @@ -116,7 +116,7 @@ public PluginMetadata getMetadataFor(final Class plugin) } @SuppressWarnings("rawtypes") - private List processPluginCommands(final PluginMetadata pluginMeta, final Class plugin) + private List processPluginCommands(final PluginMetadataImpl pluginMeta, final Class plugin) { List results = new ArrayList(); @@ -125,7 +125,7 @@ private List processPluginCommands(final PluginMetadata pluginM if (Annotations.isAnnotationPresent(method, Command.class)) { Command command = Annotations.getAnnotation(method, Command.class); - CommandMetadata commandMeta = new CommandMetadata(); + CommandMetadataImpl commandMeta = new CommandMetadataImpl(); commandMeta.setMethod(method); commandMeta.setHelp(command.help()); commandMeta.setParent(pluginMeta); @@ -184,7 +184,7 @@ private List processPluginCommands(final PluginMetadata pluginM int i = 0; for (Class clazz : parameterTypes) { - OptionMetadata optionMeta = new OptionMetadata(); + OptionMetadataImpl optionMeta = new OptionMetadataImpl(); optionMeta.setType(clazz); optionMeta.setIndex(i); diff --git a/shell/src/main/java/org/jboss/forge/shell/command/CommandMetadata.java b/shell/src/main/java/org/jboss/forge/shell/command/CommandMetadataImpl.java similarity index 90% rename from shell/src/main/java/org/jboss/forge/shell/command/CommandMetadata.java rename to shell/src/main/java/org/jboss/forge/shell/command/CommandMetadataImpl.java index 8fc0039113..25d64c8467 100644 --- a/shell/src/main/java/org/jboss/forge/shell/command/CommandMetadata.java +++ b/shell/src/main/java/org/jboss/forge/shell/command/CommandMetadataImpl.java @@ -35,11 +35,10 @@ /** * @author Lincoln Baxter, III */ -public class CommandMetadata +public class CommandMetadataImpl implements CommandMetadata { private PluginMetadata parent; private Method method; - private Method pipeInMethod; private boolean isDefault = false; @@ -47,11 +46,10 @@ public class CommandMetadata private String help = ""; private List options = new ArrayList(); - private int parmLength = 0; - @SuppressWarnings("rawtypes") private Set> resourceScopes = Collections.emptySet(); + @Override public OptionMetadata getNamedOption(final String name) throws IllegalArgumentException { for (OptionMetadata option : options) @@ -64,10 +62,7 @@ public OptionMetadata getNamedOption(final String name) throws IllegalArgumentEx throw new IllegalArgumentException("No such option [" + name + "] for command: " + this); } - /** - * Return the option at the given index. This index represents where the option was defined in the plugin method - * signature, not the index of the option on the command line. - */ + @Override public OptionMetadata getOptionByAbsoluteIndex(final int index) { for (OptionMetadata option : options) @@ -81,6 +76,7 @@ public OptionMetadata getOptionByAbsoluteIndex(final int index) } + @Override public OptionMetadata getOrderedOptionByIndex(final int index) throws IllegalArgumentException { int currentIndex = 0; @@ -98,6 +94,7 @@ else if (option.isOrdered()) throw new IllegalArgumentException("No option with index [" + index + "] exists for command: " + this); } + @Override public int getNumOrderedOptions() { int count = 0; @@ -111,6 +108,7 @@ public int getNumOrderedOptions() return count; } + @Override public Method getMethod() { return method; @@ -121,16 +119,7 @@ public void setMethod(final Method method) this.method = method; } - public Method getPipeInMethod() - { - return pipeInMethod; - } - - public void setPipeInMethod(final Method pipeInMethod) - { - this.pipeInMethod = pipeInMethod; - } - + @Override public boolean isDefault() { return isDefault; @@ -141,6 +130,7 @@ public void setDefault(final boolean isDefault) this.isDefault = isDefault; } + @Override public String getName() { return name; @@ -151,6 +141,7 @@ public void setName(final String name) this.name = name; } + @Override public List getOptions() { if (options == null) @@ -199,6 +190,7 @@ public void addOption(final OptionMetadata option) this.options.add(option); } + @Override public String getHelp() { return help; @@ -215,7 +207,8 @@ public String toString() return name; } - public PluginMetadata getPluginMetadata() + @Override + public PluginMetadata getParent() { return parent; } @@ -225,11 +218,13 @@ public void setParent(final PluginMetadata parent) this.parent = parent; } + @Override public boolean hasOptions() { return !getOptions().isEmpty(); } + @Override public boolean hasShortOption(final String name) { for (OptionMetadata option : options) @@ -242,6 +237,7 @@ public boolean hasShortOption(final String name) return false; } + @Override public boolean hasOption(final String name) { for (OptionMetadata option : options) @@ -257,6 +253,7 @@ public boolean hasOption(final String name) return false; } + @Override @SuppressWarnings("rawtypes") public Set> getResourceScopes() { @@ -275,16 +272,7 @@ public boolean usableWithResource(final Class resource) return (this.resourceScopes.size() == 0) || this.resourceScopes.contains(resource); } - public int getParmLength() - { - return parmLength; - } - - public void setParmLength(final int parmLength) - { - this.parmLength = parmLength; - } - + @Override public boolean hasOrderedOptions() { try { diff --git a/shell/src/main/java/org/jboss/forge/shell/command/Execution.java b/shell/src/main/java/org/jboss/forge/shell/command/Execution.java index 76a0a69f5b..9139eb995b 100644 --- a/shell/src/main/java/org/jboss/forge/shell/command/Execution.java +++ b/shell/src/main/java/org/jboss/forge/shell/command/Execution.java @@ -70,7 +70,7 @@ public void verifyConstraints(final Shell shell) { try { - enforcer.verifyAvailable(shell.getCurrentProject(), command.getPluginMetadata()); + enforcer.verifyAvailable(shell.getCurrentProject(), command.getParent()); } catch (ConstraintException e) { @@ -84,7 +84,7 @@ public void perform(final PipeOut pipeOut) { if (command != null) { - Class pluginType = command.getPluginMetadata().getType(); + Class pluginType = command.getParent().getType(); Set> beans = manager.getBeans(pluginType); Bean bean = manager.resolve(beans); diff --git a/shell/src/main/java/org/jboss/forge/shell/command/OptionMetadata.java b/shell/src/main/java/org/jboss/forge/shell/command/OptionMetadataImpl.java similarity index 94% rename from shell/src/main/java/org/jboss/forge/shell/command/OptionMetadata.java rename to shell/src/main/java/org/jboss/forge/shell/command/OptionMetadataImpl.java index a3580497a7..af017db608 100644 --- a/shell/src/main/java/org/jboss/forge/shell/command/OptionMetadata.java +++ b/shell/src/main/java/org/jboss/forge/shell/command/OptionMetadataImpl.java @@ -35,7 +35,7 @@ * @author Lincoln Baxter, III * */ -public class OptionMetadata +public class OptionMetadataImpl implements OptionMetadata { private CommandMetadata parent; private Class type; @@ -55,13 +55,13 @@ public class OptionMetadata private boolean pipeIn; private Class completerType; - public OptionMetadata() - { - } + public OptionMetadataImpl() + {} /** * Get an informational string describing this Option */ + @Override public String getOptionDescriptor() { StringAppender appender = new StringAppender("["); @@ -87,6 +87,7 @@ public String getOptionDescriptor() /** * Return whether this option is to be mapped via name or via parameter order. */ + @Override public boolean isNamed() { return (name != null) && !"".equals(name); @@ -96,6 +97,7 @@ public boolean isNamed() * Return the Boxed type of this Option, e.g: If the option is actual an int.class, return * Integer.class instead. */ + @Override public Class getBoxedType() { return ParseTools.boxPrimitive(getType()); @@ -104,6 +106,7 @@ public Class getBoxedType() /** * Return the literal type represented by this Option, e.g: the actual method parameter type. */ + @Override public Class getType() { return type; @@ -117,6 +120,7 @@ public void setType(final Class type) /** * Return the name of this Option, if it has one */ + @Override public String getName() { return name; @@ -130,6 +134,7 @@ public void setName(final String name) /** * Get the short name of this option, if it has one. */ + @Override public String getShortName() { return shortName; @@ -143,6 +148,7 @@ public void setShortName(final String shortName) /** * Return whether or not this option is purely a boolean flag. */ + @Override public boolean isFlagOnly() { return flagOnly; @@ -156,6 +162,7 @@ public void setFlagOnly(final boolean flagOnly) /** * Return the description of this Option */ + @Override public String getDescription() { return description; @@ -166,9 +173,7 @@ public void setDescription(final String description) this.description = description; } - /** - * Get the index of this Option in the receiving method parameter list. - */ + @Override public int getIndex() { return index; @@ -182,6 +187,7 @@ public void setIndex(final int index) /** * Get the help text for this Option */ + @Override public String getHelp() { return help; @@ -195,6 +201,7 @@ public void setHelp(final String help) /** * Return whether or not this option requires a value at execution time. */ + @Override public boolean isRequired() { return required; @@ -214,6 +221,7 @@ public String toString() /** * Get the parent Command of this Option */ + @Override public CommandMetadata getParent() { return parent; @@ -227,6 +235,7 @@ public void setParent(final CommandMetadata parent) /** * Return whether or not this option represents a {@link Boolean} type */ + @Override public boolean isBoolean() { return (Boolean.TYPE.equals(getType()) || Boolean.class.equals(getType())); @@ -235,14 +244,16 @@ public boolean isBoolean() /** * Return whether or not this option represents an {@link Enum} type. */ + @Override public boolean isEnum() { - return getType() != null && getType().isEnum(); + return (getType() != null) && getType().isEnum(); } /** * Return whether or not this option represents a Varargs parameter type */ + @Override public boolean isVarargs() { return getType().isArray(); @@ -251,6 +262,7 @@ public boolean isVarargs() /** * Return the default value for this Option, if specified */ + @Override public String getDefaultValue() { return defaultValue; @@ -264,6 +276,7 @@ public void setDefaultValue(final String defaultValue) /** * Return whether or not this Option provides a default value */ + @Override public boolean hasDefaultValue() { return (defaultValue != null) && !"".equals(defaultValue); @@ -272,6 +285,7 @@ public boolean hasDefaultValue() /** * Return the selected {@link PromptType} for this Option. */ + @Override public PromptType getPromptType() { return promptType; @@ -285,6 +299,7 @@ public void setPromptType(final PromptType type) /** * Return whether or not this Option is a {@link PipeOut} */ + @Override public boolean isPipeOut() { return pipeOut; @@ -298,6 +313,7 @@ public void setPipeOut(final boolean pipeOut) /** * Return whether or not this Option is a {@link PipeIn} */ + @Override public boolean isPipeIn() { return pipeIn; @@ -311,11 +327,13 @@ public void setPipeIn(final boolean pipeIn) /** * Return whether or not this Option is not ordered, e.g: It might have a name, or be an input/output pipe. */ + @Override public boolean notOrdered() { return pipeIn || pipeOut || isNamed(); } + @Override public boolean isOrdered() { return !notOrdered(); @@ -324,6 +342,7 @@ public boolean isOrdered() /** * Return whether or not this option has specified a custom {@link CommandCompleter} */ + @Override public boolean hasCustomCompleter() { return (completerType != null) && !completerType.equals(NullCommandCompleter.class); @@ -337,6 +356,7 @@ public void setCompleterType(final Class type) /** * Get the custom {@link CommandCompleter} for this Option, if specified. */ + @Override public Class getCompleterType() { return completerType; diff --git a/shell/src/main/java/org/jboss/forge/shell/command/PluginMetadata.java b/shell/src/main/java/org/jboss/forge/shell/command/PluginMetadataImpl.java similarity index 94% rename from shell/src/main/java/org/jboss/forge/shell/command/PluginMetadata.java rename to shell/src/main/java/org/jboss/forge/shell/command/PluginMetadataImpl.java index 90bcfc2d5f..eb30f8da00 100644 --- a/shell/src/main/java/org/jboss/forge/shell/command/PluginMetadata.java +++ b/shell/src/main/java/org/jboss/forge/shell/command/PluginMetadataImpl.java @@ -40,7 +40,7 @@ * @author Lincoln Baxter, III * @author Mike Brock */ -public class PluginMetadata +public class PluginMetadataImpl implements PluginMetadata { private String help = ""; private String name = ""; @@ -56,11 +56,13 @@ public class PluginMetadata private boolean scopeOverloaded = false; + @Override public CommandMetadata getCommand(final String name) { return getCommand(name, (Class>) null); } + @Override public CommandMetadata getCommand(final String name, final Shell shell) { return getCommand(name, shell.getCurrentResourceScope()); @@ -69,6 +71,7 @@ public CommandMetadata getCommand(final String name, final Shell shell) /** * Get the command matching the given name, or return null. */ + @Override public CommandMetadata getCommand(final String name, final Class> scope) { if (scope == null) @@ -105,21 +108,25 @@ public CommandMetadata getCommand(final String name, final Class> scope) { return getCommand(name, scope) != null; } + @Override public boolean hasDefaultCommand() { return getDefaultCommand() != null; } + @Override public CommandMetadata getDefaultCommand() { return defaultCommand; @@ -140,7 +147,7 @@ public void addCommand(final CommandMetadata command) if (defaultCommand != null) { throw new RuntimeException("default command already defined: " + command.getName() + "; for plugin: " - + name); + + name); } defaultCommand = command; } @@ -157,17 +164,19 @@ public void addCommand(final CommandMetadata command) commandMap.get(command.getName()).add(command); } + @Override public List getCommands() { return getCommands((Class>) null); } + @Override public List getCommands(final Shell shell) { return getCommands(shell.getCurrentResourceScope()); } - public List getCommands(final Class> scope) + private List getCommands(final Class> scope) { if ((scope == null) && scopeOverloaded) { @@ -188,6 +197,7 @@ public List getCommands(final Class> scop return Collections.unmodifiableList(result); } + @Override public List getAllCommands() { List result = new ArrayList(); @@ -201,6 +211,7 @@ public List getAllCommands() return Collections.unmodifiableList(result); } + @Override public boolean isCommandOverloaded(final String name) { return commandMap.containsKey(name) && (commandMap.get(name).size() > 1); @@ -212,6 +223,7 @@ public String toString() return name; } + @Override public String getName() { return name; @@ -222,6 +234,7 @@ public void setName(final String name) this.name = name; } + @Override public Class getType() { return type; @@ -232,6 +245,7 @@ public void setType(final Class type) this.type = type; } + @Override public String getHelp() { return help; @@ -242,6 +256,7 @@ public void setHelp(final String help) this.help = help; } + @Override public String getTopic() { return topic; @@ -252,11 +267,13 @@ public void setTopic(final String topic) this.topic = topic.toUpperCase(); } + @Override public boolean hasCommands() { return !commandMap.isEmpty(); } + @Override public boolean constrantsSatisfied(final Shell shell) { try @@ -271,12 +288,14 @@ public boolean constrantsSatisfied(final Shell shell) } } + @Override @SuppressWarnings("rawtypes") public boolean usableWithScope(final Class scope) { return resourceScopes.isEmpty() || resourceScopes.contains(scope); } + @Override public Set>> getResourceScopes() { return resourceScopes; diff --git a/shell/src/main/java/org/jboss/forge/shell/command/PluginRegistry.java b/shell/src/main/java/org/jboss/forge/shell/command/PluginRegistryImpl.java similarity index 94% rename from shell/src/main/java/org/jboss/forge/shell/command/PluginRegistry.java rename to shell/src/main/java/org/jboss/forge/shell/command/PluginRegistryImpl.java index 74c6ac5eba..7459047ab2 100644 --- a/shell/src/main/java/org/jboss/forge/shell/command/PluginRegistry.java +++ b/shell/src/main/java/org/jboss/forge/shell/command/PluginRegistryImpl.java @@ -49,7 +49,7 @@ * @author Lincoln Baxter, III */ @Singleton -public class PluginRegistry +public class PluginRegistryImpl implements PluginRegistry { private Map> plugins; private Map, PluginMetadata>> accessCache; @@ -58,7 +58,7 @@ public class PluginRegistry private final BeanManager manager; @Inject - public PluginRegistry(final CommandLibraryExtension library, final BeanManager manager) + public PluginRegistryImpl(final CommandLibraryExtension library, final BeanManager manager) { this.library = library; this.manager = manager; @@ -72,11 +72,13 @@ public void init() sanityCheck(); } + @Override public Map> getPlugins() { return plugins; } + @Override public void addPlugin(final PluginMetadata plugin) { if (!plugins.containsKey(plugin.getName())) @@ -93,13 +95,14 @@ public String toString() return "PluginRegistry [plugins=" + plugins + "]"; } + @Override public Plugin instanceOf(final PluginMetadata meta) { return getContextualInstance(manager, meta.getType()); } @SuppressWarnings("unchecked") - public static T getContextualInstance(final BeanManager manager, final Class type) + private static T getContextualInstance(final BeanManager manager, final Class type) { T result = null; Bean bean = (Bean) manager.resolve(manager.getBeans(type)); @@ -119,6 +122,7 @@ public static T getContextualInstance(final BeanManager manager, final Class * * @return the metadata, or null if no plugin with given name exists. */ + @Override public List getPluginMetadata(final String plugin) { List list = plugins.get(plugin); @@ -133,6 +137,7 @@ public List getPluginMetadata(final String plugin) * {@link org.jboss.forge.maven.Project}, {@link PackagingType}, and {@link Facet} constraints. Return null if no * match for the given constraints can be found. */ + @Override public PluginMetadata getPluginMetadataForScopeAndConstraints(final String name, final Shell shell) { Class> scope = shell.getCurrentResourceScope(); diff --git a/shell/src/main/java/org/jboss/forge/shell/constraint/ConstraintEnforcer.java b/shell/src/main/java/org/jboss/forge/shell/constraint/ConstraintEnforcer.java index f29acbcbfe..3c78318797 100644 --- a/shell/src/main/java/org/jboss/forge/shell/constraint/ConstraintEnforcer.java +++ b/shell/src/main/java/org/jboss/forge/shell/constraint/ConstraintEnforcer.java @@ -41,7 +41,7 @@ public void verifyAvailable(final Project currentProject, final CommandMetadata UnsatisfiedPackagingTypeException, UnsatisfiedFacetDependencyException { - Class type = command.getPluginMetadata().getType(); + Class type = command.getParent().getType(); if (ConstraintInspector.requiresProject(type) && (currentProject == null)) { throw new NoProjectException( diff --git a/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ListCommandsPlugin.java b/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ListCommandsPlugin.java index 91860502aa..9022a407ec 100644 --- a/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ListCommandsPlugin.java +++ b/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ListCommandsPlugin.java @@ -184,7 +184,7 @@ private static String render(final boolean showAll, final ClassLincoln Baxter, III */ @RunWith(Arquillian.class) -public class ShellPromptTest extends AbstractShellTest { - @Test - public void testPromptBoolean() throws Exception { - queueInputLines("y"); - assertTrue(getShell().promptBoolean("Would you like cake?")); - - queueInputLines("yes"); - assertTrue(getShell().promptBoolean("Would you like cake?")); - - queueInputLines("n"); - assertFalse(getShell().promptBoolean("Would you like cake?")); - - queueInputLines("no"); - assertFalse(getShell().promptBoolean("Would you like cake?")); - } - - @Test - public void testPromptBooleanDefaultsToYes() throws Exception { - queueInputLines(""); - assertTrue(getShell().promptBoolean("Would you like cake?")); - } - - @Test - public void testPromptBooleanLoopsIfBadInput() throws Exception { - queueInputLines("asdfdsf\n \n"); - assertFalse(getShell().promptBoolean("Would you like cake?", false)); - - queueInputLines("asdfdsf\n n\n"); - assertFalse(getShell().promptBoolean("Would you like cake?", false)); - - queueInputLines("asdfdsf\n y\n"); - } - - @Test - public void testPromptChoiceList() throws Exception { - List choices = Arrays.asList("blue", "green", "red", "yellow"); - - queueInputLines("foo", "2"); - int choice = getShell().promptChoice("What is your favorite color?", choices); - assertEquals(1, choice); - } - - @Test(expected = IllegalArgumentException.class) - public void testPromptChoiceListEmpty() throws Exception { - List choices = Arrays.asList(); - getShell().promptChoice("What is your favorite color?", choices); - fail(); - } - - @Test(expected = IllegalArgumentException.class) - public void testPromptChoiceListNull() throws Exception { - List choices = null; - getShell().promptChoice("What is your favorite color?", choices); - fail(); - } - - @Test - public void testPromptChoiceListTyped() throws Exception { - List choices = Arrays.asList("blue", "green", "red", "yellow"); - - queueInputLines("foo", "2"); - String choice = getShell().promptChoiceTyped("What is your favorite color?", choices); - assertEquals(choices.get(1), choice); - } - - @Test - public void testPromptChoiceListTypedDefault() throws Exception { - List choices = Arrays.asList("blue", "green", "red", "yellow"); - - queueInputLines("foo", ""); - String choice = getShell().promptChoiceTyped("What is your favorite color?", choices, "yellow"); - assertEquals(choices.get(3), choice); - } - - @Test(expected = IllegalArgumentException.class) - public void testPromptChoiceTypedListEmpty() throws Exception { - List choices = Arrays.asList(); - getShell().promptChoiceTyped("What is your favorite color?", choices); - fail(); - } - - @Test(expected = IllegalArgumentException.class) - public void testPromptChoiceTypedListNull() throws Exception { - List choices = null; - getShell().promptChoiceTyped("What is your favorite color?", choices); - fail(); - } - - @Test - public void testPromptChoiceMapByIndex() throws Exception { - Map options = new HashMap(); - options.put("blue", "option1"); - options.put("green", "option2"); - options.put("red", "option3"); - - queueInputLines("2"); - String choice = getShell().promptChoice("What is your favorite color?", options); - assertEquals("option1", choice); - } - - @Test - public void testPromptChoiceMapByIndexSingleItem() throws Exception { - Map options = new HashMap(); - options.put("blue", "option1"); - - queueInputLines("1"); - String choice = getShell().promptChoice("What is your favorite color?", options); - assertEquals("option1", choice); - } - - @Test - public void testPromptChoiceMapByName() throws Exception { - Map options = new HashMap(); - options.put("blue", "option1"); - options.put("green", "option2"); - options.put("red", "option3"); - - queueInputLines("green"); - String choice = getShell().promptChoice("What is your favorite color?", options); - assertEquals("option2", choice); - } - - @Test - public void testPromptChoiceMapLoopsIfNonExistingIndex() throws Exception { - Map options = new HashMap(); - options.put("blue", "option1"); - options.put("green", "option2"); - options.put("red", "option3"); - - queueInputLines("5", "2"); - String choice = getShell().promptChoice("What is your favorite color?", options); - assertEquals("option1", choice); - } - - @Test - public void testPromptChoiceMapLoopsInvalidInput() throws Exception { - Map options = new HashMap(); - options.put("blue", "option1"); - options.put("green", "option2"); - options.put("red", "option3"); - - queueInputLines("bla", "2"); - String choice = getShell().promptChoice("What is your favorite color?", options); - assertEquals("option1", choice); - } - - @Test - public void testPromptEnum() throws Exception { - queueInputLines("BAR"); - assertEquals(MockEnum.BAR, getShell().promptEnum("Enummy?", MockEnum.class)); - } - - @Test(expected = IllegalStateException.class) - public void testPromptEnumFallbackToListAsksForChoice() throws Exception { - queueInputLines(""); - getShell().promptEnum("Enummy?", MockEnum.class); - fail(); - } - - @Test - public void testPromptEnumFallbackToList() throws Exception { - queueInputLines("not-a-value", "2"); - assertEquals(MockEnum.BAR, getShell().promptEnum("Enummy?", MockEnum.class)); - - queueInputLines("not-a-value", "", "", "", "3"); - assertEquals(MockEnum.BAZ, getShell().promptEnum("Enummy?", MockEnum.class)); - - queueInputLines("not-a-value", "4"); - assertEquals(MockEnum.CAT, getShell().promptEnum("Enummy?", MockEnum.class)); - } - - @Test - public void testPromptEnumDefault() throws Exception { - queueInputLines(""); - assertEquals(MockEnum.CAT, getShell().promptEnum("Enummy?", MockEnum.class, MockEnum.CAT)); - - queueInputLines(""); - assertEquals(MockEnum.CAT, getShell().promptEnum("Enummy?", MockEnum.class, MockEnum.CAT)); - } - - @Test - public void testPromptEnumDefaultFallbackToList() throws Exception { - queueInputLines("not-a-value", ""); - assertEquals(MockEnum.BAR, getShell().promptEnum("Enummy?", MockEnum.class, MockEnum.BAR)); - } - - @Test - public void testPromptEnumDefaultFallbackToListWithDefault() throws Exception { - queueInputLines("not-a-value", "eeee", "aaa", ""); - assertEquals(MockEnum.BAR, getShell().promptEnum("Enummy?", MockEnum.class, MockEnum.BAR)); - } +public class ShellPromptTest extends AbstractShellTest +{ + @Test + public void testPromptBoolean() throws Exception + { + queueInputLines("y"); + assertTrue(getShell().promptBoolean("Would you like cake?")); + + queueInputLines("yes"); + assertTrue(getShell().promptBoolean("Would you like cake?")); + + queueInputLines("n"); + assertFalse(getShell().promptBoolean("Would you like cake?")); + + queueInputLines("no"); + assertFalse(getShell().promptBoolean("Would you like cake?")); + } + + @Test + public void testPromptBooleanDefaultsToYes() throws Exception + { + queueInputLines(""); + assertTrue(getShell().promptBoolean("Would you like cake?")); + } + + @Test + public void testPromptBooleanLoopsIfBadInput() throws Exception + { + queueInputLines("asdfdsf\n \n"); + assertFalse(getShell().promptBoolean("Would you like cake?", false)); + + queueInputLines("asdfdsf\n n\n"); + assertFalse(getShell().promptBoolean("Would you like cake?", false)); + + queueInputLines("asdfdsf\n y\n"); + } + + @Test + public void testPromptChoiceList() throws Exception + { + List choices = Arrays.asList("blue", "green", "red", "yellow"); + + queueInputLines("foo", "2"); + int choice = getShell().promptChoice("What is your favorite color?", choices); + assertEquals(1, choice); + } + + @Test(expected = IllegalArgumentException.class) + public void testPromptChoiceListEmpty() throws Exception + { + List choices = Arrays.asList(); + getShell().promptChoice("What is your favorite color?", choices); + fail(); + } + + @Test(expected = IllegalArgumentException.class) + public void testPromptChoiceListNull() throws Exception + { + List choices = null; + getShell().promptChoice("What is your favorite color?", choices); + fail(); + } + + @Test + public void testPromptChoiceListTyped() throws Exception + { + List choices = Arrays.asList("blue", "green", "red", "yellow"); + + queueInputLines("foo", "2"); + String choice = getShell().promptChoiceTyped("What is your favorite color?", choices); + assertEquals(choices.get(1), choice); + } + + @Test + public void testPromptChoiceListTypedDefault() throws Exception + { + List choices = Arrays.asList("blue", "green", "red", "yellow"); + + queueInputLines("foo", ""); + String choice = getShell().promptChoiceTyped("What is your favorite color?", choices, "yellow"); + assertEquals(choices.get(3), choice); + } + + @Test(expected = IllegalArgumentException.class) + public void testPromptChoiceTypedListEmpty() throws Exception + { + List choices = Arrays.asList(); + getShell().promptChoiceTyped("What is your favorite color?", choices); + fail(); + } + + @Test(expected = IllegalArgumentException.class) + public void testPromptChoiceTypedListNull() throws Exception + { + List choices = null; + getShell().promptChoiceTyped("What is your favorite color?", choices); + fail(); + } + + @Test + public void testPromptChoiceMapByIndex() throws Exception + { + Map options = new HashMap(); + options.put("blue", "option1"); + options.put("green", "option2"); + options.put("red", "option3"); + + queueInputLines("2"); + String choice = getShell().promptChoice("What is your favorite color?", options); + assertEquals("option1", choice); + } + + @Test + public void testPromptChoiceMapByIndexSingleItem() throws Exception + { + Map options = new HashMap(); + options.put("blue", "option1"); + + queueInputLines("1"); + String choice = getShell().promptChoice("What is your favorite color?", options); + assertEquals("option1", choice); + } + + @Test + public void testPromptChoiceMapByName() throws Exception + { + Map options = new HashMap(); + options.put("blue", "option1"); + options.put("green", "option2"); + options.put("red", "option3"); + + queueInputLines("green"); + String choice = getShell().promptChoice("What is your favorite color?", options); + assertEquals("option2", choice); + } + + @Test + public void testPromptChoiceMapLoopsIfNonExistingIndex() throws Exception + { + Map options = new HashMap(); + options.put("blue", "option1"); + options.put("green", "option2"); + options.put("red", "option3"); + + queueInputLines("5", "2"); + String choice = getShell().promptChoice("What is your favorite color?", options); + assertEquals("option1", choice); + } + + @Test + public void testPromptChoiceMapLoopsInvalidInput() throws Exception + { + Map options = new HashMap(); + options.put("blue", "option1"); + options.put("green", "option2"); + options.put("red", "option3"); + + queueInputLines("bla", "2"); + String choice = getShell().promptChoice("What is your favorite color?", options); + assertEquals("option1", choice); + } + + @Test + public void testPromptEnum() throws Exception + { + queueInputLines("BAR"); + assertEquals(MockEnum.BAR, getShell().promptEnum("Enummy?", MockEnum.class)); + } + + @Test(expected = IllegalStateException.class) + public void testPromptEnumFallbackToListAsksForChoice() throws Exception + { + queueInputLines(""); + getShell().promptEnum("Enummy?", MockEnum.class); + fail(); + } + + @Test + public void testPromptEnumFallbackToList() throws Exception + { + queueInputLines("not-a-value", "2"); + assertEquals(MockEnum.BAR, getShell().promptEnum("Enummy?", MockEnum.class)); + + queueInputLines("not-a-value", "", "", "", "3"); + assertEquals(MockEnum.BAZ, getShell().promptEnum("Enummy?", MockEnum.class)); + + queueInputLines("not-a-value", "4"); + assertEquals(MockEnum.CAT, getShell().promptEnum("Enummy?", MockEnum.class)); + } + + @Test + public void testPromptEnumDefault() throws Exception + { + queueInputLines(""); + assertEquals(MockEnum.CAT, getShell().promptEnum("Enummy?", MockEnum.class, MockEnum.CAT)); + + queueInputLines(""); + assertEquals(MockEnum.CAT, getShell().promptEnum("Enummy?", MockEnum.class, MockEnum.CAT)); + } + + @Test + public void testPromptEnumDefaultFallbackToList() throws Exception + { + queueInputLines("not-a-value", ""); + assertEquals(MockEnum.BAR, getShell().promptEnum("Enummy?", MockEnum.class, MockEnum.BAR)); + } + + @Test + public void testPromptEnumDefaultFallbackToListWithDefault() throws Exception + { + queueInputLines("not-a-value", "eeee", "aaa", ""); + assertEquals(MockEnum.BAR, getShell().promptEnum("Enummy?", MockEnum.class, MockEnum.BAR)); + } + + @Test + public void testPromptSecret() throws Exception + { + queueInputLines("secret"); + assertEquals("secret", getShell().promptSecret("What's your secret?")); + } } From 45d131d496231415516724f8a5969a93da48e0f1 Mon Sep 17 00:00:00 2001 From: "Lincoln Baxter, III" Date: Fri, 15 Jul 2011 17:03:42 -0400 Subject: [PATCH 04/11] Fix prompt deletion on backspace issue --- .../java/org/jboss/forge/shell/Shell.java | 4 +-- .../forge/shell/AbstractShellPrompt.java | 18 ----------- .../java/org/jboss/forge/shell/ShellImpl.java | 31 ++++++++++++++++++- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/shell-api/src/main/java/org/jboss/forge/shell/Shell.java b/shell-api/src/main/java/org/jboss/forge/shell/Shell.java index 07b16f3541..ce50e866ea 100644 --- a/shell-api/src/main/java/org/jboss/forge/shell/Shell.java +++ b/shell-api/src/main/java/org/jboss/forge/shell/Shell.java @@ -195,11 +195,11 @@ public interface Shell extends ShellPrintWriter, ShellPrompt, ShellHistory /** * Ask the current {@link InputStream} for input, masking keystrokes in the console with the given mask. * - * @param mask The sequence to use for masking input + * @param mask The character to use for masking input * @return any read data as a string, or null if none available. * @throws IOException on error */ - String readLine(String mask) throws IOException; + String readLine(Character mask) throws IOException; /** * Controls the shell's usage of ANSI escape code support. This method does not guarantee ANSI will function diff --git a/shell/src/main/java/org/jboss/forge/shell/AbstractShellPrompt.java b/shell/src/main/java/org/jboss/forge/shell/AbstractShellPrompt.java index 85d1f3996c..1d1f5de59e 100644 --- a/shell/src/main/java/org/jboss/forge/shell/AbstractShellPrompt.java +++ b/shell/src/main/java/org/jboss/forge/shell/AbstractShellPrompt.java @@ -22,7 +22,6 @@ package org.jboss.forge.shell; import java.io.File; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -71,23 +70,6 @@ public String prompt() return prompt(""); } - @Override - public String promptSecret(String message) - { - if (!message.isEmpty() && message.matches("^.*\\S$")) - { - message = message + " "; - } - message = renderColor(ShellColor.CYAN, " ? ") + message; - - try { - return readLine("*"); - } - catch (IOException e) { - throw new RuntimeException(e); - } - } - @Override public String promptAndSwallowCR() { diff --git a/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java b/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java index 5e54934639..26b936aadd 100644 --- a/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java +++ b/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java @@ -613,7 +613,7 @@ public String readLine() throws IOException } @Override - public String readLine(final String mask) throws IOException + public String readLine(final Character mask) throws IOException { String line = null; if (mask != null) @@ -1135,6 +1135,35 @@ public String promptWithCompleter(String message, final Completer tempCompleter) } } + @Override + public String promptSecret(String message) + { + if (!message.isEmpty() && message.matches("^.*\\S$")) + { + message = message + " "; + } + message = renderColor(ShellColor.CYAN, " ? ") + message; + + try + { + reader.removeCompleter(this.completer); + reader.setHistoryEnabled(false); + reader.setPrompt(message); + String line = readLine('*'); + return line; + } + catch (IOException e) + { + throw new IllegalStateException("Shell input stream failure", e); + } + finally + { + reader.addCompleter(this.completer); + reader.setHistoryEnabled(true); + reader.setPrompt(""); + } + } + @Override protected PromptTypeConverter getPromptTypeConverter() { From d4fb0d29b0987e0745aabc498ea7e586a3770c85 Mon Sep 17 00:00:00 2001 From: "Lincoln Baxter, III" Date: Mon, 18 Jul 2011 16:13:57 -0400 Subject: [PATCH 05/11] Plugin repository is now hosted on GitHub for easy updates/pull requests --- pom.xml | 11 +++ .../java/org/jboss/forge/shell/ShellImpl.java | 2 +- .../shell/plugins/builtin/ForgePlugin.java | 74 +++++++++++-------- .../org/jboss/forge/shell/util/PluginRef.java | 19 ++++- .../jboss/forge/shell/util/PluginUtil.java | 14 ++-- 5 files changed, 79 insertions(+), 41 deletions(-) diff --git a/pom.xml b/pom.xml index 802e21a5ad..b621f249cd 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,7 @@ 1.7.5 3.0.0.Beta4 1.0.0.Final + 1.0.1.GA 4.8.1 1.2.16 1.0.0-alpha-11 @@ -93,6 +94,11 @@ pom + + org.jboss.forge + forge-distribution + ${project.version} + org.jboss.forge forge-event-bus @@ -179,6 +185,11 @@ ${project.version} + + org.jboss.modules + jboss-modules + ${jboss.modules.version} + org.jboss.weld.se weld-se-core diff --git a/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java b/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java index 26b936aadd..9048ded195 100644 --- a/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java +++ b/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java @@ -109,7 +109,7 @@ public class ShellImpl extends AbstractShellPrompt implements Shell static final String DEFAULT_PROMPT_NO_PROJ = "[\\c{red}no project\\c] \\c{blue}\\W\\c \\c{red}\\$\\c "; static final String PROP_DEFAULT_PLUGIN_REPO = "DEFFAULT_PLUGIN_REPO"; - static final String DEFAULT_PLUGIN_REPO = "http://seamframework.org/service/File/148617"; + static final String DEFAULT_PLUGIN_REPO = "https://raw.github.com/forge/plugin-repository/master/repository.yaml"; static final String PROP_VERBOSE = "VERBOSE"; diff --git a/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java b/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java index 1185ca5bf2..ef10a658ca 100644 --- a/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java +++ b/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java @@ -86,8 +86,9 @@ public class ForgePlugin implements Plugin private final Shell shell; @Inject - public ForgePlugin(ForgeEnvironment environment, Event reinitializeEvent, - ShellPrintWriter writer, ShellPrompt prompt, DependencyResolver resolver, Shell shell) + public ForgePlugin(final ForgeEnvironment environment, final Event reinitializeEvent, + final ShellPrintWriter writer, final ShellPrompt prompt, final DependencyResolver resolver, + final Shell shell) { this.environment = environment; this.reinitializeEvent = reinitializeEvent; @@ -102,7 +103,7 @@ public ForgePlugin(ForgeEnvironment environment, Event */ @DefaultCommand - public void about(PipeOut out) + public void about(final PipeOut out) { out.println(" ____ _____ "); out.println(" / ___| ___ __ _ _ __ ___ | ___|__ _ __ __ _ ___ "); @@ -128,7 +129,7 @@ public void listInstalled( @Option(name = "all", shortName = "a", description = "Show extra information about each installed plugin", - defaultValue = "false") boolean showAll) + defaultValue = "false") final boolean showAll) { DirectoryResource pluginDir = environment.getPluginDirectory(); List> list = pluginDir.listResources(); @@ -210,21 +211,30 @@ public void listInstalled( @Command(value = "find-plugin", help = "Searches the configured Forge plugin index for a plugin matching the given search text") - public void find(@Option(description = "search string") String searchString, final PipeOut out) throws Exception + public void find(@Option(description = "search string") final String searchString, final PipeOut out) + throws Exception { // TODO remove this message once stabilized. ShellMessages.info(out, "This is a prototype feature and has limited functionality."); List pluginList = PluginUtil.findPlugin(environment, searchString, out); + if (!pluginList.isEmpty()) + { + out.println(); + } for (PluginRef ref : pluginList) { out.println(" - " + out.renderColor(ShellColor.BOLD, ref.getName()) + " (" + ref.getArtifact() + ")"); + out.println("\tAuthor: " + ref.getAuthor()); + out.println("\tDescription: " + ref.getDescription()); + out.println("\tLocation: " + ref.getLocation()); + out.println(); } } @Command(value = "install-plugin", help = "Installs a plugin from the configured Forge plugin index") - public void installFromIndex(@Option(description = "plugin-name") String pluginName, + public void installFromIndex(@Option(description = "plugin-name") final String pluginName, final PipeOut out) throws Exception { // TODO remove this message once stabilized. @@ -255,13 +265,13 @@ else if (ref.isGit()) } } - private void installFromMvnRepos(Dependency dep, PipeOut out, final DependencyRepository... repoList) + private void installFromMvnRepos(final Dependency dep, final PipeOut out, final DependencyRepository... repoList) throws Exception { installFromMvnRepos(dep, out, Arrays.asList(repoList)); } - private void installFromMvnRepos(Dependency dep, PipeOut out, final List repoList) + private void installFromMvnRepos(final Dependency dep, final PipeOut out, final List repoList) throws Exception { List temp = resolver.resolveArtifacts(dep, repoList); @@ -297,9 +307,9 @@ else if (artifacts.size() > 1) @Command(value = "mvn-plugin", help = "Download and install a plugin from a maven repository") - public void installFromMvnRepos(@Option(description = "plugin-identifier", required = true) Dependency dep, - @Option(name = "knownRepo", description = "target repository") KnownRepository repo, - @Option(name = "repoUrl", description = "target repository URL") String repoURL, + public void installFromMvnRepos(@Option(description = "plugin-identifier", required = true) final Dependency dep, + @Option(name = "knownRepo", description = "target repository") final KnownRepository repo, + @Option(name = "repoUrl", description = "target repository URL") final String repoURL, final PipeOut out) throws Exception { if (repoURL != null) @@ -323,12 +333,12 @@ else if (repo == null) @Command(value = "jar-plugin", help = "Install a plugin from a local project folder") public void installFromLocalJar( - @Option(name = "jar", description = "jar file to install", required = true) Resource resource, - @Option(name = "id", description = "plugin identifier, [e.g. \"com.example.group : example-plugin\"]", required = true) Dependency dep, + @Option(name = "jar", description = "jar file to install", required = true) final Resource resource, + @Option(name = "id", description = "plugin identifier, [e.g. \"com.example.group : example-plugin\"]", required = true) final Dependency dep, final PipeOut out) throws Exception { FileResource source = resource.reify(FileResource.class); - if (source == null || !source.exists()) + if ((source == null) || !source.exists()) { throw new IllegalArgumentException("JAR file must be specified."); } @@ -355,8 +365,8 @@ public void installFromLocalJar( @Command(value = "url-plugin", help = "Download and install a plugin from the given URL") public void installFromRemoteURL( - @Option(description = "URL of jar file", required = true) URL url, - @Option(name = "id", description = "plugin identifier, [e.g. \"com.example.group : example-plugin\"]", required = true) Dependency dep, + @Option(description = "URL of jar file", required = true) final URL url, + @Option(name = "id", description = "plugin identifier, [e.g. \"com.example.group : example-plugin\"]", required = true) final Dependency dep, final PipeOut out) throws Exception { ShellMessages.info(out, "WARNING!"); @@ -375,11 +385,11 @@ public void installFromRemoteURL( @Command(value = "source-plugin", help = "Install a plugin from a local project folder") public void installFromLocalProject( - @Option(description = "project directory", required = true) Resource projectFolder, + @Option(description = "project directory", required = true) final Resource projectFolder, final PipeOut out) throws Exception { DirectoryResource workspace = projectFolder.reify(DirectoryResource.class); - if (workspace == null || !workspace.exists()) + if ((workspace == null) || !workspace.exists()) { throw new IllegalArgumentException("Project folder must be specified."); } @@ -393,9 +403,9 @@ public void installFromLocalProject( @Command(value = "git-plugin", help = "Install a plugin from a public git repository") public void installFromGit( - @Option(description = "git repo", required = true) String gitRepo, - @Option(name = "ref", description = "branch or tag to build") String ref, - @Option(name = "checkoutDir", description = "directory in which to clone the repository") Resource checkoutDir, + @Option(description = "git repo", required = true) final String gitRepo, + @Option(name = "ref", description = "branch or tag to build") final String ref, + @Option(name = "checkoutDir", description = "directory in which to clone the repository") final Resource checkoutDir, final PipeOut out) throws Exception { @@ -407,7 +417,7 @@ public void installFromGit( DirectoryResource buildDir = workspace.getChildDirectory("repo"); if (checkoutDir != null) { - if (!checkoutDir.exists() && checkoutDir instanceof FileResource) + if (!checkoutDir.exists() && (checkoutDir instanceof FileResource)) { ((FileResource) checkoutDir).mkdirs(); } @@ -451,7 +461,7 @@ public void installFromGit( /* * Helpers */ - private void buildFromCurrentProject(final PipeOut out, DirectoryResource buildDir) throws Abort + private void buildFromCurrentProject(final PipeOut out, final DirectoryResource buildDir) throws Abort { DirectoryResource savedLocation = shell.getCurrentDirectory(); try @@ -465,7 +475,7 @@ private void buildFromCurrentProject(final PipeOut out, DirectoryResource buildD } DependencyFacet deps = project.getFacet(DependencyFacet.class); - if (!deps.hasDependency(DependencyBuilder.create("org.jboss.forge:forge-shell-api")) + if (!deps.hasDependency(DependencyBuilder.create("org.jboss.forge:forge-shell-api")) && !prompt.promptBoolean("The project does not appear to be a Forge Plugin Project, install anyway?", false)) { @@ -474,7 +484,7 @@ private void buildFromCurrentProject(final PipeOut out, DirectoryResource buildD ShellMessages.info(out, "Invoking build with underlying build system."); Resource artifact = project.getFacet(PackagingFacet.class).executeBuild(); - if (artifact != null && artifact.exists()) + if ((artifact != null) && artifact.exists()) { MetadataFacet meta = project.getFacet(MetadataFacet.class); Dependency dep = meta.getOutputDependency(); @@ -487,7 +497,7 @@ private void buildFromCurrentProject(final PipeOut out, DirectoryResource buildD else { throw new IllegalStateException("Build artifact [" + artifact.getFullyQualifiedName() - + "] is missing and cannot be installed. Please resolve build errors and try again."); + + "] is missing and cannot be installed. Please resolve build errors and try again."); } } finally @@ -496,15 +506,15 @@ private void buildFromCurrentProject(final PipeOut out, DirectoryResource buildD } } - private FileResource createIncrementedPluginJarFile(Dependency dep) + private FileResource createIncrementedPluginJarFile(final Dependency dep) { int version = 0; PluginJar pluginJar = new PluginJar(dep); DirectoryResource pluginDir = environment.getPluginDirectory(); List> list = pluginDir.listResources(new StartsWith(pluginJar.getName())); - if (list.size() > 0 && !prompt.promptBoolean( - "An existing version of this plugin was found. Replace it?", true)) + if ((list.size() > 0) && !prompt.promptBoolean( + "An existing version of this plugin was found. Replace it?", true)) { throw new RuntimeException("Aborted."); } @@ -530,15 +540,15 @@ private class StartsWith implements ResourceFilter { private final String prefix; - public StartsWith(String prefix) + public StartsWith(final String prefix) { this.prefix = prefix; } @Override - public boolean accept(Resource resource) + public boolean accept(final Resource resource) { - return resource != null && resource.getName() != null && resource.getName().startsWith(prefix); + return (resource != null) && (resource.getName() != null) && resource.getName().startsWith(prefix); } } diff --git a/shell/src/main/java/org/jboss/forge/shell/util/PluginRef.java b/shell/src/main/java/org/jboss/forge/shell/util/PluginRef.java index 109c9e7e88..34b7fe0d26 100644 --- a/shell/src/main/java/org/jboss/forge/shell/util/PluginRef.java +++ b/shell/src/main/java/org/jboss/forge/shell/util/PluginRef.java @@ -40,8 +40,9 @@ public class PluginRef private final String homeRepo; private final String gitRef; - public PluginRef(String name, String author, String description, String artifact, String homeRepo, String gitRepo, - String gitRef) + public PluginRef(final String name, final String author, final String description, final String artifact, + final String homeRepo, final String gitRepo, + final String gitRef) { this.name = name; this.author = author; @@ -91,4 +92,18 @@ public boolean isGit() { return !Strings.isNullOrEmpty(gitRepo); } + + public String getLocation() + { + String location = getHomeRepo(); + if (Strings.isNullOrEmpty(location)) + { + location = getGitRepo(); + } + if (Strings.isNullOrEmpty(location)) + { + location = "Unknown"; + } + return location; + } } diff --git a/shell/src/main/java/org/jboss/forge/shell/util/PluginUtil.java b/shell/src/main/java/org/jboss/forge/shell/util/PluginUtil.java index 477675607a..8272819d13 100644 --- a/shell/src/main/java/org/jboss/forge/shell/util/PluginUtil.java +++ b/shell/src/main/java/org/jboss/forge/shell/util/PluginUtil.java @@ -51,7 +51,7 @@ public class PluginUtil private static final String PROP_NAME = "name"; private static final Object PROP_GIT_REF = "gitref"; - private static String getDefaultRepo(ForgeEnvironment environment) + private static String getDefaultRepo(final ForgeEnvironment environment) { String defaultRepo = (String) environment.getProperty("DEFFAULT_PLUGIN_REPO"); if (defaultRepo == null) @@ -62,7 +62,8 @@ private static String getDefaultRepo(ForgeEnvironment environment) } @SuppressWarnings("unchecked") - public static List findPlugin(ForgeEnvironment environment, String searchString, PipeOut out) + public static List findPlugin(final ForgeEnvironment environment, final String searchString, + final PipeOut out) throws Exception { String defaultRepo = getDefaultRepo(environment); @@ -91,6 +92,7 @@ public static List findPlugin(ForgeEnvironment environment, String se List pluginList = new ArrayList(); Yaml yaml = new Yaml(); + // TODO this needs to be cached instead of downloaded each time for (Object o : yaml.loadAll(httpResponse.getEntity().getContent())) { if (o == null) @@ -99,11 +101,11 @@ public static List findPlugin(ForgeEnvironment environment, String se } Map map = (Map) o; - String name = map.get(PROP_NAME); - if (pattern.matcher(name).matches()) + PluginRef ref = bindToPuginRef(map); + if (pattern.matcher(ref.getName()).matches() || pattern.matcher(ref.getDescription()).matches()) { - pluginList.add(bindToPuginRef(map)); + pluginList.add(ref); } } @@ -137,7 +139,7 @@ public static void downloadFromURL(final PipeOut out, final URL url, final FileR } } - private static PluginRef bindToPuginRef(Map map) + private static PluginRef bindToPuginRef(final Map map) { return new PluginRef(map.get(PROP_NAME), map.get(PROP_AUTHOR), From 4bf205e8386613f285f96c0454dcfcf3715ae869 Mon Sep 17 00:00:00 2001 From: "Lincoln Baxter, III" Date: Mon, 18 Jul 2011 16:31:09 -0400 Subject: [PATCH 06/11] Removed outdated info message --- .../java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java b/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java index ef10a658ca..10937b33b8 100644 --- a/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java +++ b/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java @@ -214,8 +214,6 @@ public void listInstalled( public void find(@Option(description = "search string") final String searchString, final PipeOut out) throws Exception { - // TODO remove this message once stabilized. - ShellMessages.info(out, "This is a prototype feature and has limited functionality."); List pluginList = PluginUtil.findPlugin(environment, searchString, out); if (!pluginList.isEmpty()) From 3bef774aad2173633e1688366a89e6d9a7e286d5 Mon Sep 17 00:00:00 2001 From: "Lincoln Baxter, III" Date: Mon, 18 Jul 2011 17:08:21 -0400 Subject: [PATCH 07/11] Added website --- .../shell/plugins/builtin/ForgePlugin.java | 3 +- .../org/jboss/forge/shell/util/PluginRef.java | 34 ++++++++++++------- .../jboss/forge/shell/util/PluginUtil.java | 2 ++ 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java b/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java index 10937b33b8..e71b024c31 100644 --- a/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java +++ b/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java @@ -224,8 +224,9 @@ public void find(@Option(description = "search string") final String searchStrin { out.println(" - " + out.renderColor(ShellColor.BOLD, ref.getName()) + " (" + ref.getArtifact() + ")"); out.println("\tAuthor: " + ref.getAuthor()); - out.println("\tDescription: " + ref.getDescription()); + out.println("\tWebsite: " + ref.getWebsite()); out.println("\tLocation: " + ref.getLocation()); + out.println("\tDescription: " + ref.getDescription()); out.println(); } } diff --git a/shell/src/main/java/org/jboss/forge/shell/util/PluginRef.java b/shell/src/main/java/org/jboss/forge/shell/util/PluginRef.java index 34b7fe0d26..097fe1195b 100644 --- a/shell/src/main/java/org/jboss/forge/shell/util/PluginRef.java +++ b/shell/src/main/java/org/jboss/forge/shell/util/PluginRef.java @@ -32,19 +32,22 @@ */ public class PluginRef { - private final String name; - private final String author; - private final String description; - private final String artifact; - private final String gitRepo; - private final String homeRepo; - private final String gitRef; + private String name = ""; + private String website = ""; + private String author = ""; + private String description = ""; + private String artifact = ""; + private String gitRepo = ""; + private String homeRepo = ""; + private String gitRef = ""; - public PluginRef(final String name, final String author, final String description, final String artifact, + public PluginRef(final String name, final String website, final String author, final String description, + final String artifact, final String homeRepo, final String gitRepo, final String gitRef) { this.name = name; + this.website = website; this.author = author; this.description = description; this.artifact = artifact; @@ -60,17 +63,17 @@ public String getGitRef() public String getName() { - return name; + return name == null ? "" : name; } public String getAuthor() { - return author; + return author == null ? "" : author; } public String getDescription() { - return description; + return description == null ? "" : description; } public Dependency getArtifact() @@ -80,12 +83,12 @@ public Dependency getArtifact() public String getHomeRepo() { - return homeRepo; + return homeRepo == null ? "" : homeRepo; } public String getGitRepo() { - return gitRepo; + return gitRepo == null ? "" : website; } public boolean isGit() @@ -93,6 +96,11 @@ public boolean isGit() return !Strings.isNullOrEmpty(gitRepo); } + public String getWebsite() + { + return website == null ? "" : website; + } + public String getLocation() { String location = getHomeRepo(); diff --git a/shell/src/main/java/org/jboss/forge/shell/util/PluginUtil.java b/shell/src/main/java/org/jboss/forge/shell/util/PluginUtil.java index 8272819d13..1334e44155 100644 --- a/shell/src/main/java/org/jboss/forge/shell/util/PluginUtil.java +++ b/shell/src/main/java/org/jboss/forge/shell/util/PluginUtil.java @@ -49,6 +49,7 @@ public class PluginUtil private static final String PROP_DESCRIPTION = "description"; private static final String PROP_AUTHOR = "author"; private static final String PROP_NAME = "name"; + private static final String PROP_WEBSITE = "website"; private static final Object PROP_GIT_REF = "gitref"; private static String getDefaultRepo(final ForgeEnvironment environment) @@ -142,6 +143,7 @@ public static void downloadFromURL(final PipeOut out, final URL url, final FileR private static PluginRef bindToPuginRef(final Map map) { return new PluginRef(map.get(PROP_NAME), + map.get(PROP_WEBSITE), map.get(PROP_AUTHOR), map.get(PROP_DESCRIPTION), map.get(PROP_ARTIFACT), From f2cd029e4a710c030e468f3d93f56623b60ac918 Mon Sep 17 00:00:00 2001 From: "Lincoln Baxter, III" Date: Mon, 18 Jul 2011 17:28:01 -0400 Subject: [PATCH 08/11] Fixed location --- .../shell/plugins/builtin/ForgePlugin.java | 1 + .../org/jboss/forge/shell/util/PluginRef.java | 68 ++++++++++++++----- .../jboss/forge/shell/util/PluginUtil.java | 25 ++++--- 3 files changed, 68 insertions(+), 26 deletions(-) diff --git a/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java b/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java index e71b024c31..47d027044b 100644 --- a/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java +++ b/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/ForgePlugin.java @@ -226,6 +226,7 @@ public void find(@Option(description = "search string") final String searchStrin out.println("\tAuthor: " + ref.getAuthor()); out.println("\tWebsite: " + ref.getWebsite()); out.println("\tLocation: " + ref.getLocation()); + out.println("\tTags: " + ref.getTags()); out.println("\tDescription: " + ref.getDescription()); out.println(); } diff --git a/shell/src/main/java/org/jboss/forge/shell/util/PluginRef.java b/shell/src/main/java/org/jboss/forge/shell/util/PluginRef.java index 097fe1195b..57ab7245a2 100644 --- a/shell/src/main/java/org/jboss/forge/shell/util/PluginRef.java +++ b/shell/src/main/java/org/jboss/forge/shell/util/PluginRef.java @@ -36,26 +36,12 @@ public class PluginRef private String website = ""; private String author = ""; private String description = ""; + private String tags = ""; private String artifact = ""; private String gitRepo = ""; private String homeRepo = ""; private String gitRef = ""; - public PluginRef(final String name, final String website, final String author, final String description, - final String artifact, - final String homeRepo, final String gitRepo, - final String gitRef) - { - this.name = name; - this.website = website; - this.author = author; - this.description = description; - this.artifact = artifact; - this.homeRepo = homeRepo; - this.gitRepo = gitRepo; - this.gitRef = gitRef; - } - public String getGitRef() { return gitRef; @@ -76,6 +62,11 @@ public String getDescription() return description == null ? "" : description; } + public String getTags() + { + return tags == null ? "" : tags; + } + public Dependency getArtifact() { return DependencyBuilder.create(artifact); @@ -88,7 +79,7 @@ public String getHomeRepo() public String getGitRepo() { - return gitRepo == null ? "" : website; + return gitRepo == null ? "" : gitRepo; } public boolean isGit() @@ -114,4 +105,49 @@ public String getLocation() } return location; } + + public void setName(final String name) + { + this.name = name; + } + + public void setWebsite(final String website) + { + this.website = website; + } + + public void setAuthor(final String author) + { + this.author = author; + } + + public void setDescription(final String description) + { + this.description = description; + } + + public void setTags(final String tags) + { + this.tags = tags; + } + + public void setArtifact(final String artifact) + { + this.artifact = artifact; + } + + public void setGitRepo(final String gitRepo) + { + this.gitRepo = gitRepo; + } + + public void setHomeRepo(final String homeRepo) + { + this.homeRepo = homeRepo; + } + + public void setGitRef(final String gitRef) + { + this.gitRef = gitRef; + } } diff --git a/shell/src/main/java/org/jboss/forge/shell/util/PluginUtil.java b/shell/src/main/java/org/jboss/forge/shell/util/PluginUtil.java index 1334e44155..4ad897482e 100644 --- a/shell/src/main/java/org/jboss/forge/shell/util/PluginUtil.java +++ b/shell/src/main/java/org/jboss/forge/shell/util/PluginUtil.java @@ -50,7 +50,8 @@ public class PluginUtil private static final String PROP_AUTHOR = "author"; private static final String PROP_NAME = "name"; private static final String PROP_WEBSITE = "website"; - private static final Object PROP_GIT_REF = "gitref"; + private static final String PROP_GIT_REF = "gitref"; + private static final String PROP_TAGS = "tags"; private static String getDefaultRepo(final ForgeEnvironment environment) { @@ -104,7 +105,8 @@ public static List findPlugin(final ForgeEnvironment environment, fin Map map = (Map) o; PluginRef ref = bindToPuginRef(map); - if (pattern.matcher(ref.getName()).matches() || pattern.matcher(ref.getDescription()).matches()) + if (pattern.matcher(ref.getName()).matches() || pattern.matcher(ref.getDescription()).matches() + || pattern.matcher(ref.getTags()).matches()) { pluginList.add(ref); } @@ -142,13 +144,16 @@ public static void downloadFromURL(final PipeOut out, final URL url, final FileR private static PluginRef bindToPuginRef(final Map map) { - return new PluginRef(map.get(PROP_NAME), - map.get(PROP_WEBSITE), - map.get(PROP_AUTHOR), - map.get(PROP_DESCRIPTION), - map.get(PROP_ARTIFACT), - map.get(PROP_HOME_MAVEN_REPO), - map.get(PROP_GIT_REPOSITORY), - map.get(PROP_GIT_REF)); + PluginRef ref = new PluginRef(); + ref.setName(map.get(PROP_NAME)); + ref.setWebsite(map.get(PROP_WEBSITE)); + ref.setArtifact(map.get(PROP_ARTIFACT)); + ref.setAuthor(map.get(PROP_AUTHOR)); + ref.setDescription(map.get(PROP_DESCRIPTION)); + ref.setTags(map.get(PROP_TAGS)); + ref.setHomeRepo(map.get(PROP_HOME_MAVEN_REPO)); + ref.setGitRepo(map.get(PROP_GIT_REPOSITORY)); + ref.setGitRef(map.get(PROP_GIT_REF)); + return ref; } } From 930b78c6c278fe8ef871721c1e333688898ad33b Mon Sep 17 00:00:00 2001 From: "Lincoln Baxter, III" Date: Mon, 18 Jul 2011 17:40:35 -0400 Subject: [PATCH 09/11] Added error message for when completers cannot be instantiated --- .../OptionValueResolverCompleter.java | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/shell/src/main/java/org/jboss/forge/shell/completer/OptionValueResolverCompleter.java b/shell/src/main/java/org/jboss/forge/shell/completer/OptionValueResolverCompleter.java index 31f0d6e4bb..0f4ec106f1 100644 --- a/shell/src/main/java/org/jboss/forge/shell/completer/OptionValueResolverCompleter.java +++ b/shell/src/main/java/org/jboss/forge/shell/completer/OptionValueResolverCompleter.java @@ -1,5 +1,12 @@ package org.jboss.forge.shell.completer; +import java.io.File; +import java.util.ArrayList; +import java.util.Map; + +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; + import org.jboss.forge.project.Project; import org.jboss.forge.project.facets.JavaSourceFacet; import org.jboss.forge.project.services.ResourceFactory; @@ -12,18 +19,10 @@ import org.jboss.forge.shell.Shell; import org.jboss.forge.shell.command.OptionMetadata; import org.jboss.forge.shell.command.parser.CommandParserContext; -import org.jboss.forge.shell.completer.CommandCompleter; -import org.jboss.forge.shell.completer.CommandCompleterState; import org.jboss.forge.shell.util.BeanManagerUtils; import org.jboss.forge.shell.util.JavaPathspecParser; import org.jboss.forge.shell.util.PathspecParser; -import javax.enterprise.inject.spi.BeanManager; -import javax.inject.Inject; -import java.io.File; -import java.util.ArrayList; -import java.util.Map; - public class OptionValueResolverCompleter implements CommandCompleter { @@ -51,6 +50,12 @@ public void complete(final CommandCompleterState st) if (option.hasCustomCompleter()) { CommandCompleter completer = BeanManagerUtils.getContextualInstance(manager, option.getCompleterType()); + if (completer == null) + { + throw new RuntimeException("Could not instantiate completer of type: " + + option.getCompleterType().getName() + + ", completers must be valid CDI beans (public top-level classes.)"); + } completer.complete(state); } else if (option.isEnum()) @@ -64,9 +69,9 @@ else if (isJavaResourceAssignable(option)) completeJavaPaths(state, option, valueMap, new ResourceFilter() { @Override - public boolean accept(Resource resource) + public boolean accept(final Resource resource) { - return (resource instanceof DirectoryResource || resource instanceof JavaResource); + return ((resource instanceof DirectoryResource) || (resource instanceof JavaResource)); } }); } @@ -75,7 +80,7 @@ else if (isJavaPackageAssignable(option)) completeJavaPaths(state, option, valueMap, new ResourceFilter() { @Override - public boolean accept(Resource resource) + public boolean accept(final Resource resource) { return (resource instanceof DirectoryResource); } @@ -89,11 +94,11 @@ else if (isFileResourceAssignable(option)) } } - private void completeJavaPaths(PluginCommandCompleterState state, OptionMetadata option, - Map valueMap, ResourceFilter filter) + private void completeJavaPaths(final PluginCommandCompleterState state, final OptionMetadata option, + final Map valueMap, final ResourceFilter filter) { Project project = shell.getCurrentProject(); - if (project != null && project.hasFacet(JavaSourceFacet.class)) + if ((project != null) && project.hasFacet(JavaSourceFacet.class)) { ArrayList results = new ArrayList(); String[] values; @@ -130,26 +135,26 @@ else if (valueMap.get(option) == null) // the separator char // set the value ahead by 1. int lastNest = val.lastIndexOf("."); - state.setIndex(state.getOriginalIndex() - val.length() + (lastNest != -1 ? lastNest + 1 : 0)); + state.setIndex((state.getOriginalIndex() - val.length()) + (lastNest != -1 ? lastNest + 1 : 0)); state.getCandidates().addAll(results); } } - private boolean isJavaPackageAssignable(OptionMetadata option) + private boolean isJavaPackageAssignable(final OptionMetadata option) { return PromptType.JAVA_PACKAGE.equals(option.getPromptType()); } - private boolean isJavaResourceAssignable(OptionMetadata option) + private boolean isJavaResourceAssignable(final OptionMetadata option) { return JavaResource[].class.isAssignableFrom(option.getBoxedType()) || JavaResource.class.isAssignableFrom(option.getBoxedType()) || PromptType.JAVA_CLASS.equals(option.getPromptType()); } - private void completeFilenames(PluginCommandCompleterState state, OptionMetadata option, - Map valueMap) + private void completeFilenames(final PluginCommandCompleterState state, final OptionMetadata option, + final Map valueMap) { ArrayList results = new ArrayList(); String[] values; @@ -188,7 +193,7 @@ else if (valueMap.get(option) == null) // Record the current index point in the buffer. If we're at // the separator char // set the value ahead by 1. - state.setIndex(state.getOriginalIndex() - val.length() + (lastNest != -1 ? lastNest + 1 : 0)); + state.setIndex((state.getOriginalIndex() - val.length()) + (lastNest != -1 ? lastNest + 1 : 0)); state.getCandidates().addAll(results); } From 300499da1da7acaba3392ab2056bf89802e9589e Mon Sep 17 00:00:00 2001 From: "Lincoln Baxter, III" Date: Tue, 19 Jul 2011 15:58:19 -0400 Subject: [PATCH 10/11] Implemented SEAMFORGE-253 --- ...tStreamInterceptor.java => CommandInterceptor.java} | 6 +++--- .../src/main/java/org/jboss/forge/shell/ShellImpl.java | 10 +++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) rename shell-api/src/main/java/org/jboss/forge/shell/spi/{InputStreamInterceptor.java => CommandInterceptor.java} (87%) diff --git a/shell-api/src/main/java/org/jboss/forge/shell/spi/InputStreamInterceptor.java b/shell-api/src/main/java/org/jboss/forge/shell/spi/CommandInterceptor.java similarity index 87% rename from shell-api/src/main/java/org/jboss/forge/shell/spi/InputStreamInterceptor.java rename to shell-api/src/main/java/org/jboss/forge/shell/spi/CommandInterceptor.java index 69143fe63d..72c21c88ae 100644 --- a/shell-api/src/main/java/org/jboss/forge/shell/spi/InputStreamInterceptor.java +++ b/shell-api/src/main/java/org/jboss/forge/shell/spi/CommandInterceptor.java @@ -27,11 +27,11 @@ * @author Lincoln Baxter, III * */ -public interface InputStreamInterceptor +public interface CommandInterceptor { /** - * Intercepts a line of input and returns it along with any modifications. The returned value will be passed to the - * Shell for invocation. + * Intercepts a command and returns it along with any modifications. The returned value will be passed to the Shell + * for invocation. */ public String intercept(String line); } diff --git a/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java b/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java index 9048ded195..3916a396f3 100644 --- a/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java +++ b/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java @@ -40,6 +40,7 @@ import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Event; import javax.enterprise.event.Observes; +import javax.enterprise.inject.Instance; import javax.enterprise.inject.spi.BeanManager; import javax.inject.Inject; @@ -83,6 +84,7 @@ import org.jboss.forge.shell.exceptions.ShellExecutionException; import org.jboss.forge.shell.plugins.builtin.Echo; import org.jboss.forge.shell.project.CurrentProject; +import org.jboss.forge.shell.spi.CommandInterceptor; import org.jboss.forge.shell.util.Files; import org.jboss.forge.shell.util.GeneralUtils; import org.jboss.forge.shell.util.JavaPathspecParser; @@ -228,6 +230,9 @@ public boolean canConvertFrom(final Class aClass) @Inject private ShellConfig shellConfig; + @Inject + private Instance commandInterceptors; + void init(@Observes final Startup event, final PluginCommandCompleter pluginCompleter) throws Exception { BooleanConverter booleanConverter = new BooleanConverter(); @@ -694,11 +699,14 @@ public void cursorLeft(final int x) } @Override - public void execute(final String line) + public void execute(String line) { try { executing = true; + for (CommandInterceptor interceptor : commandInterceptors) { + line = interceptor.intercept(line); + } fshRuntime.run(line); } catch (Exception e) From c37a15d161b7fe53ac65ff1fd439112eedaf60fd Mon Sep 17 00:00:00 2001 From: "Lincoln Baxter, III" Date: Tue, 19 Jul 2011 16:32:32 -0400 Subject: [PATCH 11/11] Fixed potential for NPE with CommandInterceptor --- .../forge/shell/spi/CommandInterceptor.java | 2 +- .../java/org/jboss/forge/shell/ShellImpl.java | 4 +- .../plugins/builtin/AliasInterceptor.java | 42 +++++++++++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 shell/src/main/java/org/jboss/forge/shell/plugins/builtin/AliasInterceptor.java diff --git a/shell-api/src/main/java/org/jboss/forge/shell/spi/CommandInterceptor.java b/shell-api/src/main/java/org/jboss/forge/shell/spi/CommandInterceptor.java index 72c21c88ae..09fab16624 100644 --- a/shell-api/src/main/java/org/jboss/forge/shell/spi/CommandInterceptor.java +++ b/shell-api/src/main/java/org/jboss/forge/shell/spi/CommandInterceptor.java @@ -31,7 +31,7 @@ public interface CommandInterceptor { /** * Intercepts a command and returns it along with any modifications. The returned value will be passed to the Shell - * for invocation. + * for invocation. If the returned value is null, the shell simply ignores this line and waits for the next input. */ public String intercept(String line); } diff --git a/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java b/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java index 3916a396f3..2391f4ef22 100644 --- a/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java +++ b/shell/src/main/java/org/jboss/forge/shell/ShellImpl.java @@ -707,7 +707,9 @@ public void execute(String line) for (CommandInterceptor interceptor : commandInterceptors) { line = interceptor.intercept(line); } - fshRuntime.run(line); + + if (line != null) + fshRuntime.run(line); } catch (Exception e) { diff --git a/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/AliasInterceptor.java b/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/AliasInterceptor.java new file mode 100644 index 0000000000..ae122e7f02 --- /dev/null +++ b/shell/src/main/java/org/jboss/forge/shell/plugins/builtin/AliasInterceptor.java @@ -0,0 +1,42 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.forge.shell.plugins.builtin; + +import org.jboss.forge.shell.spi.CommandInterceptor; + +/** + * Responsible for converting aliases into full commands. + * + * @author Lincoln Baxter, III + * + */ +public class AliasInterceptor implements CommandInterceptor +{ + @Override + public String intercept(final String line) + { + if ("alias".equals(line.trim())) + return null; + + return line; + } +}