You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by jd...@apache.org on 2008/09/27 11:49:28 UTC

svn commit: r699610 - in /geronimo/gshell/trunk: ./ gshell-assembly/src/main/underlay/etc/ gshell-bootstrap/src/main/java/org/apache/geronimo/gshell/bootstrap/ gshell-bootstrap/src/main/resources/ gshell-bootstrap/src/main/resources/org/ gshell-bootstr...

Author: jdillon
Date: Sat Sep 27 02:49:27 2008
New Revision: 699610

URL: http://svn.apache.org/viewvc?rev=699610&view=rev
Log:
Using XML log4j configuration
Made the presense of etc/gsh-log4j.xml and etc/gsh-classworlds.conf optional
Allow support of etc/log4j.xml and etc/classworlds.conf (just minus the program.name prefix)
Changed the gshell-bootstrap Launcher to extend from the ClassWorlds Launcher and customize it further to load configuration from resources as desired.

Added:
    geronimo/gshell/trunk/gshell-assembly/src/main/underlay/etc/log4j.xml   (with props)
    geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/
    geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/
    geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/
    geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/
    geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/
    geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/
    geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/classworlds.conf   (with props)
    geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/log4j.xml   (with props)
Removed:
    geronimo/gshell/trunk/gshell-assembly/src/main/underlay/etc/gsh-classworlds.conf
    geronimo/gshell/trunk/gshell-assembly/src/main/underlay/etc/gsh-log4j.properties
Modified:
    geronimo/gshell/trunk/gsh
    geronimo/gshell/trunk/gshell-bootstrap/src/main/java/org/apache/geronimo/gshell/bootstrap/Launcher.java
    geronimo/gshell/trunk/gshell-cli/src/main/java/org/apache/geronimo/gshell/cli/Main.java
    geronimo/gshell/trunk/gshell-wisdom/gshell-wisdom-core/src/main/java/org/apache/geronimo/gshell/wisdom/command/CommandMessageSource.java

Modified: geronimo/gshell/trunk/gsh
URL: http://svn.apache.org/viewvc/geronimo/gshell/trunk/gsh?rev=699610&r1=699609&r2=699610&view=diff
==============================================================================
--- geronimo/gshell/trunk/gsh (original)
+++ geronimo/gshell/trunk/gsh Sat Sep 27 02:49:27 2008
@@ -1,3 +1,3 @@
 #!/bin/sh
 
-JAVA_OPTS="-ea" `dirname $0`/gshell-*/bin/gsh -e "$@"
+JAVA_OPTS="$JAVA_OPTS -ea" `dirname $0`/gshell-*/bin/gsh -e "$@"

