diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java index 026547b797c..87b1fc1c05c 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java @@ -18,8 +18,10 @@ package org.eclipse.jetty.start; +import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; +import java.io.FileReader; import java.io.IOException; import java.text.CollationKey; import java.text.Collator; @@ -30,12 +32,15 @@ import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Set; +import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.omg.CORBA.INITIALIZE; + /** * Represents a Module metadata, as defined in Jetty. */ -public class Module extends TextFile +public class Module // extends TextFile { public static class NameComparator implements Comparator { @@ -50,7 +55,7 @@ public class Module extends TextFile return k1.compareTo(k2); } } - + public static class DepthComparator implements Comparator { private Collator collator = Collator.getInstance(); @@ -71,6 +76,8 @@ public class Module extends TextFile } } + /** The file of the module */ + private File file; /** The name of this Module */ private String name; /** The depth of the module in the tree */ @@ -90,8 +97,7 @@ public class Module extends TextFile /** List of library options for this Module */ private List libs; /** List of downloads for this Module */ - private List downloads; - + private List downloads; /** Is this Module enabled via start.jar command line, start.ini, or start.d/*.ini ? */ private boolean enabled = false; @@ -100,11 +106,14 @@ public class Module extends TextFile public Module(File file) throws FileNotFoundException, IOException { - super(file); + this.file = file; String name = file.getName(); // Strip .ini name = Pattern.compile(".mod$",Pattern.CASE_INSENSITIVE).matcher(name).replaceFirst(""); + + init(); + process(); } public void addChildEdge(Module child) @@ -201,12 +210,12 @@ public class Module extends TextFile { return initialise; } - + public List getDownloads() { return downloads; } - + @Override public int hashCode() { @@ -216,22 +225,21 @@ public class Module extends TextFile return result; } - @Override public void init() { - String name = getFile().getName(); + String name = file.getName(); // Strip .ini this.name = Pattern.compile(".mod$",Pattern.CASE_INSENSITIVE).matcher(name).replaceFirst(""); - parentNames=new HashSet<>(); - optionalParentNames=new HashSet<>(); - parentEdges=new HashSet<>(); - childEdges=new HashSet<>(); - xmls=new ArrayList<>(); - initialise=new ArrayList<>(); - libs=new ArrayList<>(); - downloads=new ArrayList<>(); + parentNames = new HashSet<>(); + optionalParentNames = new HashSet<>(); + parentEdges = new HashSet<>(); + childEdges = new HashSet<>(); + xmls = new ArrayList<>(); + initialise = new ArrayList<>(); + libs = new ArrayList<>(); + downloads = new ArrayList<>(); } public boolean isEnabled() @@ -239,61 +247,70 @@ public class Module extends TextFile return enabled; } - @Override - public void process(String line) + public void process() throws FileNotFoundException, IOException { - boolean handled = false; + Pattern section = Pattern.compile("\\s*\\[([^]]*)\\]\\s*"); - if (line == null) + if (!FS.canReadFile(file)) { - - } - - // has assignment - int idx = line.indexOf('='); - if (idx >= 0) - { - String key = line.substring(0,idx); - String value = line.substring(idx + 1); - - switch (key.toUpperCase(Locale.ENGLISH)) - { - case "DEPEND": - parentNames.add(value); - handled = true; - break; - case "LIB": - libs.add(value); - handled = true; - break; - case "OPTIONAL": - optionalParentNames.add(value); - handled = true; - break; - case "DOWNLOAD": - downloads.add(value); - handled = true; - break; - case "INI": - initialise.add(value); - handled = true; - break; - } - } - - if (handled) - { - return; // no further processing of line needed - } - - // Is it an XML line? - if (FS.isXml(line)) - { - xmls.add(line); + StartLog.debug("Skipping read of missing file: %s",file.getAbsolutePath()); return; } - throw new IllegalArgumentException("Unrecognized Module Metadata line [" + line + "] in Module file [" + getFile() + "]"); + try (FileReader reader = new FileReader(file)) + { + try (BufferedReader buf = new BufferedReader(reader)) + { + String line; + String sectionType = ""; + while ((line = buf.readLine()) != null) + { + line = line.trim(); + Matcher sectionMatcher = section.matcher(line); + + if (sectionMatcher.matches()) + { + sectionType = sectionMatcher.group(1).trim().toUpperCase(); + } + else + { + System.out.println("Processing: " + line); + // blank lines and comments are valid for initialize section + if (line.length() == 0 || line.startsWith("#")) + { + if ("INI".equals(sectionType)) + { + initialise.add(line); + } + } + else + { + switch (sectionType) + { + case "DEPEND": + parentNames.add(line); + break; + case "LIB": + libs.add(line); + break; + case "XML": + xmls.add(line); + break; + case "OPTIONAL": + optionalParentNames.add(line); + break; + case "DOWNLOAD": + downloads.add(line); + break; + case "INI": + initialise.add(line); + break; + } + } + } + } + } + } } public void setDepth(int depth) @@ -310,17 +327,17 @@ public class Module extends TextFile { this.sources.addAll(sources); } - + public void clearSources() { this.sources.clear(); } - + public Set getSources() { return Collections.unmodifiableSet(sources); } - + @Override public String toString() { @@ -333,5 +350,4 @@ public class Module extends TextFile str.append(']'); return str.toString(); } - } diff --git a/jetty-start/src/test/resources/jetty home with spaces/modules/base.mod b/jetty-start/src/test/resources/jetty home with spaces/modules/base.mod index 7d52330120e..f14d52a29c1 100644 --- a/jetty-start/src/test/resources/jetty home with spaces/modules/base.mod +++ b/jetty-start/src/test/resources/jetty home with spaces/modules/base.mod @@ -1 +1,2 @@ -LIB=lib/example*with spaces.jar \ No newline at end of file +[lib] +lib/example*with spaces.jar \ No newline at end of file diff --git a/jetty-start/src/test/resources/usecases/base.with.db/modules/db.mod b/jetty-start/src/test/resources/usecases/base.with.db/modules/db.mod index 444d0eeeecc..5acded8b285 100644 --- a/jetty-start/src/test/resources/usecases/base.with.db/modules/db.mod +++ b/jetty-start/src/test/resources/usecases/base.with.db/modules/db.mod @@ -1,8 +1,11 @@ -DEPEND=deploy -DEPEND=jndi -DEPEND=plus +[depend] +deploy +jndi +plus -LIB=lib/db/*.jar +[lib] +lib/db/*.jar +[xml] etc/jetty-db.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/annotations.mod b/jetty-start/src/test/resources/usecases/home/modules/annotations.mod index 3470bf75c79..65e4654127d 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/annotations.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/annotations.mod @@ -2,13 +2,16 @@ # Jetty Annotation Scanning Module # +[depend] # Annotations needs plus, and jndi features -DEPEND=plus +plus +[lib] # Annotations needs jetty annotation jars -LIB=lib/jetty-annotations-${jetty.version}.jar +lib/jetty-annotations-${jetty.version}.jar # Need annotation processing jars too -LIB=lib/annotations/*.jar +lib/annotations/*.jar +[xml] # Enable annotation scanning webapp configurations etc/jetty-annotations.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/base.mod b/jetty-start/src/test/resources/usecases/home/modules/base.mod index d3e2ab8fd04..ad8ea320882 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/base.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/base.mod @@ -2,7 +2,10 @@ # Base Module # -OPTIONAL=jmx +[optional] +# JMX is optional, if it appears in the module tree then depend on it +jmx -LIB=lib/jetty-util-${jetty.version}.jar -LIB=lib/jetty-io-${jetty.version}.jar +[lib] +lib/jetty-util-${jetty.version}.jar +lib/jetty-io-${jetty.version}.jar diff --git a/jetty-start/src/test/resources/usecases/home/modules/client.mod b/jetty-start/src/test/resources/usecases/home/modules/client.mod index f434cdc0870..6788eacf79c 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/client.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/client.mod @@ -2,5 +2,6 @@ # Client Feature # +[lib] # Client jars -LIB=lib/jetty-client-${jetty.version}.jar +lib/jetty-client-${jetty.version}.jar diff --git a/jetty-start/src/test/resources/usecases/home/modules/debug.mod b/jetty-start/src/test/resources/usecases/home/modules/debug.mod index 8cdf5b94ab6..f740ea2c762 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/debug.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/debug.mod @@ -2,6 +2,8 @@ # Debug module # -DEPEND=server +[depend] +server +[xml] etc/jetty-debug.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/deploy.mod b/jetty-start/src/test/resources/usecases/home/modules/deploy.mod index 47fc62c1774..94c0e403168 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/deploy.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/deploy.mod @@ -2,10 +2,13 @@ # Deploy Feature # -DEPEND=webapp +[depend] +webapp +[lib] # Deploy jars -LIB=lib/jetty-deploy-${jetty.version}.jar +lib/jetty-deploy-${jetty.version}.jar +[xml] # Deploy configuration etc/jetty-deploy.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/http.mod b/jetty-start/src/test/resources/usecases/home/modules/http.mod index 94eed962e9b..85154141acc 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/http.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/http.mod @@ -2,6 +2,8 @@ # Jetty HTTP Server # -DEPEND=server +[depend] +server +[xml] etc/jetty-http.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/https.mod b/jetty-start/src/test/resources/usecases/home/modules/https.mod index 5e930e934f7..281c5dba040 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/https.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/https.mod @@ -2,7 +2,9 @@ # Jetty HTTP Server # -DEPEND=server +[depend] +server +[xml] etc/jetty-ssl.xml etc/jetty-https.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/ipaccess.mod b/jetty-start/src/test/resources/usecases/home/modules/ipaccess.mod index f99f26ec3e3..956ea0f2e3a 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/ipaccess.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/ipaccess.mod @@ -2,6 +2,8 @@ # IPAccess module # -DEPEND=server +[depend] +server +[xml] etc/jetty-ipaccess.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/jaas.mod b/jetty-start/src/test/resources/usecases/home/modules/jaas.mod index 2a608c74874..9fb04f7a57d 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/jaas.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/jaas.mod @@ -2,10 +2,13 @@ # JAAS Feature # -DEPEND=server +[depend] +server +[lib] # JAAS jars -LIB=lib/jetty-jaas-${jetty.version}.jar +lib/jetty-jaas-${jetty.version}.jar +[xml] # JAAS configuration etc/jetty-jaas.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/jmx.mod b/jetty-start/src/test/resources/usecases/home/modules/jmx.mod index 2a7922690e9..fd8740ae8d7 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/jmx.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/jmx.mod @@ -2,8 +2,10 @@ # JMX Feature # +[lib] # JMX jars (as defined in start.config) -LIB=lib/jetty-jmx-${jetty.version}.jar +lib/jetty-jmx-${jetty.version}.jar +[xml] # JMX configuration etc/jetty-jmx.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/jndi.mod b/jetty-start/src/test/resources/usecases/home/modules/jndi.mod index cfdcc526142..33c077ce684 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/jndi.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/jndi.mod @@ -2,8 +2,10 @@ # JNDI Support # -DEPEND=server +[depend] +server -LIB=lib/jetty-jndi-${jetty.version}.jar -LIB=lib/jndi/*.jar +[lib] +lib/jetty-jndi-${jetty.version}.jar +lib/jndi/*.jar diff --git a/jetty-start/src/test/resources/usecases/home/modules/jsp.mod b/jetty-start/src/test/resources/usecases/home/modules/jsp.mod index d24dddf44d5..f85530d3c8a 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/jsp.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/jsp.mod @@ -2,7 +2,9 @@ # Jetty Servlet Module # -DEPEND=servlet +[depend] +servlet -LIB=lib/jsp/*.jar +[lib] +lib/jsp/*.jar diff --git a/jetty-start/src/test/resources/usecases/home/modules/lowresources.mod b/jetty-start/src/test/resources/usecases/home/modules/lowresources.mod index 578d8165edd..4ca96de10ee 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/lowresources.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/lowresources.mod @@ -2,6 +2,8 @@ # Low Resources module # -DEPEND=server +[depend] +server +[xml] etc/jetty-lowresources.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/monitor.mod b/jetty-start/src/test/resources/usecases/home/modules/monitor.mod index 249ccef15d1..67f006d0c4c 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/monitor.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/monitor.mod @@ -2,9 +2,12 @@ # Jetty Monitor module # -DEPEND=server -DEPEND=client +[depend] +server +client -LIB=lib/jetty-monitor-${jetty.version}.jar +[lib] +lib/jetty-monitor-${jetty.version}.jar +[xml] etc/jetty-monitor.xml \ No newline at end of file diff --git a/jetty-start/src/test/resources/usecases/home/modules/npn.mod b/jetty-start/src/test/resources/usecases/home/modules/npn.mod index c32988666a4..1f2856c73e0 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/npn.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/npn.mod @@ -1,4 +1,6 @@ -DOWNLOAD=http://repo1.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.5.v20130313/npn-boot-1.1.5.v20130313.jar:lib/npn/npn-boot-1.1.5.v20130313.jar +[download] +http://repo1.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.5.v20130313/npn-boot-1.1.5.v20130313.jar:lib/npn/npn-boot-1.1.5.v20130313.jar -INI=-Xbootclasspath/p:lib/npn/npn-boot-1.1.5.v20130313.jar \ No newline at end of file +[ini] +-Xbootclasspath/p:lib/npn/npn-boot-1.1.5.v20130313.jar \ No newline at end of file diff --git a/jetty-start/src/test/resources/usecases/home/modules/plus.mod b/jetty-start/src/test/resources/usecases/home/modules/plus.mod index caa799376a6..b781f00bf2f 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/plus.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/plus.mod @@ -2,11 +2,14 @@ # Jetty Proxy module # -DEPEND=server -DEPEND=security -DEPEND=jndi +[depend] +server +security +jndi -LIB=lib/jetty-plus-${jetty.version}.jar +[lib] +lib/jetty-plus-${jetty.version}.jar +[xml] # Plus requires configuration etc/jetty-plus.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/proxy.mod b/jetty-start/src/test/resources/usecases/home/modules/proxy.mod index 5ab6e70a880..7873329afaa 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/proxy.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/proxy.mod @@ -2,10 +2,13 @@ # Jetty Proxy module # -DEPEND=server -DEPEND=client +[depend] +server +client -LIB=lib/jetty-proxy-${jetty.version}.jar +[lib] +lib/jetty-proxy-${jetty.version}.jar +[xml] # Proxy requires configuration etc/jetty-proxy.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/requestlog.mod b/jetty-start/src/test/resources/usecases/home/modules/requestlog.mod index 060ca9f0a22..2b048dbc767 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/requestlog.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/requestlog.mod @@ -2,6 +2,8 @@ # Request Log module # -DEPEND=server +[depend] +server +[xml] etc/jetty-requestlog.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/rewrite.mod b/jetty-start/src/test/resources/usecases/home/modules/rewrite.mod index d5ccf960410..85fe5f090d1 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/rewrite.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/rewrite.mod @@ -2,9 +2,12 @@ # Jetty Rewrite module # -DEPEND=server +[depend] +server -LIB=lib/jetty-rewrite-${jetty.version}.jar +[lib] +lib/jetty-rewrite-${jetty.version}.jar +[xml] # Annotations needs annotations configuration etc/jetty-rewrite.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/security.mod b/jetty-start/src/test/resources/usecases/home/modules/security.mod index 5a3c4a368a6..ba3163275f5 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/security.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/security.mod @@ -2,6 +2,8 @@ # Jetty Security Module # -DEPEND=server +[depend] +server -LIB=lib/jetty-security-${jetty.version}.jar +[lib] +lib/jetty-security-${jetty.version}.jar diff --git a/jetty-start/src/test/resources/usecases/home/modules/server.mod b/jetty-start/src/test/resources/usecases/home/modules/server.mod index aa6cad6b0e6..d0c2de35d74 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/server.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/server.mod @@ -2,14 +2,17 @@ # Base server # -DEPEND=base -DEPEND=xml +[depend] +base +xml -LIB=lib/servlet-api-3.1.jar -LIB=lib/jetty-schemas-3.1.jar -LIB=lib/jetty-http-${jetty.version}.jar -LIB=lib/jetty-continuation-${jetty.version}.jar -LIB=lib/jetty-server-${jetty.version}.jar +[lib] +lib/servlet-api-3.1.jar +lib/jetty-schemas-3.1.jar +lib/jetty-http-${jetty.version}.jar +lib/jetty-continuation-${jetty.version}.jar +lib/jetty-server-${jetty.version}.jar +[xml] # Annotations needs annotations configuration etc/jetty.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/servlet.mod b/jetty-start/src/test/resources/usecases/home/modules/servlet.mod index a427eed5478..fdb65c57a16 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/servlet.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/servlet.mod @@ -2,6 +2,8 @@ # Jetty Servlet Module # -DEPEND=server +[depend] +server -LIB=lib/jetty-servlet-${jetty.version}.jar +[lib] +lib/jetty-servlet-${jetty.version}.jar diff --git a/jetty-start/src/test/resources/usecases/home/modules/spdy.mod b/jetty-start/src/test/resources/usecases/home/modules/spdy.mod index cd45fad3a8e..92e31a2b231 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/spdy.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/spdy.mod @@ -1,8 +1,11 @@ -DEPEND=server -DEPEND=npn +[depend] +server +npn -LIB=lib/spdy/*.jar +[lib] +lib/spdy/*.jar +[xml] etc/jetty-ssl.xml etc/jetty-spdy.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/stats.mod b/jetty-start/src/test/resources/usecases/home/modules/stats.mod index cd56d5b4d7b..0922469cdfb 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/stats.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/stats.mod @@ -2,6 +2,8 @@ # Stats module # -DEPEND=server +[depend] +server +[xml] etc/jetty-stats.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/webapp.mod b/jetty-start/src/test/resources/usecases/home/modules/webapp.mod index c39d5aae063..f62c5545555 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/webapp.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/webapp.mod @@ -2,6 +2,8 @@ # Base server # -DEPEND=servlet +[depend] +servlet -LIB=lib/jetty-webapp-${jetty.version}.jar +[lib] +lib/jetty-webapp-${jetty.version}.jar diff --git a/jetty-start/src/test/resources/usecases/home/modules/websocket.mod b/jetty-start/src/test/resources/usecases/home/modules/websocket.mod index a74a1072ac2..f45babd8863 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/websocket.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/websocket.mod @@ -3,12 +3,15 @@ # # WebSocket needs Annotations feature -DEPEND=server -DEPEND=annotations +[depend] +server +annotations # WebSocket needs websocket jars (as defined in start.config) -LIB=lib/websocket/*.jar +[lib] +lib/websocket/*.jar # WebSocket needs websocket configuration +[xml] etc/jetty-websockets.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/xinetd.mod b/jetty-start/src/test/resources/usecases/home/modules/xinetd.mod index c93064ad767..fdc1b3c7b00 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/xinetd.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/xinetd.mod @@ -2,6 +2,8 @@ # Stats module # -DEPEND=server +[depend] +server +[xml] etc/jetty-xinetd.xml diff --git a/jetty-start/src/test/resources/usecases/home/modules/xml.mod b/jetty-start/src/test/resources/usecases/home/modules/xml.mod index 949e2057117..d53107a84f5 100644 --- a/jetty-start/src/test/resources/usecases/home/modules/xml.mod +++ b/jetty-start/src/test/resources/usecases/home/modules/xml.mod @@ -2,7 +2,9 @@ # Jetty XML Configuration # -DEPEND=base +[depend] +base -LIB=lib/jetty-xml-${jetty.version}.jar +[lib] +lib/jetty-xml-${jetty.version}.jar