View Javadoc
1   /**
2    * Copyright 2014 Internet2
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  /*
17   * Copyright (C) 2006-2007 blair christensen.
18   * All Rights Reserved.
19   *
20   * You may use and distribute under the same terms as Grouper itself.
21   */
22  
23  package edu.internet2.middleware.grouper.app.gsh;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.lang.reflect.Method;
27  import java.util.ArrayList;
28  import java.util.HashMap;
29  import java.util.List;
30  import java.util.Map;
31  
32  import jline.TerminalFactory;
33  
34  import org.apache.commons.lang.exception.ExceptionUtils;
35  import org.apache.commons.lang3.ArrayUtils;
36  import org.apache.commons.lang3.StringUtils;
37  import org.apache.commons.logging.Log;
38  import org.apache.commons.logging.LogFactory;
39  import org.codehaus.groovy.control.CompilerConfiguration;
40  import org.codehaus.groovy.tools.shell.ExitNotification;
41  import org.codehaus.groovy.tools.shell.Groovysh;
42  import org.codehaus.groovy.tools.shell.IO;
43  import org.codehaus.groovy.tools.shell.util.Logger;
44  
45  import bsh.Interpreter;
46  import edu.internet2.middleware.grouper.GrouperSession;
47  import edu.internet2.middleware.grouper.SubjectFinder;
48  import edu.internet2.middleware.grouper.app.gsh.jline.WindowsTerminal;
49  import edu.internet2.middleware.grouper.app.gsh.template.GshTemplateReturnException;
50  import edu.internet2.middleware.grouper.app.loader.GrouperLoader;
51  import edu.internet2.middleware.grouper.audit.GrouperEngineBuiltin;
52  import edu.internet2.middleware.grouper.cache.EhcacheController;
53  import edu.internet2.middleware.grouper.cfg.GrouperConfig;
54  import edu.internet2.middleware.grouper.hibernate.GrouperContext;
55  import edu.internet2.middleware.grouper.hibernate.HibernateSession;
56  import edu.internet2.middleware.grouper.hooks.beans.GrouperContextTypeBuiltIn;
57  import edu.internet2.middleware.grouper.misc.GrouperStartup;
58  import edu.internet2.middleware.grouper.plugins.GrouperPluginManager;
59  import edu.internet2.middleware.grouper.util.GrouperUtil;
60  import edu.internet2.middleware.grouper.xml.export.XmlExportGsh;
61  import edu.internet2.middleware.grouper.xml.importXml.XmlImportGsh;
62  
63  /**
64   * Grouper Management Shell.
65   * <p/>
66   * @author  blair christensen.
67   * @version $Id: GrouperShell.java,v 1.18 2009-11-02 03:50:51 mchyzer Exp $
68   * @since   0.0.1
69   */
70  public class GrouperShell {
71    
72    /** if we should exit on failure */ 
73    static boolean exitOnFailure = false;
74    
75    private static Map<String, String> mainLookups = new HashMap<String, String>();
76    //TODO config file?
77    static {
78  	  mainLookups.put("-xmlimportold", 
79  			  "edu.internet2.middleware.grouper.xml.XmlImporter");
80  	  
81  	  mainLookups.put("-xmlexportold", 
82  			  "edu.internet2.middleware.grouper.xml.XmlExporter");
83  	  
84      mainLookups.put("-xmlimport", 
85        XmlImportGsh.class.getName());
86  
87      mainLookups.put("-xmlexport", 
88        XmlExportGsh.class.getName());
89  
90  	  mainLookups.put("-test",      
91  			  "edu.internet2.middleware.grouper.AllTests");
92  	  
93  	  mainLookups.put("-loader",    
94  			  "edu.internet2.middleware.grouper.app.loader.GrouperLoader");
95  	  
96  	  mainLookups.put("-registry",  
97  			  "edu.internet2.middleware.grouper.registry.RegistryInitializeSchema");
98  	  
99  	  mainLookups.put("-findbadmemberships",  
100 			  "edu.internet2.middleware.grouper.misc.FindBadMemberships");
101 
102     mainLookups.put("-ldappc",  
103       "edu.internet2.middleware.ldappc.Ldappc");
104     
105     mainLookups.put("-ldappcng",
106         "edu.internet2.middleware.ldappc.spml.PSPCLI");
107     
108     mainLookups.put("-psp",
109         "edu.internet2.middleware.psp.PspCLI");
110     
111     mainLookups.put("-pspngattributestoprovisioningattributes",
112         "edu.internet2.middleware.grouper.app.provisioning.PspngToNewProvisioningAttributeConversion");
113 
114   }
115   
116   // PROTECTED CLASS CONSTANTS //
117   protected static final String NAME    = "gsh";
118 
119 
120   // PRIVATE CLASS CONSTANTS //
121   private static final String GSH_DEBUG   = "GSH_DEBUG";
122   private static final String GSH_DEVEL   = "GSH_DEVEL";
123   private static final String GSH_HISTORY = "_GSH_HISTORY";
124   private static final String GSH_OURS    = "_GSH_OURS";
125   private static final String GSH_SESSION = "_GSH_GROUPER_SESSION";
126   private static final String GSH_TIMER   = "GSH_TIMER";
127   
128 
129   // PRIVATE INSTANCE VARIABLES //
130   private Interpreter   interpreter = null;
131   private CommandReader r = null;
132 
133   /** if running from GSH */
134   public static boolean runFromGsh = false;
135   
136   /** if running from GSH interactively */
137   private static boolean runFromGshInteractive = false;
138   
139   private static ThreadLocal<String> groovyPreloadString = new ThreadLocal<String>();
140   
141   // MAIN //
142 
143   /**
144    * Run {@link GrouperShell}.
145    * <pre class="eg">
146    * // Launch GrouperShell in interactive mode
147    * % gsh.sh
148    *
149    * // Run GrouperShell script
150    * % gsh.sh script.gsh
151    * 
152    * // Read commands from STDIN
153    * % gsh.sh - 
154    * </pre>
155    * @param args 
156    * @since 0.0.1
157    */
158   public static void main(String args[]) {
159     boolean wasSpecialCase = false;
160     
161     try {
162       //set this and leave it...
163       @SuppressWarnings("unused")
164       GrouperContext grouperContext = GrouperContext.createNewDefaultContext(
165           GrouperEngineBuiltin.GSH, false, true);
166       
167       wasSpecialCase = handleSpecialCase(args);
168       if(wasSpecialCase) {
169       	return;
170       }
171   	  runFromGsh = true;
172   	
173       GrouperStartup.runFromMain = true;
174       GrouperStartup.startup();
175       GrouperStartup.waitForGrouperStartup();
176   
177       //turn on logging
178       Log bshLogger = LogFactory.getLog("bsh");
179       if (bshLogger.isTraceEnabled()) {
180         Interpreter.TRACE = true;
181       }
182       if (bshLogger.isDebugEnabled()) {
183         Interpreter.DEBUG = true;
184       }
185       exitOnFailure = true;
186       try {
187         grouperShellHelper(args, null);
188       }
189       catch (GrouperShellException eGS) {
190         eGS.printStackTrace();
191         LOG.error("GSH is exiting: " + eGS.getMessage(), eGS);
192         System.exit(1);
193       } catch (UnsatisfiedLinkError e) {
194         if (e.getMessage() != null && e.getMessage().contains("jansi")) {
195           System.err.println("\n\n\nUnable to start GSH.  Your tmpdir " + System.getProperty("java.io.tmpdir") + " may have the noexec flag set.  If so, set this environment variable: export GSH_JVMARGS=\"-Dlibrary.jansi.path=/some/other/temp/path/with/exec\"\n\n\n");
196         }
197         
198         throw new RuntimeException(e);
199       }
200     } finally {
201       if (!wasSpecialCase) {
202         try {
203           EhcacheController.ehcacheController().stop();
204         } catch (Exception e) {
205           LOG.error("error stopping ehcache controller");
206         }
207       }
208     }
209     System.exit(0);
210   } // public static void main(args)
211   
212   
213  /**
214  * Avoid GSH initialisation for special cases 
215  * @param args - command line arguments
216  * @return whether this was handled as a special case
217  */
218 private static boolean handleSpecialCase(String[] args) {
219 	  if(args == null || args.length==0) {
220 		  return false;
221 	  }
222 	  if("-h".equalsIgnoreCase(args[0])||"-help".equalsIgnoreCase(args[0])) {
223 		  System.out.println(_getUsage());
224 		  return true;
225 	  }
226 	  
227 	  if("-nocheck".equalsIgnoreCase(args[0])) {
228 		  GrouperStartup.ignoreCheckConfig = true;
229 		  return false;
230 	  }
231 	  boolean isLoader = StringUtils.equals("-loader", args[0].toLowerCase());
232 	  String mainClass = mainLookups.get(args[0].toLowerCase());
233 	  if(mainClass==null) {
234 		  return false;
235 	  }
236 	  String[] mainArgs = new String[args.length -1];
237 	  for(int i=1;i<args.length;i++) {
238 		  mainArgs[i-1] = args[i];
239 	  }
240 	  
241 	  try {
242 		  Class claz = Class.forName(mainClass);
243 		  
244 		  Method method = claz.getMethod("main", String[].class);
245 		  method.invoke(null, (Object)mainArgs);
246 	  }catch(Exception e) {
247 	    if (ExceptionUtils.getFullStackTrace(e).contains("PSPCLI")) {
248 	      String error = "Make sure you have run 'ant dist' in ldappcng, and 'ant ldappcng' in grouper to copy the libs over";
249         LOG.fatal(error);
250         System.err.println(error);
251 	    }
252 		  if(e instanceof RuntimeException) {
253 			  throw (RuntimeException)e;
254 		  }
255 		  throw new RuntimeException(e);
256 	  } finally {
257 	    if (!isLoader) {
258 	      try {
259 	        GrouperLoader.shutdownIfStarted();
260 	      } catch (Exception e) {
261 	        LOG.error("error shutting down loader", e);
262 	      }
263         try {
264           GrouperPluginManager.shutdownIfStarted();
265         } catch (Exception e) {
266           LOG.error("error shutting down plugins", e);
267         }
268         try {
269           EhcacheController.ehcacheController().stop();
270         } catch (Exception e) {
271           LOG.error("error stopping ehcache controller");
272         }
273 	    }
274 	  }
275 	  
276 	  return true;
277   } //private static boolean handleSpecialCase(args)
278  
279   /**
280    * if ARM processor this wont work, use NONE
281    */
282   private static boolean useTerminalFactoryAuto = true;
283 
284   /**
285    * helper method to kick off GSH without exiting
286    * @param args
287    * @param inputStreamParam if passing in an inputStream
288    * @throws GrouperShellException
289    */
290   static void grouperShellHelper(String args[], InputStream inputStreamParam) throws GrouperShellException {
291 
292     System.out.println("Type help() for instructions");
293     
294     GrouperContextTypeBuiltIn.setDefaultContext(GrouperContextTypeBuiltIn.GSH);
295     
296     boolean forceLegacyGsh = false;
297     if (args != null && args.length > 0 && args[0].equalsIgnoreCase("-forceLegacyGsh")) {
298       forceLegacyGsh = true;
299       args = ArrayUtils.remove(args, 0);
300     }
301     
302     boolean lightweightProfile = false;
303     if (args != null && args.length > 0 && args[0].equalsIgnoreCase("-lightWeightProfile")) {
304       lightweightProfile = true;
305       args = ArrayUtils.remove(args, 0);
306     }
307     
308     if (forceLegacyGsh || GrouperConfig.retrieveConfig().propertyValueBoolean("gsh.useLegacy", false)) {
309       new GrouperShell( new ShellCommandReader(args, inputStreamParam )).run();
310     } else {
311       
312       TerminalFactory.registerFlavor(TerminalFactory.Flavor.WINDOWS, WindowsTerminal.class);
313       
314       StringBuilder body = new StringBuilder();
315       
316       if (lightweightProfile) {
317         if (args != null && args.length > 0 && !args[0].equalsIgnoreCase("-check") && !args[0].equals("-runarg")) {
318           body.append(":load '" + GrouperUtil.fileFromResourceName("groovysh_lightWeightWithFile.profile").getAbsolutePath() + "'");
319         } else {
320           body.append(":load '" + GrouperUtil.fileFromResourceName("groovysh_lightWeight.profile").getAbsolutePath() + "'");
321         }
322       } else {
323         body.append(":load '" + GrouperUtil.fileFromResourceName("groovysh.profile").getAbsolutePath() + "'");
324       }
325       if (args != null && args.length > 0 && !args[0].equalsIgnoreCase("-check")) {
326         
327         if (args[0].equals("-main")) {
328           if (args.length == 1) {
329             throw new RuntimeException("When passing -main, pass at least one more argument, the class to run");
330           }
331           
332           // ok running a main method and exiting          
333           body.append("\n" + args[1] + ".main(");
334           
335           for(int i = 2; i < args.length; i++) {
336             body.append("\"" + args[i] + "\"");
337             if ((i + 1) < args.length) {
338               body.append(", ");
339             }
340           }
341           
342           body.append(")");
343         } else if (args[0].equals("-runarg")) {
344           if (args.length == 1) {
345             throw new RuntimeException("When passing -runarg, pass one other argument, the gsh command to run");
346           }
347           
348           String commands = args[1];
349           //if \\n was in there, then make it a newline...
350           commands = commands.replace("\\n", "\n");
351           body.append("\n" + commands);
352         } else {
353           body.append("\n" + ":gshFileLoad '" + args[0] + "'");
354         }
355         
356         body.append("\n:exit");
357       } else if (inputStreamParam != null) {
358         throw new RuntimeException("Unexpected (for now at least)");
359       } else {
360         runFromGshInteractive = true;
361       }
362       
363       groovyPreloadString.set(body.toString());
364       //org.codehaus.groovy.tools.shell.Main.main(new String[] { "-e", body.toString() });
365       
366       boolean exitOnError = !GrouperShell.runFromGshInteractive && GrouperConfig.retrieveConfig().propertyValueBoolean("gsh.exitOnNonInteractiveError", false);
367 
368       if (runFromGshInteractive && useTerminalFactoryAuto) {
369         try {
370           org.codehaus.groovy.tools.shell.Main.setTerminalType(TerminalFactory.AUTO, false);
371         } catch (UnsatisfiedLinkError e) {
372           useTerminalFactoryAuto = false;
373         }
374       } else {
375         org.codehaus.groovy.tools.shell.Main.setTerminalType(TerminalFactory.NONE, false);
376       }
377       IO io = new IO();
378       CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
379       Logger.io = io;
380       compilerConfiguration.setParameters(false);
381 
382       final Groovysh shell = new GrouperGroovysh(io, compilerConfiguration, exitOnError);
383       
384       Runtime.getRuntime().addShutdownHook(new Thread() {
385         public void run() {
386           try {
387             if (shell.getHistory() != null) {
388               shell.getHistory().flush();
389             }
390           } catch (IOException e) {
391             System.err.println("Error flushing GSH history: " + ExceptionUtils.getFullStackTrace(e));
392           }
393         }
394       });
395       
396       int code = 0;
397       try {        
398         code = shell.run(body.toString());
399       } catch (GshTemplateReturnException e) {
400       }
401 
402       System.exit(code);
403     }
404   }
405   
406   /**
407    * @param command
408    * @param t
409    */
410   public static void handleFileLoadError(String command, Throwable t) {
411     if (t instanceof GshTemplateReturnException) {
412       return;
413     }
414     // This gets called when loading a file.
415     // Note that this gets invoked (mostly) during a caught exception.  If an exception is thrown here, the gsh error handle (displayError) will end up being called.
416     // If we just print the error, then the processing will continue (e.g. next line of gsh file).
417     boolean exitOnNonInteractiveError = !GrouperShell.runFromGshInteractive && GrouperConfig.retrieveConfig().propertyValueBoolean("gsh.exitOnNonInteractiveError", false);
418     String error = "Error while running command (" + command +  ")";
419     if (exitOnNonInteractiveError) {
420       // note this doesnt always get logged
421       LOG.error("Error in command '" + command + "'", t);
422       throw new RuntimeException(error, t);
423     }
424       
425     System.err.println(error + ": " + ExceptionUtils.getFullStackTrace(t));
426   }
427   
428   /**
429    * @return groovy string to preload
430    */
431   public static String getGroovyPreloadString() {
432     return groovyPreloadString.get();
433   }
434 
435   // CONSTRUCTORS //
436 
437   // @since   0.1.1
438   protected GrouperShell(CommandReader r) 
439     throws  GrouperShellException
440   {
441     this.interpreter  = r.getInterpreter();
442     this.r  = r;
443   } // protected GrouperShell()
444 
445 
446   // PROTECTED CLASS METHODS //
447 
448   // @since   0.0.1
449   protected static void error(Interpreter i, Exception e) {
450     error(i, e, e.getMessage());
451   } // protected static void error(i, e)
452 
453   // @since   0.0.1
454   protected static void error(Interpreter interpreter, Exception e, String msg) {
455     interpreter.error(msg);
456     LOG.error("Error in GSH: " + msg, e);
457     if (isDebug(interpreter)) {
458       e.printStackTrace();
459     }
460     if (ShellHelper.closeOpenTransactions(interpreter, e)) {
461       ShellHelper.exitDueToOpenTransaction(interpreter);
462     }
463   } // protected static void error(i, e, msg)
464 
465   // @since   0.0.1
466   protected static Object get(Interpreter i, String key) 
467     throws  bsh.EvalError
468   {
469     return i.get(key);
470   } // protected static Object set(i, key)
471 
472   // @since   0.0.1
473   protected static List getHistory(Interpreter i) 
474     throws  bsh.EvalError
475   {
476     List history = (ArrayList) GrouperShell.get(i, GSH_HISTORY);
477     if (history == null) {
478       history = new ArrayList();
479     }
480     return history;
481   } // protected static List getHistory(i)
482 
483   // @since   0.0.1
484   protected static GrouperSession getSession(Interpreter i) 
485     throws  GrouperShellException
486   {
487     try {
488       //get static first
489       GrouperSession s = null;
490       
491       if (GrouperConfig.retrieveConfig().propertyValueBoolean("grouper.gsh.useStaticGrouperSessionFirst", true)) {
492         s = GrouperSession.staticGrouperSession(false);
493       }
494       if (s==null) {
495         s = (GrouperSession) GrouperShell.get(i, GSH_SESSION);
496       }
497       if (s != null && s.getSubjectDb() == null) {
498         s = null;
499         GrouperShell.set(i, GSH_SESSION, s);
500       }
501       if (s == null) {
502         s = GrouperSession.staticGrouperSession(false);
503         
504         if (s == null) {
505           s = GrouperSession.startRootSession();
506         }
507         GrouperShell.set(i, GSH_SESSION, s);
508       }
509       return s;
510     }
511     catch (Exception e) {
512       if (i != null) {
513         i.error(e.getMessage());
514       }
515       throw new GrouperShellException(e);
516     }
517   } // protected static GrouperSession getSession(i)
518 
519   // @since   0.0.1
520   protected static boolean isDebug(Interpreter i) {
521     return _isTrue(i, GSH_DEBUG);
522   } // protected static boolean isDebug(i)
523 
524   // @return  True if last command run was a GrouperShell command.
525   // @since   0.0.1
526   protected static boolean isOurCommand(Interpreter i) {
527     return _isTrue(i, GSH_OURS);
528   } // protected static boolean isOurCommand()
529 
530   // @return  True if commands should be timed.
531   // @since   0.0.1
532   protected static boolean isTimed(Interpreter i) {
533     return _isTrue(i, GSH_TIMER);
534   } // protected static boolean isTimed()
535 
536   // @since   0.0.1
537   protected static void set(Interpreter i, String key, Object obj) 
538     throws  bsh.EvalError
539   {
540     i.set(key, obj);  
541   } // protected static void set(i, key, obj)
542 
543   // @since   0.0.1
544   protected static boolean isDevel(Interpreter i) {
545     return _isTrue(i, GSH_DEVEL);
546   } // protected static boolean isDevel(i)
547 
548   // @since   0.0.1
549   protected static void setHistory(Interpreter i, int cnt, String cmd) 
550     throws  bsh.EvalError
551   {
552     List history = GrouperShell.getHistory(i);
553     history.add(cnt, cmd);
554     GrouperShell.set(i, GSH_HISTORY, history);
555   } // protected static void setHistory(i, cnt, cmd)
556 
557   // @since   0.0.1
558   public static void setOurCommand(Interpreter i, boolean b) {
559     try {
560       GrouperShell.set(i, GSH_OURS, Boolean.valueOf(b));
561     }
562     catch (bsh.EvalError eBEE) {
563       i.error(eBEE.getMessage());
564     }
565   } // protected static void setOurCommand(i, b)
566 
567 
568   // PROTECTED INSTANCE METHODS //
569 
570   // @since   0.1.1
571   protected void run() 
572     throws  GrouperShellException
573   {
574     String cmd = new String();
575     try {
576       this.interpreter.eval(  "importCommands(\"edu.internet2.middleware.grouper\")");
577       this.interpreter.eval(  "importCommands(\"edu.internet2.middleware.grouper.app.gsh\")");
578       this.interpreter.eval(  "importCommands(\"edu.internet2.middleware.grouper.app.misc\")");
579       this.interpreter.eval(  "importCommands(\"edu.internet2.middleware.grouper.privs\")");
580       //this.i.eval(  "importCommands(\"edu.internet2.middleware.grouper.registry\")");
581       this.interpreter.eval(  "importCommands(\"edu.internet2.middleware.subject\")");
582       this.interpreter.eval(  "importCommands(\"edu.internet2.middleware.subject.provider\")");
583       this.interpreter.eval(  "import edu.internet2.middleware.grouper.*;");
584       this.interpreter.eval(  "import edu.internet2.middleware.grouper.authentication.*;");
585       this.interpreter.eval(  "import edu.internet2.middleware.grouper.app.loader.ldap.*;");
586       this.interpreter.eval(  "import edu.internet2.middleware.grouper.attr.*;");
587       this.interpreter.eval(  "import edu.internet2.middleware.grouper.attr.assign.*;");
588       this.interpreter.eval(  "import edu.internet2.middleware.grouper.attr.finder.*;");
589       this.interpreter.eval(  "import edu.internet2.middleware.grouper.attr.value.*;");
590       this.interpreter.eval(  "import edu.internet2.middleware.grouper.audit.*;");
591       this.interpreter.eval(  "import edu.internet2.middleware.grouper.client.*;");
592       this.interpreter.eval(  "import edu.internet2.middleware.grouper.entity.*;");
593       this.interpreter.eval(  "import edu.internet2.middleware.grouper.externalSubjects.*;");
594       this.interpreter.eval(  "import edu.internet2.middleware.grouper.group.*;");
595       this.interpreter.eval(  "import edu.internet2.middleware.grouper.ldap.*;");
596       this.interpreter.eval(  "import edu.internet2.middleware.grouper.app.loader.*;");
597       this.interpreter.eval(  "import edu.internet2.middleware.grouper.xml.*;");
598       this.interpreter.eval(  "import edu.internet2.middleware.grouper.registry.*;");
599       this.interpreter.eval(  "import edu.internet2.middleware.grouper.app.usdu.*;");
600       this.interpreter.eval(  "import edu.internet2.middleware.grouper.app.provisioning.*;");
601       this.interpreter.eval(  "import edu.internet2.middleware.grouper.app.gsh.*;");
602       this.interpreter.eval(  "import edu.internet2.middleware.grouper.app.misc.*;");
603       this.interpreter.eval(  "import edu.internet2.middleware.grouper.privs.*;");
604       this.interpreter.eval(  "import edu.internet2.middleware.grouper.rules.*;");
605       this.interpreter.eval(  "import edu.internet2.middleware.grouper.misc.*;");
606       this.interpreter.eval(  "import edu.internet2.middleware.grouper.hibernate.*;");
607       this.interpreter.eval(  "import edu.internet2.middleware.grouper.permissions.*;");
608       this.interpreter.eval(  "import edu.internet2.middleware.grouper.util.*;");
609       this.interpreter.eval(  "import edu.internet2.middleware.grouper.xml.export.*;");
610       this.interpreter.eval(  "import edu.internet2.middleware.subject.*;");
611       this.interpreter.eval(  "import edu.internet2.middleware.subject.provider.*;");
612       this.interpreter.eval(  "import edu.internet2.middleware.grouper.userData.*;");
613       this.interpreter.eval(  "import edu.internet2.middleware.grouper.messaging.*;");
614       
615     }
616     catch (bsh.EvalError eBBB) {
617       throw new GrouperShellException(GshErrorMessages.I_IMPORT + eBBB.getMessage(), eBBB);
618     }
619     while ( ( cmd = r.getNext() ) != null) {
620       if ( this._isComment(cmd) ) {
621         continue;
622       }
623       if ( this._isTimeToExit(cmd) ) {
624         int txSize = HibernateSession._internal_staticSessions().size();
625         boolean hasTransactions = txSize>0;
626         if (hasTransactions) {
627           String error = "Exiting in the middle of " + txSize + " open transactions, they will be rolled back and closed";
628           this.interpreter.println(error);
629           LOG.error(error);
630           HibernateSession._internal_closeAllHibernateSessions(new RuntimeException());
631         }
632         this._stopSession();
633         if (hasTransactions) {
634           ShellHelper.exitDueToOpenTransaction(this.interpreter);
635         }
636         break;
637       }
638       // Now try to eval the command
639       cmd = ShellHelper.eval(interpreter, cmd);
640     }
641   } 
642 
643   /** logger */
644   private static final Log LOG = GrouperUtil.getLog(GrouperShell.class);
645 
646   /**
647    * 
648    * @param i
649    * @param var
650    * @return true if istrue
651    */
652   private static boolean _isTrue(Interpreter i, String var) {
653     boolean rv = false;
654     try {
655       Object  obj = GrouperShell.get(i, var);
656     if (
657                 (obj != null)
658             &&  (obj instanceof Boolean)
659             &&  (Boolean.TRUE.equals( obj ))
660          )
661       {
662         rv = true;
663       }
664     }
665     catch (bsh.EvalError eBEE) {
666       i.error(eBEE.getMessage());
667     }
668     return rv;
669   } // private static boolean _isTrue(i, var)
670 
671 
672   // PRIVATE INSTANCE METHODS //
673 
674   // I'm not sure if this is the best place for this but...
675   // @since   1.1.0
676   private boolean _isComment(String cmd) {
677     if ( cmd.startsWith("#") || cmd.startsWith("//") ) {
678       return true;
679     }
680     return false;
681   } // private boolean _isComment(cmd)
682 
683   // I'm not sure if this is the best place for this but...
684   // @since   1.1.0
685   private boolean _isTimeToExit(String cmd) {
686     if ( cmd.equals("exit") || cmd.equals("quit") ) {
687       return true;
688     }
689     return false;
690   } // private boolean _isTimeToExit(cmd)
691 
692   // @since   0.0.1
693   private void _stopSession() 
694     throws  GrouperShellException
695   {
696     try {
697       // `GrouperShell.getSession()` will start the session if it doesn't exist.
698       // That's just slow.  And wrong.
699       GrouperSession../../../../../edu/internet2/middleware/grouper/GrouperSession.html#GrouperSession">GrouperSession s = (GrouperSession) GrouperShell.get(this.interpreter, GSH_SESSION);
700       if (s != null) {
701         s.stop();
702         this.interpreter.unset(GSH_SESSION);
703       }
704     }
705     catch (Exception e) {
706       if (interpreter != null) {
707         this.interpreter.error(e.getMessage());
708       }
709       throw new GrouperShellException(e);
710     }
711   } // private void _stopSession()
712   
713   private static String _getUsage() {
714 	    return  "Usage:"                                                                   + GrouperConfig.NL
715 	            + "args: -h,               Prints this message"                            + GrouperConfig.NL
716 	            + "args: <filename>,       Execute commands in specified file"             + GrouperConfig.NL
717 	            + "no args:                Enters an interactive shell"                    + GrouperConfig.NL
718 	            + "args: -lightWeightProfile"                                              + GrouperConfig.NL
719 	            + "       Use alternate init script (classes/groovysh_lightWeight.profile)" + GrouperConfig.NL
720 	            + "       which has less imports and may improve startup performance"      + GrouperConfig.NL
721 	            + "args: -nocheck,         Skips startup check and enters an "          + GrouperConfig.NL
722 	            + "                        interactive shell"                              + GrouperConfig.NL
723 	            + "args: -runarg <command> Run command (use \\\\n to separate commands)"   + GrouperConfig.NL
724 	            + "args: -main <class> [args...]                                    "      + GrouperConfig.NL
725 	            + "   class,               Full class name (must have main method)"        + GrouperConfig.NL
726 	            + "   args,                args as required by main method of class"       + GrouperConfig.NL
727 	            + "args: -initEnv [<configDir>]"                                           + GrouperConfig.NL
728 	            + "       On Windows sets GROUPER_HOME and adds GROUPER_HOME/bin to path"  + GrouperConfig.NL
729 	            + "       For *nix 'source gsh.sh' for the same result"                    + GrouperConfig.NL
730 	            + "       configDir optionally adds an alternative conf directory than"    + GrouperConfig.NL 
731 	            + "       GROUPER_HOME/conf to the classpath"                              + GrouperConfig.NL
732 	            + "args: (-xmlimport | -xmlexport | -loader | -test | -registry |"   + GrouperConfig.NL
733 	            + "       -findbadmemberships | -ldappc | -pspngAttributesToProvisioningAttributes) "
734 	            + "                        Enter option to get additional usage for that " + GrouperConfig.NL
735 	            + "                        option "                                        + GrouperConfig.NL
736 	            
737 	            + "  -xmlimport,           Invokes XmlImporter*"                           + GrouperConfig.NL
738 	            + "                        *XML format has changed in v1.6. To import"     + GrouperConfig.NL
739 	            + "                        the original XML format use -xmlimportold"      + GrouperConfig.NL
740 	            + "  -xmlexport,           Invokes XmlExporter"                            + GrouperConfig.NL
741 	            + "  -loader,              Invokes GrouperLoader"                          + GrouperConfig.NL
742 	            + "  -registry,            Manipulate the Grouper schema and install"      + GrouperConfig.NL
743 	            + "                        bootstrap data"                                 + GrouperConfig.NL
744 	            + "  -test,                Run JUnit tests"                                + GrouperConfig.NL
745 	             
746 	            + "  -pspngAttributesToProvisioningAttributes Copies pspng attributes to " + GrouperConfig.NL
747 	            + "                        provisioning, enter pspngConfigId and provisioningFrameworkConfigId"  + GrouperConfig.NL
748 	            + "  -findbadmemberships,  Check for membership data inconsistencies    "  + GrouperConfig.NL
749                 + "  -ldappc,              Run the grouper ldap provisioning connector to send data to ldap    "  + GrouperConfig.NL
750 	            ;
751 	  } // private static String _getUsage()
752 
753 } // public class GrouperShell
754