Added: geronimo/gshell/trunk/gshell-assembly/src/main/underlay/etc/log4j.xml
URL: http://svn.apache.org/viewvc/geronimo/gshell/trunk/gshell-assembly/src/main/underlay/etc/log4j.xml?rev=699610&view=auto
==============================================================================
--- geronimo/gshell/trunk/gshell-assembly/src/main/underlay/etc/log4j.xml (added)
+++ geronimo/gshell/trunk/gshell-assembly/src/main/underlay/etc/log4j.xml Sat Sep 27 02:49:27 2008
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+
+<!-- $Rev$ $Date$ -->
+
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+        
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+        <param name="Target" value="System.out"/>
+        <param name="Threshold" value="${gshell.log.console.level}"/>
+        <layout class="org.apache.log4j.PatternLayout">
+            <param name="ConversionPattern" value="%-5p %-25.30c{1} [%t] %m%n"/>
+        </layout>
+    </appender>
+
+    <appender name="FILE" class="org.apache.log4j.FileAppender">
+        <param name="File" value="${gshell.home}/log/gshell.log"/>
+        <param name="Append" value="false"/>
+        <param name="Threshold" value="${gshell.log.console.level}"/>
+        <layout class="org.apache.log4j.PatternLayout">
+            <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p (%t) [%c] %m%n"/>
+        </layout>
+    </appender>
+
+    <logger name="org.apache.geronimo.gshell.parser.CommandLineParser">
+        <level value="INFO"/>
+    </logger>
+
+    <logger name="org.apache.geronimo.gshell.artifact.GShellArtifactMetadataSource">
+        <level value="DEBUG"/>
+    </logger>
+
+    <logger name="org.apache.geronimo.gshell.artifact.monitor.ProgressSpinnerMonitor">
+        <level value="INFO"/>
+    </logger>
+
+    <logger name="org.apache.geronimo.gshell.application.ApplicationSecurityManager">
+        <level value="DEBUG"/>
+    </logger>
+
+    <logger name="org.apache.geronimo.gshell.model.interpolate.InterpolatorSupport">
+        <level value="DEBUG"/>
+    </logger>
+
+    <logger name="org.apache.geronimo.gshell.console">
+        <level value="INFO"/>
+    </logger>
+
+    <logger name="org.codehaus.plexus.PlexusContainer">
+        <level value="INFO"/>
+    </logger>
+
+    <logger name="org.apache.mina.filter.executor.ExecutorFilter">
+        <level value="INFO"/>
+    </logger>
+
+    <logger name="org.apache.maven">
+        <level value="INFO"/>
+    </logger>
+
+    <logger name="org.apache.maven.artifact.manager">
+        <level value="ERROR"/>
+    </logger>
+
+    <logger name="org.apache.maven.artifact.repository.metadata">
+        <level value="WARN"/>
+    </logger>
+
+    <logger name="org.springframework">
+        <level value="INFO"/>
+    </logger>
+
+    <logger name="org.apache.geronimo.gshell.spring.BeanContainerContext">
+        <level value="INFO"/>
+    </logger>
+
+    <root>
+        <level value="${gshell.log.console.level}"/>
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE"/>
+    </root>
+
+</log4j:configuration>
\ No newline at end of file

Propchange: geronimo/gshell/trunk/gshell-assembly/src/main/underlay/etc/log4j.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/gshell/trunk/gshell-assembly/src/main/underlay/etc/log4j.xml
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: geronimo/gshell/trunk/gshell-assembly/src/main/underlay/etc/log4j.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Modified: geronimo/gshell/trunk/gshell-bootstrap/src/main/java/org/apache/geronimo/gshell/bootstrap/Launcher.java
URL: http://svn.apache.org/viewvc/geronimo/gshell/trunk/gshell-bootstrap/src/main/java/org/apache/geronimo/gshell/bootstrap/Launcher.java?rev=699610&r1=699609&r2=699610&view=diff
==============================================================================
--- geronimo/gshell/trunk/gshell-bootstrap/src/main/java/org/apache/geronimo/gshell/bootstrap/Launcher.java (original)
+++ geronimo/gshell/trunk/gshell-bootstrap/src/main/java/org/apache/geronimo/gshell/bootstrap/Launcher.java Sat Sep 27 02:49:27 2008
@@ -20,49 +20,32 @@
 package org.apache.geronimo.gshell.bootstrap;
 
 import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
 
 /**
- * Platform independent launcher to setup common configuration and delegate to
- * the Classworlds launcher.
+ * Platform independent launcher to setup common configuration and launch the application.
  *
  * @version $Rev$ $Date$
  */
 public class Launcher
