22
33import com .github .tomaslanger .chalk .Chalk ;
44import com .github .tomaslanger .cli .choice .SingleChoice ;
5+ import java .io .BufferedInputStream ;
56import java .io .File ;
7+ import java .io .FileInputStream ;
8+ import java .io .FileNotFoundException ;
9+ import java .io .FileOutputStream ;
610import java .io .IOException ;
711import java .io .InputStream ;
812import java .io .PrintStream ;
913import java .io .UnsupportedEncodingException ;
1014import java .nio .file .Files ;
1115import java .util .ArrayList ;
16+ import java .util .Date ;
17+ import java .util .Enumeration ;
1218import java .util .List ;
1319import java .util .Properties ;
1420import java .util .Scanner ;
21+ import java .util .jar .JarEntry ;
22+ import java .util .jar .JarFile ;
23+ import java .util .jar .JarOutputStream ;
24+ import java .util .jar .Manifest ;
1525import java .util .logging .Level ;
1626import java .util .logging .Logger ;
1727import java .util .regex .Matcher ;
1828import java .util .regex .Pattern ;
1929import javax .sound .midi .SysexMessage ;
30+ import javax .xml .crypto .Data ;
2031import net .sourceforge .argparse4j .ArgumentParsers ;
2132import net .sourceforge .argparse4j .impl .Arguments ;
2233import static net .sourceforge .argparse4j .impl .Arguments .storeTrue ;
@@ -126,6 +137,22 @@ private static void run(String[] args) {
126137 .dest ("extra_args" )
127138 .help ("Pass-through args" );
128139
140+ var lib = subparsers .addParser ("lib" )
141+ .defaultHelp (true )
142+ .help ("Build sources into a lib" );
143+
144+ lib .addArgument ("--new" )
145+ .action (storeTrue ())
146+ .help ("Create a new jar file" );
147+
148+ lib .addArgument ("--ls" )
149+ .action (storeTrue ())
150+ .help ("Lists the contents of the jar file" );
151+
152+ lib .addArgument ("file" )
153+ .nargs ("?" ) // Optional
154+ .help ("The directory to build a lib from or the lib to work with" );
155+
129156 parser .addArgument ("--version" ).action (Arguments .version ());
130157
131158 // optional: glmr help
@@ -148,6 +175,31 @@ private static void run(String[] args) {
148175 }
149176 }
150177
178+ if ("lib" .equals (command )) {
179+ var input = res .getString ("file" );
180+ if (input == null ) {
181+ System .out .println ("No input directory or file" );
182+ return ;
183+ }
184+
185+ if (res .getBoolean ("new" )) {
186+ createJarFile (input );
187+ return ;
188+ }
189+
190+ if (res .getBoolean ("ls" )) {
191+ if (!input .endsWith (".jar" )) {
192+ System .out .println ("Invalid library archive file" );
193+ return ;
194+ }
195+
196+ printLib (input );
197+ return ;
198+ }
199+
200+
201+ }
202+
151203 if ("build" .equals (command )) {
152204 /*System.out.println("==> build:");
153205 System.out.println("Emit: " + res.getBoolean("emit"));
@@ -404,4 +456,83 @@ private static void createNewProject() {
404456 return ;
405457 }
406458 }
459+
460+ private static void createJarFile (String input ) {
461+ var inputFile = new File (input );
462+ var outputFile = new File (inputFile .getName () + ".jar" );
463+
464+ String baseName = inputFile .getName ();
465+
466+
467+ // Create custom manifest
468+ Manifest manifest = new Manifest ();
469+ var attr = manifest .getMainAttributes ();
470+ attr .putValue ("Manifest-Version" , "1.0" );
471+ attr .putValue ("PiccodeScript-Version" , "" + VERSION );
472+ attr .putValue ("Library-Name" , inputFile .getName ());
473+ attr .putValue ("Library-Type" , "PiccodeScript-Native" );
474+ attr .putValue ("Build-Date" , new Date ().toString ());
475+
476+ try (JarOutputStream jos = new JarOutputStream (new FileOutputStream (outputFile ), manifest )) {
477+ addToJar (inputFile , baseName ,jos );
478+ } catch (FileNotFoundException ex ) {
479+ } catch (IOException ex ) {
480+ }
481+
482+ System .out .println ("JAR with custom manifest created!" );
483+ }
484+
485+
486+ private static void addToJar (File file , String baseName , JarOutputStream jos ) throws IOException {
487+ String entryName = baseName + file .getPath ()
488+ .substring (new File (baseName ).getPath ().length ()) // relative to base
489+ .replace ("\\ " , "/" );
490+
491+ if (file .isDirectory ()) {
492+ if (!entryName .endsWith ("/" )) {
493+ entryName += "/" ;
494+ }
495+ JarEntry dirEntry = new JarEntry (entryName );
496+ jos .putNextEntry (dirEntry );
497+ jos .closeEntry ();
498+
499+ for (File child : file .listFiles ()) {
500+ addToJar (child , baseName , jos );
501+ }
502+ } else {
503+ JarEntry fileEntry = new JarEntry (entryName );
504+ jos .putNextEntry (fileEntry );
505+ try (BufferedInputStream in = new BufferedInputStream (new FileInputStream (file ))) {
506+ byte [] buffer = new byte [1024 ];
507+ int count ;
508+ while ((count = in .read (buffer )) != -1 ) {
509+ jos .write (buffer , 0 , count );
510+ }
511+ }
512+ jos .closeEntry ();
513+ }
514+ }
515+
516+
517+
518+ private static void printLib (String path ) {
519+ File jarPath = new File (path );
520+ try (JarFile jarFile = new JarFile (jarPath )) {
521+
522+ // Print manifest entries
523+ Manifest manifest = jarFile .getManifest ();
524+ System .out .println ("Manifest contents:" );
525+ manifest .getMainAttributes ().forEach ((k , v ) -> System .out .println (k + ": " + v ));
526+
527+ // Print files in jar
528+ System .out .println ("\n Sources:" );
529+ Enumeration <JarEntry > entries = jarFile .entries ();
530+ while (entries .hasMoreElements ()) {
531+ JarEntry entry = entries .nextElement ();
532+ System .out .println (" - " + entry .getName ());
533+ }
534+ } catch (IOException ex ) {
535+ System .getLogger (Piccode .class .getName ()).log (System .Logger .Level .ERROR , (String ) null , ex );
536+ }
537+ }
407538}
0 commit comments