Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forbidden characters in Groovy script filenames?

I have written a tiny Groovy script (just a few simple instructions) and named it a-b.groovy.
My colleague has trouble running it and said:

I believe '-' is illegal in Groovy scripts filenames

Question: What is the complete list of characters that are illegal in Groovy filenames?

(Note: Unlike Naming convention for groovy script files, my question is not about conventions)

like image 540
Nicolas Raoul Avatar asked Dec 24 '22 06:12

Nicolas Raoul


2 Answers

The most accurate answer is to use the same standards for naming Groovy scripts as we use for naming Java classes. Groovy, similarly to Java supports Unicode characters encoding and you can most probably use any Unicode character as a script name (it doesn't mean you should do it).

Every Groovy script gets compiled to a Java class that extends groovy.lang.Script class. Its name is taken from a Groovy script file name. Take a look at this example:

someSimpleGroovyScript.groovy

println "test"

When we compile it with groovyc someSimpleGroovyScript.groovy we will see a class file someSimpleGroovyScript.class. Now if we take a look what does this class look like:

javap someSimpleGroovyScript

we will get something like this:

Compiled from "someSimpleGroovyScript.groovy"
public class someSimpleGroovyScript extends groovy.lang.Script {
  public static transient boolean __$stMC;
  public someSimpleGroovyScript();
  public someSimpleGroovyScript(groovy.lang.Binding);
  public static void main(java.lang.String...);
  public java.lang.Object run();
  protected groovy.lang.MetaClass $getStaticMetaClass();
}


Corner cases for Groovy script names

Even though Java class naming standards apply to Groovy script names, there are some corner cases that Groovy supports.

Using - character in the script name

You can name your script as a-b.groovy and run as a Groovy script:

groovy a-b.groovy

You can even compile it with groovyc to get following Java class:

Compiled from "a-b.groovy"
public class a-b extends groovy.lang.Script {
  public static transient boolean __$stMC;
  public a-b();
  public a-b(groovy.lang.Binding);
  public static void main(java.lang.String...);
  public java.lang.Object run();
  protected groovy.lang.MetaClass $getStaticMetaClass();
}

Even though this class name incorrect for Java compiler, you can still run it with Java (you need to add groovy-all to the classpath):

java -classpath ".:./groovy-all-2.4.12.jar" a-b

Using $ in the script name

In Groovy you can even call your script as 123$.groovy and you can simply run it as:

groovy 123\$.groovy

Groovy compiler however will replace $ with underscore when compiling this script to Java class:

javap 123_

Output:

Compiled from "123$.groovy"
public class 123_ extends groovy.lang.Script {
  public static transient boolean __$stMC;
  public 123_();
  public 123_(groovy.lang.Binding);
  public static void main(java.lang.String...);
  public java.lang.Object run();
  protected groovy.lang.MetaClass $getStaticMetaClass();
}

You can still run such compiled script with Java:

java -classpath ".:./groovy-all-2.4.12.jar" 123_

Using space in the script name

You can also use a space in your script name, e.g. this is script.groovy can be executed as:

groovy this\ is\ script.groovy

Groovy compiler however will replace every space with a underscore:

Compiled from "this is script.groovy"
public class this_is_script extends groovy.lang.Script {
  public static transient boolean __$stMC;
  public this_is_script();
  public this_is_script(groovy.lang.Binding);
  public static void main(java.lang.String...);
  public java.lang.Object run();
  protected groovy.lang.MetaClass $getStaticMetaClass();
}

You can still run such compiled script with Java:

java -classpath ".:./groovy-all-2.4.12.jar" this_is_script

Using class.groovy as a script name

It goes even further. You can create a script called class.groovy that will compile to a following Java class:

Compiled from "class.groovy"
public class class extends groovy.lang.Script {
  public static transient boolean __$stMC;
  public class();
  public class(groovy.lang.Binding);
  public static void main(java.lang.String...);
  public java.lang.Object run();
  protected groovy.lang.MetaClass $getStaticMetaClass();
}

javac compiler would never allow you compiling a class with such name, however java has no problems with running such bytecode:

java -classpath ".:./groovy-all-2.4.12.jar" class
like image 62
Szymon Stepniak Avatar answered Jan 04 '23 19:01

Szymon Stepniak


As the file name of the script is used to generate the corresponding class name, it would be restricted to valid java class names Valid characters in a Java class name

You can have almost any character, including most Unicode characters! The exact definition is in the Java Language Specification under section 3.8: Identifiers.

An identifier is an unlimited-length sequence of Java letters and Java digits, the first of which must be a Java letter. ...

Letters and digits may be drawn from the entire Unicode character set, ... This allows programmers to use identifiers in their programs that are written in their native languages.

An identifier cannot have the same spelling (Unicode character sequence) as a keyword (§3.9), boolean literal (§3.10.3), or the null literal (§3.10.7), or a compile-time error occurs.

like image 35
Michael Rutherfurd Avatar answered Jan 04 '23 20:01

Michael Rutherfurd