+    extends org.codehaus.plexus.classworlds.launcher.Launcher
 {
-    private static boolean debug = Boolean.getBoolean(Launcher.class.getName() + ".debug");
+    private static final String PROGRAM_NAME = "program.name";
 
-    private static String programName;
-    
-    private static File homeDir;
+    private static final String GSHELL_HOME = "gshell.home";
 
-    public static void main(final String[] args) throws Exception {
-        assert args != null;
+    private static final String LOG4J_CONF = "log4j.configuration";
 
-        //
-        // NOTE: Branding information is not available here, so we must use the basic GShell properties to configure
-        //       the bootstrap loader.
-        //
-        
-        programName = getProgramName();
-        setProperty("program.name", programName);
-        
-        homeDir = getHomeDir();
-        setProperty("gshell.home", homeDir.getCanonicalPath());
+    private static final String DEFAULT_LOG4J_CONF = "org/apache/geronimo/gshell/bootstrap/log4j.xml";
 
-        //
-        // FIXME: Should load the classworlds.conf from a resource, and hide it in the bootstrap jar, as folks should not
-        //        alter it anymore...
-        //
-        
-        File classworldsConf = getClassworldsConf();
-        setProperty("classworlds.conf", classworldsConf.getCanonicalPath());
+    private static final String DEFAULT_CLASSWORLDS_CONF = "org/apache/geronimo/gshell/bootstrap/classworlds.conf";
 
-        File log4jConf = getLog4jConf();
-        setProperty("log4j.configuration", log4jConf.toURI().toURL().toExternalForm());
+    private static boolean debug = Boolean.getBoolean(Launcher.class.getName() + ".debug");
 
-        // Delegate to the Classworlds launcher to finish booting
-        org.codehaus.plexus.classworlds.launcher.Launcher.main(args);
-    }
+    private static String programName;
+    
+    private static File homeDir;
 
     private static void debug(final String message) {
         if (debug) {
@@ -71,16 +54,21 @@
     }
 
     private static void warn(final String message) {
-        System.err.println("[WARNING] " + message);
+        System.err.println("[WARN] " + message);
+    }
+
+    private static void error(final String message) {
+        System.err.println("[ERROR] " + message);
+        throw new Error(message);
     }
 
     private static void setProperty(final String name, final String value) {
         System.setProperty(name, value);
-        debug(name + "=" + value);
+        debug("Setting property: " + name + "=" + value);
     }
 
     private static String getProgramName() {
-        String name = System.getProperty("program.name");
+        String name = System.getProperty(PROGRAM_NAME);
         if (name == null) {
             name = "gsh";
         }
@@ -89,7 +77,7 @@
     }
 
     private static File getHomeDir() throws Exception {
-        String path = System.getProperty("gshell.home");
+        String path = System.getProperty(GSHELL_HOME);
         File dir;
 
         if (path == null) {
@@ -107,31 +95,156 @@
         return dir;
     }
 
-    private static File getClassworldsConf() throws Exception {
-        String path = System.getProperty("classworlds.conf");
+    private static File getProgramConfigurationFile(final String filename) {
+        assert filename != null;
+
+        File etcDir = new File(homeDir, "etc");
+
+        File file = new File(etcDir, programName + "-" + filename);
+
+        if (!file.exists()) {
+            File unprefixedFile = new File(etcDir, filename);
+            
+            if (unprefixedFile.exists()) {
+                file = unprefixedFile;
+            }
+        }
+
+        return file;
+    }
+
+    private static String getClassworldsConf() throws Exception {
+        String path = System.getProperty(CLASSWORLDS_CONF);
         File file;
 
         if (path == null) {
-            file = new File(homeDir, "etc/" + programName + "-classworlds.conf");
+            file = getProgramConfigurationFile("classworlds.conf");
         }
         else {
             file = new File(path).getCanonicalFile();
         }
 
-        return file;
+        if (file.exists()) {
+            return file.getCanonicalPath();
+        }
+
+        return DEFAULT_CLASSWORLDS_CONF;
     }
 
-    private static File getLog4jConf() throws Exception {
-        String path = System.getProperty("log4j.configuration");
+    private static String getLog4jConf() throws Exception {
+        String path = System.getProperty(LOG4J_CONF);
         File file;
 
         if (path == null) {
-            file = new File(homeDir, "etc/" + programName + "-log4j.properties");
+            file = getProgramConfigurationFile("log4j.xml");
         }
         else {
             file = new File(path).getCanonicalFile();
         }
 
-        return file;
+        if (file.exists()) {
+            return file.toURI().toURL().toExternalForm();
+        }
+
+        return DEFAULT_LOG4J_CONF;
+    }
+
+    private static void configure() throws Exception {
+        // Branding information is not available here, so we must use the basic GShell properties to configure the bootstrap loader.
+
+        programName = getProgramName();
+        setProperty(PROGRAM_NAME, programName);
+
+        homeDir = getHomeDir();
+        setProperty(GSHELL_HOME, homeDir.getCanonicalPath());
+
+        String classworldsConf = getClassworldsConf();
+        if (classworldsConf != null) {
+            setProperty(CLASSWORLDS_CONF, classworldsConf);
+        }
+
+        String log4jConf = getLog4jConf();
+        if (log4jConf != null) {
+            setProperty(LOG4J_CONF, log4jConf);
+        }
+        else {
+            warn("Missing Log4j configuration! Logging may not properly initialize;  Please set the '" +
+                    LOG4J_CONF + "' property to a valid configuration file or resource name.");
+        }
+    }
+
+    public static int mainWithExitCode(final String[] args) throws Exception {
+        assert args != null;
+
+        Launcher launcher = new Launcher();
+
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        launcher.setSystemClassLoader(cl);
+
+        String classworldsConf = System.getProperty(CLASSWORLDS_CONF);
+        URL configUrl = null;
+
+        if (classworldsConf != null) {
+            File file = new File(classworldsConf);
+            if (file.exists()) {
+                configUrl = file.toURI().toURL();
+            }
+            else {
+                configUrl = cl.getResource(classworldsConf);
+            }
+        }
+
+        if (configUrl == null) {
+            error("Failed to locate ClassWorlds configuration!  Please set the '" +
+                    CLASSWORLDS_CONF + "' property to a valid configuration file or resource name.");
+            // Unreachable statement, ^^^ throws Error w/message
+            throw new Error();
+        }
+
+        debug("Resolved " + CLASSWORLDS_CONF + ": " + configUrl);
+
+        launcher.configure(configUrl.openStream());
+
+        try {
+            launcher.launch(args);
+        }
+        catch (InvocationTargetException e) {
+            throw new LaunchFailedError(e.getTargetException());
+        }
+
+        return launcher.getExitCode();
+    }
+
+    public static void main(final String[] args) {
+        assert args != null;
+
+        try {
+            configure();
+
+            int exitCode = mainWithExitCode(args);
+
+            System.exit(exitCode);
+        }
+        catch (Throwable t) {
+            t.printStackTrace(System.err);
+            System.err.flush();
+            System.exit(100);
+        }
+    }
+
+    //
+    // LaunchFailedError
+    //
+    
+    private static class LaunchFailedError
+        extends Error
+    {
+        public LaunchFailedError(final Throwable cause) {
+            super(cause);
+        }
+
+        public LaunchFailedError(final String msg) {
+            super(msg);
+        }
     }
 }

Added: geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/classworlds.conf
URL: http://svn.apache.org/viewvc/geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/classworlds.conf?rev=699610&view=auto
==============================================================================
--- geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/classworlds.conf (added)
+++ geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/classworlds.conf Sat Sep 27 02:49:27 2008
@@ -0,0 +1,29 @@
+##
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements.  See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership.  The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License.  You may obtain a copy of the License at
+##
+##  http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied.  See the License for the
+## specific language governing permissions and limitations
+## under the License.
+##
+
+##
+## $Rev$ $Date$
+##
+
+main is org.apache.geronimo.gshell.cli.Main from gshell.launcher
+
+[gshell.launcher]
+    load ${gshell.home}/etc
+    load ${gshell.home}/lib/*.jar
+

Propchange: geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/classworlds.conf
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/classworlds.conf
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/classworlds.conf
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/log4j.xml
URL: http://svn.apache.org/viewvc/geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/log4j.xml?rev=699610&view=auto
==============================================================================
--- geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/log4j.xml (added)
+++ geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/log4j.xml Sat Sep 27 02:49:27 2008
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+
+<!-- $Rev$ $Date$ -->
+
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+        
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+        <param name="Target" value="System.out"/>
+        <param name="Threshold" value="${gshell.log.console.level}"/>
+        <layout class="org.apache.log4j.PatternLayout">
+            <param name="ConversionPattern" value="%-5p %-25.30c{1} [%t] %m%n"/>
+        </layout>
+    </appender>
+    
+    <appender name="FILE" class="org.apache.log4j.FileAppender">
+        <param name="File" value="${gshell.home}/log/gshell.log"/>
+        <param name="Append" value="false"/>
+        <param name="Threshold" value="${gshell.log.console.level}"/>
+        <layout class="org.apache.log4j.PatternLayout">
+            <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p (%t) [%c] %m%n"/>
+        </layout>
+    </appender>
+
+    <root>
+        <level value="${gshell.log.console.level}"/>
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE"/>
+    </root>
+
+</log4j:configuration>
\ No newline at end of file

Propchange: geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/log4j.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/log4j.xml
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: geronimo/gshell/trunk/gshell-bootstrap/src/main/resources/org/apache/geronimo/gshell/bootstrap/log4j.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Modified: geronimo/gshell/trunk/gshell-cli/src/main/java/org/apache/geronimo/gshell/cli/Main.java
URL: http://svn.apache.org/viewvc/geronimo/gshell/trunk/gshell-cli/src/main/java/org/apache/geronimo/gshell/cli/Main.java?rev=699610&r1=699609&r2=699610&view=diff
==============================================================================
--- geronimo/gshell/trunk/gshell-cli/src/main/java/org/apache/geronimo/gshell/cli/Main.java (original)
+++ geronimo/gshell/trunk/gshell-cli/src/main/java/org/apache/geronimo/gshell/cli/Main.java Sat Sep 27 02:49:27 2008
@@ -257,16 +257,9 @@
         System.exit(code);
     }
 
-    public static void main(final String[] args) {
-        try {
-            Main main = new Main();
-            main.boot(args);
-        }
-        catch (Throwable t) {
-            // Avoid ugly/confusing classworlds muck when an exception occurs which is not handled
-            t.printStackTrace(System.err);
-            System.err.flush();
-        }
+    public static void main(final String[] args) throws Exception {
+        Main main = new Main();
+        main.boot(args);
     }
 }
 

Modified: geronimo/gshell/trunk/gshell-wisdom/gshell-wisdom-core/src/main/java/org/apache/geronimo/gshell/wisdom/command/CommandMessageSource.java
URL: http://svn.apache.org/viewvc/geronimo/gshell/trunk/gshell-wisdom/gshell-wisdom-core/src/main/java/org/apache/geronimo/gshell/wisdom/command/CommandMessageSource.java?rev=699610&r1=699609&r2=699610&view=diff
==============================================================================
--- geronimo/gshell/trunk/gshell-wisdom/gshell-wisdom-core/src/main/java/org/apache/geronimo/gshell/wisdom/command/CommandMessageSource.java (original)
+++ geronimo/gshell/trunk/gshell-wisdom/gshell-wisdom-core/src/main/java/org/apache/geronimo/gshell/wisdom/command/CommandMessageSource.java Sat Sep 27 02:49:27 2008
@@ -41,6 +41,11 @@
         this.command = command;
     }
 
+    //
+    // FIXME: See if we can use more gshell: ns glue to automatically configure this message source to *NOT* require the Action instance,
+    //        only use the class-name, that should speed up help rendering a lot.
+    //
+    
     private MessageSource getMessages() {
         if (messages == null) {
             assert command != null;