001 /*
002 * Copyright (C) 2010 eXo Platform SAS.
003 *
004 * This is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU Lesser General Public License as
006 * published by the Free Software Foundation; either version 2.1 of
007 * the License, or (at your option) any later version.
008 *
009 * This software is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public
015 * License along with this software; if not, write to the Free
016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018 */
019
020 package org.crsh.command;
021
022 import groovy.lang.Closure;
023 import groovy.lang.GroovyObjectSupport;
024 import groovy.lang.MissingMethodException;
025 import groovy.lang.MissingPropertyException;
026 import org.codehaus.groovy.runtime.InvokerInvocationException;
027 import org.crsh.shell.impl.CRaSH;
028
029 /**
030 * A base command that should be subclasses by Groovy commands. For this matter it inherits the
031 * {@link GroovyObjectSupport} class.
032 *
033 * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
034 * @version $Revision$
035 */
036 public abstract class GroovyCommand extends GroovyObjectSupport {
037
038 protected abstract CommandContext getContext();
039
040 @Override
041 public final Object invokeMethod(String name, Object args) {
042 try {
043 return super.invokeMethod(name, args);
044 }
045 catch (MissingMethodException e) {
046
047 //
048 CommandContext context = getContext();
049
050 //
051 if (context instanceof InvocationContext) {
052 InvocationContext ic = (InvocationContext)context;
053 CRaSH crash = (CRaSH)context.getAttributes().get("crash");
054 if (crash != null) {
055 ShellCommand cmd;
056 try {
057 cmd = crash.getCommand(name);
058 }
059 catch (NoSuchCommandException ce) {
060 throw new InvokerInvocationException(ce);
061 }
062 if (cmd != null) {
063 CommandDispatcher dispatcher = new CommandDispatcher(cmd, ic);
064 return dispatcher.dispatch("", args);
065 }
066 }
067 }
068
069 //
070 Object o = context.getAttributes().get(name);
071 if (o instanceof Closure) {
072 Closure closure = (Closure)o;
073 if (args instanceof Object[]) {
074 Object[] array = (Object[])args;
075 if (array.length == 0) {
076 return closure.call();
077 } else {
078 return closure.call(array);
079 }
080 } else {
081 return closure.call(args);
082 }
083 } else {
084 throw e;
085 }
086 }
087 }
088
089 @Override
090 public final Object getProperty(String property) {
091 CommandContext context = getContext();
092 if ("out".equals(property)) {
093 if (context instanceof InvocationContext<?, ?>) {
094 return ((InvocationContext<?, ?>)context).getWriter();
095 } else {
096 return null;
097 }
098 } else {
099 if (context instanceof InvocationContext<?, ?>) {
100 CRaSH crash = (CRaSH)context.getAttributes().get("crash");
101 if (crash != null) {
102 try {
103 ShellCommand cmd = crash.getCommand(property);
104 if (cmd != null) {
105 return new CommandDispatcher(cmd, (InvocationContext<?, ?>)context);
106 }
107 } catch (NoSuchCommandException e) {
108 throw new InvokerInvocationException(e);
109 }
110 }
111 }
112
113 //
114 try {
115 return super.getProperty(property);
116 }
117 catch (MissingPropertyException e) {
118 return context.getAttributes().get(property);
119 }
120 }
121 }
122
123 @Override
124 public final void setProperty(String property, Object newValue) {
125 if ("out".equals(property)) {
126 throw new IllegalArgumentException("Cannot write out");
127 }
128 try {
129 super.setProperty(property, newValue);
130 }
131 catch (MissingPropertyException e) {
132 CommandContext context = getContext();
133 context.getAttributes().put(property, newValue);
134 }
135 }
136 }