From 4677ca31f428d9e62a1f1b61dd125f5c5bcdb58f Mon Sep 17 00:00:00 2001 From: mkyong Date: Tue, 28 Sep 2021 19:29:58 +0800 Subject: [PATCH 01/15] Java 17 --- java-17/pom.xml | 38 +++++++++ .../main/java/com/mkyong/java17/HelloApp.java | 9 +++ .../java/com/mkyong/java17/jep356/JEP356.java | 36 +++++++++ .../java/com/mkyong/java17/jep406/JEP406.java | 63 +++++++++++++++ .../com/mkyong/java17/jep406/JEP406_2.java | 49 ++++++++++++ .../com/mkyong/java17/jep415/DdosExample.java | 10 +++ .../java17/jep415/JComponentExample.java | 7 ++ .../java/com/mkyong/java17/jep415/JEP290.java | 49 ++++++++++++ .../com/mkyong/java17/jep415/JEP290_B.java | 48 +++++++++++ .../java/com/mkyong/java17/jep415/JEP415.java | 41 ++++++++++ .../com/mkyong/java17/jep415/JEP415_B.java | 79 +++++++++++++++++++ java-17/src/main/resources/test.html | 5 ++ 12 files changed, 434 insertions(+) create mode 100644 java-17/pom.xml create mode 100644 java-17/src/main/java/com/mkyong/java17/HelloApp.java create mode 100644 java-17/src/main/java/com/mkyong/java17/jep356/JEP356.java create mode 100644 java-17/src/main/java/com/mkyong/java17/jep406/JEP406.java create mode 100644 java-17/src/main/java/com/mkyong/java17/jep406/JEP406_2.java create mode 100644 java-17/src/main/java/com/mkyong/java17/jep415/DdosExample.java create mode 100644 java-17/src/main/java/com/mkyong/java17/jep415/JComponentExample.java create mode 100644 java-17/src/main/java/com/mkyong/java17/jep415/JEP290.java create mode 100644 java-17/src/main/java/com/mkyong/java17/jep415/JEP290_B.java create mode 100644 java-17/src/main/java/com/mkyong/java17/jep415/JEP415.java create mode 100644 java-17/src/main/java/com/mkyong/java17/jep415/JEP415_B.java create mode 100644 java-17/src/main/resources/test.html diff --git a/java-17/pom.xml b/java-17/pom.xml new file mode 100644 index 0000000..0c1c6e0 --- /dev/null +++ b/java-17/pom.xml @@ -0,0 +1,38 @@ + + 4.0.0 + com.mkyong + java17 + 1.0 + + java-17 + https://www.mkyong.com + + + UTF-8 + 17 + 17 + 17 + + + + + + + java17 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 17 + 17 + --enable-preview + + + + + diff --git a/java-17/src/main/java/com/mkyong/java17/HelloApp.java b/java-17/src/main/java/com/mkyong/java17/HelloApp.java new file mode 100644 index 0000000..35cd61a --- /dev/null +++ b/java-17/src/main/java/com/mkyong/java17/HelloApp.java @@ -0,0 +1,9 @@ +package com.mkyong.java17; + +public class HelloApp { + + public static void main(String[] args) { + System.out.println("Hello Java 17"); + } + +} \ No newline at end of file diff --git a/java-17/src/main/java/com/mkyong/java17/jep356/JEP356.java b/java-17/src/main/java/com/mkyong/java17/jep356/JEP356.java new file mode 100644 index 0000000..3bacb84 --- /dev/null +++ b/java-17/src/main/java/com/mkyong/java17/jep356/JEP356.java @@ -0,0 +1,36 @@ +package com.mkyong.java17.jep356; + +import java.security.Security; +import java.util.random.RandomGenerator; +import java.util.random.RandomGeneratorFactory; + +public class JEP356 { + + public static void main(String[] args) { + + // RandomGeneratorFactory.of("Random").create(42); + + // default L32X64MixRandom + // RandomGenerator randomGenerator = RandomGeneratorFactory.getDefault().create(); + + // Passing the same seed to random, and then calling it will give you the same set of numbers + // seed = 999 + RandomGenerator randomGenerator = RandomGeneratorFactory.of("Xoshiro256PlusPlus").create(999); + + System.out.println(randomGenerator.getClass()); + + int counter = 0; + while(counter<=10){ + // 0-10 + int result = randomGenerator.nextInt(11); + System.out.println(result); + counter++; + } + + RandomGeneratorFactory.all() + .map(fac -> fac.group()+ " : " +fac.name()) + .sorted() + .forEach(System.out::println); + + } +} diff --git a/java-17/src/main/java/com/mkyong/java17/jep406/JEP406.java b/java-17/src/main/java/com/mkyong/java17/jep406/JEP406.java new file mode 100644 index 0000000..804c89e --- /dev/null +++ b/java-17/src/main/java/com/mkyong/java17/jep406/JEP406.java @@ -0,0 +1,63 @@ +package com.mkyong.java17.jep406; + +public class JEP406 { + + public static void main(String[] args) { + + System.out.println(formatterJava17("Java 17")); + System.out.println(formatterJava17(17)); + + testStringJava17("Java 16"); // Ok + testStringJava17("Java 11"); // LTS + testStringJava17(""); // Ok + testStringJava17(null); // Unknown! + } + + // check null, before Java 17 + static void testString(String s) { + if (s == null) { + System.out.println("Unknown!"); + return; + } + switch (s) { + case "Java 11", "Java 17" -> System.out.println("LTS"); + default -> System.out.println("Ok"); + } + } + + // check null, Java 17 + static void testStringJava17(String s) { + switch (s) { + case null -> System.out.println("Unknown!"); + case "Java 11", "Java 17" -> System.out.println("LTS"); + default -> System.out.println("Ok"); + } + } + + // if...else chain, before Java 17 + static String formatter(Object o) { + String formatted = "unknown"; + if (o instanceof Integer i) { + formatted = String.format("int %d", i); + } else if (o instanceof Long l) { + formatted = String.format("long %d", l); + } else if (o instanceof Double d) { + formatted = String.format("double %f", d); + } else if (o instanceof String s) { + formatted = String.format("String %s", s); + } + return formatted; + } + + // if...else chain, Java 17 + static String formatterJava17(Object o) { + return switch (o) { + case Integer i -> String.format("int %d", i); + case Long l -> String.format("long %d", l); + case Double d -> String.format("double %f", d); + case String s -> String.format("String %s", s); + default -> o.toString(); + }; + } + +} diff --git a/java-17/src/main/java/com/mkyong/java17/jep406/JEP406_2.java b/java-17/src/main/java/com/mkyong/java17/jep406/JEP406_2.java new file mode 100644 index 0000000..9d59031 --- /dev/null +++ b/java-17/src/main/java/com/mkyong/java17/jep406/JEP406_2.java @@ -0,0 +1,49 @@ +package com.mkyong.java17.jep406; + +public class JEP406_2 { + + public static void main(String[] args) { + + testTriangle(null); + testTriangle2(null); + + } + + class Shape {} + class Rectangle extends Shape {} + class Triangle extends Shape { + int calculateArea(){ + return 8; + } } + + static void testTriangle(Shape s) { + switch (s) { + case null: + break; + case Triangle t: + if (t.calculateArea() > 100) { + System.out.println("Large triangle"); + break; + }else{ + System.out.println("Triangle"); + } + default: + System.out.println("Unknown!"); + } + } + + static void testTriangle2(Shape s) { + switch (s) { + case null -> + {} + case Triangle t && (t.calculateArea() > 100) -> + System.out.println("Large triangle"); + case Triangle t -> + System.out.println("Triangle"); + default -> + System.out.println("Unknown!"); + } + } + +} + diff --git a/java-17/src/main/java/com/mkyong/java17/jep415/DdosExample.java b/java-17/src/main/java/com/mkyong/java17/jep415/DdosExample.java new file mode 100644 index 0000000..bea1f28 --- /dev/null +++ b/java-17/src/main/java/com/mkyong/java17/jep415/DdosExample.java @@ -0,0 +1,10 @@ +package com.mkyong.java17.jep415; + +import java.io.Serializable; + +public class DdosExample implements Serializable { + @Override + public String toString() { + return "running ddos...!"; + } +} diff --git a/java-17/src/main/java/com/mkyong/java17/jep415/JComponentExample.java b/java-17/src/main/java/com/mkyong/java17/jep415/JComponentExample.java new file mode 100644 index 0000000..da65099 --- /dev/null +++ b/java-17/src/main/java/com/mkyong/java17/jep415/JComponentExample.java @@ -0,0 +1,7 @@ +package com.mkyong.java17.jep415; + +import javax.swing.*; +import java.io.Serializable; + +public class JComponentExample extends JComponent implements Serializable { +} diff --git a/java-17/src/main/java/com/mkyong/java17/jep415/JEP290.java b/java-17/src/main/java/com/mkyong/java17/jep415/JEP290.java new file mode 100644 index 0000000..7a9fa99 --- /dev/null +++ b/java-17/src/main/java/com/mkyong/java17/jep415/JEP290.java @@ -0,0 +1,49 @@ +package com.mkyong.java17.jep415; + +import java.io.*; + +public class JEP290 { + + public static void main(String[] args) throws IOException { + + byte[] bytes = convertObjectToStream(new DdosExample()); + InputStream is = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(is); + + // Setting a Custom Filter Using a Pattern + // need full package path + // the maximum number of bytes in the input stream = 1024 + // allows classes in com.mkyong.java17.jep415.* + // allows classes in the java.base module + // rejects all other classes !* + ObjectInputFilter filter1 = + ObjectInputFilter.Config.createFilter( + "maxbytes=1024;com.mkyong.java17.jep415.*;java.base/*;!*"); + + /* reject com.mkyong.java17.jep415.* + ObjectInputFilter filter1 = + ObjectInputFilter.Config.createFilter( + "maxbytes=1024;!com.mkyong.java17.jep415.*;java.base/*;!*"); + */ + ois.setObjectInputFilter(filter1); + + try { + Object obj = ois.readObject(); + System.out.println("Read obj: " + obj); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + + private static byte[] convertObjectToStream(Object obj) { + ByteArrayOutputStream boas = new ByteArrayOutputStream(); + try (ObjectOutputStream ois = new ObjectOutputStream(boas)) { + ois.writeObject(obj); + return boas.toByteArray(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + throw new RuntimeException(); + } + +} diff --git a/java-17/src/main/java/com/mkyong/java17/jep415/JEP290_B.java b/java-17/src/main/java/com/mkyong/java17/jep415/JEP290_B.java new file mode 100644 index 0000000..5e7edb9 --- /dev/null +++ b/java-17/src/main/java/com/mkyong/java17/jep415/JEP290_B.java @@ -0,0 +1,48 @@ +package com.mkyong.java17.jep415; + +import javax.swing.*; +import java.io.*; + +public class JEP290_B { + + public static void main(String[] args) throws IOException { + + byte[] bytes = convertObjectToStream(new JComponentExample()); + InputStream is = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(is); + + ois.setObjectInputFilter(createObjectFilter()); + + try { + Object obj = ois.readObject(); + System.out.println("Read obj: " + obj); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + + // reject all JComponent classes + private static ObjectInputFilter createObjectFilter() { + return filterInfo -> { + Class clazz = filterInfo.serialClass(); + if (clazz != null) { + return (JComponent.class.isAssignableFrom(clazz)) + ? ObjectInputFilter.Status.REJECTED + : ObjectInputFilter.Status.ALLOWED; + } + return ObjectInputFilter.Status.UNDECIDED; + }; + } + + private static byte[] convertObjectToStream(Object obj) { + ByteArrayOutputStream boas = new ByteArrayOutputStream(); + try (ObjectOutputStream ois = new ObjectOutputStream(boas)) { + ois.writeObject(obj); + return boas.toByteArray(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + throw new RuntimeException(); + } + +} diff --git a/java-17/src/main/java/com/mkyong/java17/jep415/JEP415.java b/java-17/src/main/java/com/mkyong/java17/jep415/JEP415.java new file mode 100644 index 0000000..e00db1c --- /dev/null +++ b/java-17/src/main/java/com/mkyong/java17/jep415/JEP415.java @@ -0,0 +1,41 @@ +package com.mkyong.java17.jep415; + +import javax.swing.*; +import java.io.*; + +public class JEP415 { + + public static void main(String[] args) throws IOException { + + byte[] bytes = convertObjectToStream(new JComponentExample()); + InputStream is = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(is); + + // Java 17 + // reject all JComponent classes + ObjectInputFilter jComponentFilter = ObjectInputFilter.rejectFilter( + JComponent.class::isAssignableFrom, + ObjectInputFilter.Status.UNDECIDED); + ois.setObjectInputFilter(jComponentFilter); + + try { + Object obj = ois.readObject(); + System.out.println("Read obj: " + obj); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + + } + + private static byte[] convertObjectToStream(Object obj) { + ByteArrayOutputStream boas = new ByteArrayOutputStream(); + try (ObjectOutputStream ois = new ObjectOutputStream(boas)) { + ois.writeObject(obj); + return boas.toByteArray(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + throw new RuntimeException(); + } + +} diff --git a/java-17/src/main/java/com/mkyong/java17/jep415/JEP415_B.java b/java-17/src/main/java/com/mkyong/java17/jep415/JEP415_B.java new file mode 100644 index 0000000..5fdff7d --- /dev/null +++ b/java-17/src/main/java/com/mkyong/java17/jep415/JEP415_B.java @@ -0,0 +1,79 @@ +package com.mkyong.java17.jep415; + +import java.io.*; +import java.util.function.BinaryOperator; + +public class JEP415_B { + + static class PrintFilterFactory implements BinaryOperator { + + @Override + public ObjectInputFilter apply( + ObjectInputFilter currentFilter, ObjectInputFilter nextFilter) { + + System.out.println("Current filter: " + currentFilter); + System.out.println("Requested filter: " + nextFilter); + + // Returns a filter that merges the status of a filter and another filter + return ObjectInputFilter.merge(nextFilter, currentFilter); + + // some logic and return other filters + // reject all JComponent classes + /*return filterInfo -> { + Class clazz = filterInfo.serialClass(); + if (clazz != null) { + if(JComponent.class.isAssignableFrom(clazz)){ + return ObjectInputFilter.Status.REJECTED; + } + } + return ObjectInputFilter.Status.ALLOWED; + };*/ + + } + } + + public static void main(String[] args) throws IOException { + + // Set a filter factory + PrintFilterFactory filterFactory = new PrintFilterFactory(); + ObjectInputFilter.Config.setSerialFilterFactory(filterFactory); + + // create a maxdepth and package filter + ObjectInputFilter filter1 = + ObjectInputFilter.Config.createFilter("com.mkyong.java17.jep415.*;java.base/*;!*"); + ObjectInputFilter.Config.setSerialFilter(filter1); + + // Create a filter to allow String.class only + ObjectInputFilter intFilter = ObjectInputFilter.allowFilter( + cl -> cl.equals(String.class), ObjectInputFilter.Status.REJECTED); + + // if pass anything other than String.class, hits filter status: REJECTED + //byte[] byteStream =convertObjectToStream(99); + + // Create input stream + byte[] byteStream =convertObjectToStream("hello"); + InputStream is = new ByteArrayInputStream(byteStream); + ObjectInputStream ois = new ObjectInputStream(is); + + ois.setObjectInputFilter(intFilter); + + try { + Object obj = ois.readObject(); + System.out.println("Read obj: " + obj); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + + private static byte[] convertObjectToStream(Object obj) { + ByteArrayOutputStream boas = new ByteArrayOutputStream(); + try (ObjectOutputStream ois = new ObjectOutputStream(boas)) { + ois.writeObject(obj); + return boas.toByteArray(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + throw new RuntimeException(); + } + +} \ No newline at end of file diff --git a/java-17/src/main/resources/test.html b/java-17/src/main/resources/test.html new file mode 100644 index 0000000..67ef16d --- /dev/null +++ b/java-17/src/main/resources/test.html @@ -0,0 +1,5 @@ + + +

Hello, World

+ + \ No newline at end of file From 00236434b5e000a1d59349c2eddf6e1d3908479d Mon Sep 17 00:00:00 2001 From: mkyong Date: Tue, 5 Oct 2021 16:31:20 +0800 Subject: [PATCH 02/15] java serialization filter --- .../mkyong/io/object/HelloSerialization.java | 42 ++++++ ...Utils.java => HelloSerializationFile.java} | 32 ++--- .../java/com/mkyong/io/object/Person.java | 1 + .../mkyong/io/object/SerializationUtils.java | 122 ++++++++++++++++++ .../mkyong/io/object/attack/DosExample.java | 79 ++++++++++++ .../object/attack/StackOverflowExample.java | 75 +++++++++++ .../serialization/DeserializationBomb.java | 38 ------ .../io/object/serialization/TestExample.java | 24 ---- .../com/mkyong/io/utils/SerializeUtil.java | 26 ---- 9 files changed, 336 insertions(+), 103 deletions(-) create mode 100644 java-io/src/main/java/com/mkyong/io/object/HelloSerialization.java rename java-io/src/main/java/com/mkyong/io/object/{ObjectUtils.java => HelloSerializationFile.java} (60%) create mode 100644 java-io/src/main/java/com/mkyong/io/object/SerializationUtils.java create mode 100644 java-io/src/main/java/com/mkyong/io/object/attack/DosExample.java create mode 100644 java-io/src/main/java/com/mkyong/io/object/attack/StackOverflowExample.java delete mode 100644 java-io/src/main/java/com/mkyong/io/object/serialization/DeserializationBomb.java delete mode 100644 java-io/src/main/java/com/mkyong/io/object/serialization/TestExample.java delete mode 100644 java-io/src/main/java/com/mkyong/io/utils/SerializeUtil.java diff --git a/java-io/src/main/java/com/mkyong/io/object/HelloSerialization.java b/java-io/src/main/java/com/mkyong/io/object/HelloSerialization.java new file mode 100644 index 0000000..1267af5 --- /dev/null +++ b/java-io/src/main/java/com/mkyong/io/object/HelloSerialization.java @@ -0,0 +1,42 @@ +package com.mkyong.io.object; + +import java.io.*; +import java.math.BigDecimal; + +public class HelloSerialization { + + public static void main(String[] args) { + + Person person = new Person("mkyong", 40, new BigDecimal(900)); + + byte[] bytes = convertObjectToBytes(person); + + Person p = (Person) convertBytesToObject(bytes); + + System.out.println(p); + } + + // Convert object to byte[] + public static byte[] convertObjectToBytes(Object obj) { + ByteArrayOutputStream boas = new ByteArrayOutputStream(); + try (ObjectOutputStream ois = new ObjectOutputStream(boas)) { + ois.writeObject(obj); + return boas.toByteArray(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + throw new RuntimeException(); + } + + // Convert byte[] to object + public static Object convertBytesToObject(byte[] bytes) { + InputStream is = new ByteArrayInputStream(bytes); + try (ObjectInputStream ois = new ObjectInputStream(is)) { + return ois.readObject(); + } catch (IOException | ClassNotFoundException ioe) { + ioe.printStackTrace(); + } + throw new RuntimeException(); + } + +} diff --git a/java-io/src/main/java/com/mkyong/io/object/ObjectUtils.java b/java-io/src/main/java/com/mkyong/io/object/HelloSerializationFile.java similarity index 60% rename from java-io/src/main/java/com/mkyong/io/object/ObjectUtils.java rename to java-io/src/main/java/com/mkyong/io/object/HelloSerializationFile.java index cff245e..6f00f12 100644 --- a/java-io/src/main/java/com/mkyong/io/object/ObjectUtils.java +++ b/java-io/src/main/java/com/mkyong/io/object/HelloSerializationFile.java @@ -3,11 +3,25 @@ import java.io.*; import java.math.BigDecimal; -public class ObjectUtils { +public class HelloSerializationFile { + + public static void main(String[] args) throws IOException, ClassNotFoundException { + + Person person = new Person("mkyong", 50, new BigDecimal(1000)); + + File file = new File("person.anything"); + + writeObjectToFile(person, file); + + Person p = readObjectFromFile(file); + + System.out.println(p); + + } // Serialization // Save object into a file. - public static void writeObject(Person obj, File file) throws IOException { + public static void writeObjectToFile(Person obj, File file) throws IOException { try (FileOutputStream fos = new FileOutputStream(file); ObjectOutputStream oos = new ObjectOutputStream(fos)) { oos.writeObject(obj); @@ -17,7 +31,7 @@ public static void writeObject(Person obj, File file) throws IOException { // Deserialization // Get object from a file. - public static Person readObject(File file) throws IOException, ClassNotFoundException { + public static Person readObjectFromFile(File file) throws IOException, ClassNotFoundException { Person result = null; try (FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis)) { @@ -26,16 +40,4 @@ public static Person readObject(File file) throws IOException, ClassNotFoundExce return result; } - public static void main(String[] args) throws IOException, ClassNotFoundException { - - Person person = new Person("mkyong", 40, new BigDecimal(900)); - - // object -> file - ObjectUtils.writeObject(person, new File("person.obj")); - - // file -> object - Person obj = ObjectUtils.readObject(new File("person.obj")); - System.out.println(obj); - - } } diff --git a/java-io/src/main/java/com/mkyong/io/object/Person.java b/java-io/src/main/java/com/mkyong/io/object/Person.java index 0a66853..d085565 100644 --- a/java-io/src/main/java/com/mkyong/io/object/Person.java +++ b/java-io/src/main/java/com/mkyong/io/object/Person.java @@ -11,6 +11,7 @@ public class Person implements Serializable { private String name; private int age; + // dun save this field into file private transient BigDecimal salary; diff --git a/java-io/src/main/java/com/mkyong/io/object/SerializationUtils.java b/java-io/src/main/java/com/mkyong/io/object/SerializationUtils.java new file mode 100644 index 0000000..f2db1fd --- /dev/null +++ b/java-io/src/main/java/com/mkyong/io/object/SerializationUtils.java @@ -0,0 +1,122 @@ +package com.mkyong.io.object; + +import java.io.*; +import java.math.BigDecimal; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class SerializationUtils { + + // Serialization + // Save object into a file. + public static void writeObjectToFile(Person obj, File file) throws IOException { + try (FileOutputStream fos = new FileOutputStream(file); + ObjectOutputStream oos = new ObjectOutputStream(fos)) { + oos.writeObject(obj); + oos.flush(); + } + } + + // Serialization + // Convert object to OutputStream + public static void writeObjectToStream(Object obj, OutputStream output) throws IOException { + try (ObjectOutputStream oos = new ObjectOutputStream(output)) { + oos.writeObject(obj); + oos.flush(); + } + } + + // Serialization + // Convert object to byte[] + public static byte[] writeObjectToStream(Object obj) { + ByteArrayOutputStream boas = new ByteArrayOutputStream(); + try (ObjectOutputStream ois = new ObjectOutputStream(boas)) { + ois.writeObject(obj); + return boas.toByteArray(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + throw new RuntimeException(); + } + + // Deserialization + // Get object from a file. + public static Person readObject(File file) throws IOException, ClassNotFoundException { + Person result = null; + try (FileInputStream fis = new FileInputStream(file); + ObjectInputStream ois = new ObjectInputStream(fis)) { + result = (Person) ois.readObject(); + } + return result; + } + + // Deserialization + // generic example + @SuppressWarnings("unchecked") + public static T readObject(InputStream is, Class anyClass) throws IOException, ClassNotFoundException { + T result = null; + try (ObjectInputStream ois = new ObjectInputStream(is)) { + result = (T) ois.readObject(); + } + return result; + } + + public static byte[] serialize(Object o) { + ByteArrayOutputStream ba = new ByteArrayOutputStream(); + try { + new ObjectOutputStream(ba).writeObject(o); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + return ba.toByteArray(); + } + + public static Object deserialize(byte[] bytes) { + try { + return new ObjectInputStream( + new ByteArrayInputStream(bytes)).readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } + } + + public static Object deserializeFilter(byte[] bytes, ObjectInputFilter filter) { + + try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais)) { + + ois.setObjectInputFilter(filter); + + return ois.readObject(); + }catch (IOException | ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } + + } + + public static void main(String[] args) throws IOException, ClassNotFoundException { + + Person person = new Person("mkyong", 41, new BigDecimal(900)); + + // object -> file + + // example 1 + // SerializationUtils.writeObjectToFile(person, new File("person.obj")); + + // example 2 + SerializationUtils.writeObjectToStream(person, new FileOutputStream("person.obj")); + + // example 3 + // byte[] bytes = SerializationUtils.writeObjectToStream(person); + // Files.write(Paths.get("person.obj"), bytes); + + // file -> object + //Person obj = SerializationUtils.readObject(new File("person.obj")); + + Person obj = SerializationUtils.readObject( + new FileInputStream("person.obj"), Person.class); + + System.out.println(obj); + + } +} diff --git a/java-io/src/main/java/com/mkyong/io/object/attack/DosExample.java b/java-io/src/main/java/com/mkyong/io/object/attack/DosExample.java new file mode 100644 index 0000000..5057390 --- /dev/null +++ b/java-io/src/main/java/com/mkyong/io/object/attack/DosExample.java @@ -0,0 +1,79 @@ +package com.mkyong.io.object.attack; + +import java.io.*; +import java.util.HashSet; +import java.util.Set; + +//https://homepages.ecs.vuw.ac.nz/~alex/files/DietrichJezekRasheedTahirPotaninECOOP2017.pdf +public class DosExample { + + public static void main(String[] args) throws Exception { + System.out.println(bomb().length); + + //deserialize(bomb()); // Dos here + + ObjectInputFilter filter = + ObjectInputFilter.Config.createFilter( + "maxdepth=10;java.base/*;!*"); + + deserializeFilter(bomb(), filter); // Dos here + + System.out.println("Done"); + } + + static byte[] bomb() { + Set root = new HashSet<>(); + Set s1 = root; + Set s2 = new HashSet<>(); + for (int i = 0; i < 100; i++) { + Set t1 = new HashSet<>(); + Set t2 = new HashSet<>(); + t1.add("test-" + i); // make it not equal to t2 + + s1.add(t1); // root also add set + s1.add(t2); + + s2.add(t1); + s2.add(t2); + + s1 = t1; // reference to t1, so that `root` can add new set from the last t1 + s2 = t2; + } + return serialize(root); + } + + public static byte[] serialize(Object o) { + ByteArrayOutputStream ba = new ByteArrayOutputStream(); + try { + new ObjectOutputStream(ba).writeObject(o); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + return ba.toByteArray(); + } + + /*public static Object deserialize(byte[] bytes) { + try { + return new ObjectInputStream( + new ByteArrayInputStream(bytes)).readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } + }*/ + + public static Object deserializeFilter(byte[] bytes, ObjectInputFilter filter) { + + try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais)) { + + // add filter before readObject + ois.setObjectInputFilter(filter); + + return ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } + + } + +} \ No newline at end of file diff --git a/java-io/src/main/java/com/mkyong/io/object/attack/StackOverflowExample.java b/java-io/src/main/java/com/mkyong/io/object/attack/StackOverflowExample.java new file mode 100644 index 0000000..1882d85 --- /dev/null +++ b/java-io/src/main/java/com/mkyong/io/object/attack/StackOverflowExample.java @@ -0,0 +1,75 @@ +package com.mkyong.io.object.attack; + +import java.io.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +// https://homepages.ecs.vuw.ac.nz/~alex/files/DietrichJezekRasheedTahirPotaninECOOP2017.pdf +public class StackOverflowExample { + + public static void main(String[] args) { + System.out.println(bomb().length); + + /*ObjectInputFilter filter = + ObjectInputFilter.Config.createFilter( + "maxdepth=2;com.mkyong.io.object.*;java.base/*;!*"); + Person person = new Person("mkyong", 41, new BigDecimal(900)); + var bytes = SerializationUtils.writeObjectToStream(person); + SerializationUtils.deserializeFilter(bytes, filter);*/ + + //deserialize(bomb()); // throws StackOverflow + + ObjectInputFilter filter = + ObjectInputFilter.Config.createFilter( + "maxdepth=2;java.base/*;!*"); + + deserializeFilter(bomb(), filter); // java.io.InvalidClassException: filter status: REJECTED + + System.out.println("Done"); + } + + static byte[] bomb() { + HashMap map = new HashMap(); + List list = new ArrayList(); + map.put(list, ""); + list.add(list); + return serialize(map); + } + + public static byte[] serialize(Object o) { + ByteArrayOutputStream ba = new ByteArrayOutputStream(); + try { + new ObjectOutputStream(ba).writeObject(o); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + return ba.toByteArray(); + } + + + /*public static Object deserialize(byte[] bytes) { + try { + return new ObjectInputStream( + new ByteArrayInputStream(bytes)).readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } + }*/ + + public static Object deserializeFilter(byte[] bytes, ObjectInputFilter filter) { + + try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais)) { + + // add filter before readObject + ois.setObjectInputFilter(filter); + + return ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } + + } + +} diff --git a/java-io/src/main/java/com/mkyong/io/object/serialization/DeserializationBomb.java b/java-io/src/main/java/com/mkyong/io/object/serialization/DeserializationBomb.java deleted file mode 100644 index 01dd369..0000000 --- a/java-io/src/main/java/com/mkyong/io/object/serialization/DeserializationBomb.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.mkyong.io.object.serialization; - -import com.mkyong.io.utils.SerializeUtil; - -import java.util.HashSet; -import java.util.Set; - -//https://homepages.ecs.vuw.ac.nz/~alex/files/DietrichJezekRasheedTahirPotaninECOOP2017.pdf -public class DeserializationBomb { - - public static void main(String[] args) throws Exception { - System.out.println(bomb().length); - SerializeUtil.deserialize(bomb()); // Dos here - System.out.println("Done"); - } - - static byte[] bomb() { - Set root = new HashSet<>(); - Set s1 = root; - Set s2 = new HashSet<>(); - for (int i = 0; i < 100; i++) { - Set t1 = new HashSet<>(); - Set t2 = new HashSet<>(); - t1.add("test-" + i); // make it not equal to t2 - - s1.add(t1); // root also add set - s1.add(t2); - - s2.add(t1); - s2.add(t2); - - s1 = t1; // reference to t1, so that `root` can add new set from the last t1 - s2 = t2; - } - return SerializeUtil.serialize(root); - } - -} diff --git a/java-io/src/main/java/com/mkyong/io/object/serialization/TestExample.java b/java-io/src/main/java/com/mkyong/io/object/serialization/TestExample.java deleted file mode 100644 index 93a9c40..0000000 --- a/java-io/src/main/java/com/mkyong/io/object/serialization/TestExample.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.mkyong.io.object.serialization; - -import com.mkyong.io.utils.SerializeUtil; - -import java.util.*; - -public class TestExample { - - // https://homepages.ecs.vuw.ac.nz/~alex/files/DietrichJezekRasheedTahirPotaninECOOP2017.pdf - public static void main(String[] args) { - System.out.println(bomb().length); - SerializeUtil.deserialize(bomb()); // Dos here - System.out.println("Done"); - } - - static byte[] bomb() { - HashMap map = new HashMap() ; - List list = new ArrayList() ; - map.put(list ,""); - list.add(list); - return SerializeUtil.serialize(map); - } - -} diff --git a/java-io/src/main/java/com/mkyong/io/utils/SerializeUtil.java b/java-io/src/main/java/com/mkyong/io/utils/SerializeUtil.java deleted file mode 100644 index 7fc6aca..0000000 --- a/java-io/src/main/java/com/mkyong/io/utils/SerializeUtil.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.mkyong.io.utils; - -import java.io.*; - -public class SerializeUtil { - - public static byte[] serialize(Object o) { - ByteArrayOutputStream ba = new ByteArrayOutputStream(); - try { - new ObjectOutputStream(ba).writeObject(o); - } catch (IOException e) { - throw new IllegalArgumentException(e); - } - return ba.toByteArray(); - } - - public static Object deserialize(byte[] bytes) { - try { - return new ObjectInputStream( - new ByteArrayInputStream(bytes)).readObject(); - } catch (IOException | ClassNotFoundException e) { - throw new IllegalArgumentException(e); - } - } - -} From efd15a999aeb162c2e7794024066492c5fb37895 Mon Sep 17 00:00:00 2001 From: mkyong Date: Wed, 6 Oct 2021 16:47:49 +0800 Subject: [PATCH 03/15] serialization --- java-io/pom.xml | 8 +-- .../java/com/mkyong/io/object/Address.java | 40 -------------- .../io/object/HelloDeserializationFilter.java | 55 +++++++++++++++++++ .../io/object/HelloSerializationFile.java | 15 ++++- .../java/com/mkyong/io/object/Person2.java | 21 +++++++ .../object/attack/StackOverflowExample.java | 7 --- 6 files changed, 94 insertions(+), 52 deletions(-) delete mode 100644 java-io/src/main/java/com/mkyong/io/object/Address.java create mode 100644 java-io/src/main/java/com/mkyong/io/object/HelloDeserializationFilter.java create mode 100644 java-io/src/main/java/com/mkyong/io/object/Person2.java diff --git a/java-io/pom.xml b/java-io/pom.xml index f2538d2..f2ca168 100644 --- a/java-io/pom.xml +++ b/java-io/pom.xml @@ -14,9 +14,9 @@ UTF-8 - 11 - 11 - 11 + 17 + 17 + 17 5.4.0 @@ -135,4 +135,4 @@ - + \ No newline at end of file diff --git a/java-io/src/main/java/com/mkyong/io/object/Address.java b/java-io/src/main/java/com/mkyong/io/object/Address.java deleted file mode 100644 index b78b4a7..0000000 --- a/java-io/src/main/java/com/mkyong/io/object/Address.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.mkyong.io.object; - -import java.io.Serializable; - -public class Address implements Serializable { - - private static final long serialVersionUID = -2338626292552177485L; - - String street; - String country; - - public Address(String street, String country) { - this.street = street; - this.country = country; - } - - public String getStreet() { - return street; - } - - public void setStreet(String street) { - this.street = street; - } - - public String getCountry() { - return country; - } - - public void setCountry(String country) { - this.country = country; - } - - @Override - public String toString() { - return "Address{" + - "street='" + street + '\'' + - ", country='" + country + '\'' + - '}'; - } -} diff --git a/java-io/src/main/java/com/mkyong/io/object/HelloDeserializationFilter.java b/java-io/src/main/java/com/mkyong/io/object/HelloDeserializationFilter.java new file mode 100644 index 0000000..f629a0f --- /dev/null +++ b/java-io/src/main/java/com/mkyong/io/object/HelloDeserializationFilter.java @@ -0,0 +1,55 @@ +package com.mkyong.io.object; + +import java.io.*; +import java.math.BigDecimal; + +public class HelloDeserializationFilter { + + public static void main(String[] args) { + + //Person person = new Person("mkyong", 40, new BigDecimal(900)); + + // reject this Person2, only allow Person class + Person2 person = new Person2("mkyong", 40, new BigDecimal(900), "test"); + + byte[] bytes = convertObjectToBytes(person); + + // only allow to deserialize com.mkyong.io.object.Person and java.base/* + // !* reject all + ObjectInputFilter filter = + ObjectInputFilter.Config.createFilter( + "com.mkyong.io.object.Person;java.base/*;!*"); + + Person p = (Person) convertBytesToObject(bytes, filter); + + System.out.println(p); + } + + // Convert object to byte[] + public static byte[] convertObjectToBytes(Object obj) { + ByteArrayOutputStream boas = new ByteArrayOutputStream(); + try (ObjectOutputStream ois = new ObjectOutputStream(boas)) { + ois.writeObject(obj); + return boas.toByteArray(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + throw new RuntimeException(); + } + + // Convert byte[] to object + public static Object convertBytesToObject(byte[] bytes, ObjectInputFilter filter) { + InputStream is = new ByteArrayInputStream(bytes); + try (ObjectInputStream ois = new ObjectInputStream(is)) { + + // add filter before readObject + ois.setObjectInputFilter(filter); + + return ois.readObject(); + } catch (IOException | ClassNotFoundException ioe) { + ioe.printStackTrace(); + } + throw new RuntimeException(); + } + +} diff --git a/java-io/src/main/java/com/mkyong/io/object/HelloSerializationFile.java b/java-io/src/main/java/com/mkyong/io/object/HelloSerializationFile.java index 6f00f12..7147a50 100644 --- a/java-io/src/main/java/com/mkyong/io/object/HelloSerializationFile.java +++ b/java-io/src/main/java/com/mkyong/io/object/HelloSerializationFile.java @@ -9,12 +9,14 @@ public static void main(String[] args) throws IOException, ClassNotFoundExceptio Person person = new Person("mkyong", 50, new BigDecimal(1000)); - File file = new File("person.anything"); + File file = new File("person.bin"); writeObjectToFile(person, file); Person p = readObjectFromFile(file); + //Person p = (Person) readObjectFromFile2(file); + System.out.println(p); } @@ -40,4 +42,15 @@ public static Person readObjectFromFile(File file) throws IOException, ClassNotF return result; } + // Deserialization + // Get object from a file. + public static Object readObjectFromFile2(File file) throws IOException, ClassNotFoundException { + Object result = null; + try (FileInputStream fis = new FileInputStream(file); + ObjectInputStream ois = new ObjectInputStream(fis)) { + result = ois.readObject(); + } + return result; + } + } diff --git a/java-io/src/main/java/com/mkyong/io/object/Person2.java b/java-io/src/main/java/com/mkyong/io/object/Person2.java new file mode 100644 index 0000000..47d8bf1 --- /dev/null +++ b/java-io/src/main/java/com/mkyong/io/object/Person2.java @@ -0,0 +1,21 @@ +package com.mkyong.io.object; + +import java.math.BigDecimal; + +public class Person2 extends Person{ + + private String address; + + public Person2(String name, int age, BigDecimal salary, String address) { + super(name, age, salary); + this.address = address; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } +} diff --git a/java-io/src/main/java/com/mkyong/io/object/attack/StackOverflowExample.java b/java-io/src/main/java/com/mkyong/io/object/attack/StackOverflowExample.java index 1882d85..e5f2165 100644 --- a/java-io/src/main/java/com/mkyong/io/object/attack/StackOverflowExample.java +++ b/java-io/src/main/java/com/mkyong/io/object/attack/StackOverflowExample.java @@ -11,13 +11,6 @@ public class StackOverflowExample { public static void main(String[] args) { System.out.println(bomb().length); - /*ObjectInputFilter filter = - ObjectInputFilter.Config.createFilter( - "maxdepth=2;com.mkyong.io.object.*;java.base/*;!*"); - Person person = new Person("mkyong", 41, new BigDecimal(900)); - var bytes = SerializationUtils.writeObjectToStream(person); - SerializationUtils.deserializeFilter(bytes, filter);*/ - //deserialize(bomb()); // throws StackOverflow ObjectInputFilter filter = From b292b043206c42b6fda0e9ec42bf46922707a845 Mon Sep 17 00:00:00 2001 From: mkyong Date: Mon, 17 Jan 2022 17:09:43 +0800 Subject: [PATCH 04/15] new --- java-string/pom.xml | 48 +++++++++++ .../mkyong/string/ConvertBytesToString.java | 20 +++++ .../mkyong/string/ConvertStringToBytes.java | 31 +++++++ .../mkyong/string/StringTokenizerExample.java | 83 +++++++++++++++++++ 4 files changed, 182 insertions(+) create mode 100644 java-string/pom.xml create mode 100644 java-string/src/main/java/com/mkyong/string/ConvertBytesToString.java create mode 100644 java-string/src/main/java/com/mkyong/string/ConvertStringToBytes.java create mode 100644 java-string/src/main/java/com/mkyong/string/StringTokenizerExample.java diff --git a/java-string/pom.xml b/java-string/pom.xml new file mode 100644 index 0000000..7eef9d9 --- /dev/null +++ b/java-string/pom.xml @@ -0,0 +1,48 @@ + + + + 4.0.0 + com.mkyong + string + 1.0 + + java-string + https://mkyong.com + + + UTF-8 + 17 + 17 + 17 + 5.4.0 + + + + + + org.junit.jupiter + junit-jupiter-params + ${junit.version} + test + + + + + + java-basic + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + ${java.version} + ${java.version} + + + + + diff --git a/java-string/src/main/java/com/mkyong/string/ConvertBytesToString.java b/java-string/src/main/java/com/mkyong/string/ConvertBytesToString.java new file mode 100644 index 0000000..d3c5506 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/ConvertBytesToString.java @@ -0,0 +1,20 @@ +package com.mkyong.string; + +import java.nio.charset.StandardCharsets; + +public class ConvertBytesToString { + + public static void main(String[] args) { + + // String to byte[] + byte[] bytes = "mkyong".getBytes(StandardCharsets.UTF_8); + + // byte[] to String + String s = new String(bytes, StandardCharsets.UTF_8); + + // mkyong + System.out.println(s); + + } + +} \ No newline at end of file diff --git a/java-string/src/main/java/com/mkyong/string/ConvertStringToBytes.java b/java-string/src/main/java/com/mkyong/string/ConvertStringToBytes.java new file mode 100644 index 0000000..082c720 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/ConvertStringToBytes.java @@ -0,0 +1,31 @@ +package com.mkyong.string; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +public class ConvertStringToBytes { + + public static void main(String[] args) { + + String example = "This is an example"; + + // default charset, a bit dangerous + byte[] output1 = example.getBytes(); + + // in old days, before java 1.7 + byte[] output2 = example.getBytes(Charset.forName("UTF-8")); + + // the best , java 1.7+ + byte[] output3 = example.getBytes(StandardCharsets.UTF_8); + + System.out.println("Text : " + example); + + // base64 encode + String base64encoded = Base64.getEncoder().encodeToString(output3); + + System.out.println("Text [Base64] : " + base64encoded); + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/StringTokenizerExample.java b/java-string/src/main/java/com/mkyong/string/StringTokenizerExample.java new file mode 100644 index 0000000..ce53c08 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/StringTokenizerExample.java @@ -0,0 +1,83 @@ +package com.mkyong.string; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +public class StringTokenizerExample { + + public static void main(String[] args) throws IOException { + + StringTokenizer st = new StringTokenizer("1, 2, 3, 4, 5"); + while (st.hasMoreTokens()) { + System.out.println(st.nextToken().trim()); + } + + /*String line = "This is a String, split by, StringTokenizer example."; + List result = split(line, ","); + for (String s : result) { + System.out.println(s.trim()); + }*/ + + /*StringTokenizerExample obj = new StringTokenizerExample(); + List trends = obj.readFile(Paths.get("C:\\test\\sample.csv"), "|"); + trends.forEach(System.out::println);*/ + } + + public static List split(String line, String delimiter) { + List result = new ArrayList<>(); + StringTokenizer st = new StringTokenizer(line, delimiter); + while (st.hasMoreTokens()) { + result.add(st.nextToken()); + } + return result; + } + + public List readFile(Path path, String delimiter) throws IOException { + + List result = new ArrayList<>(); + + try (BufferedReader br = new BufferedReader(new FileReader(path.toString()))) { + + String line; + while ((line = br.readLine()) != null) { + StringTokenizer st = new StringTokenizer(line, delimiter); + while (st.hasMoreTokens()) { + Integer id = Integer.parseInt(st.nextToken().trim()); + Double index = Double.parseDouble(st.nextToken().trim()); + String desc = st.nextToken().trim(); + result.add(new Trend(id, index, desc)); + } + } + } + return result; + } + + class Trend { + private int id; + private Double index; + private String desc; + + public Trend(int id, Double index, String desc) { + this.id = id; + this.index = index; + this.desc = desc; + } + + @Override + public String toString() { + return "Trend{" + + "id=" + id + + ", index=" + index + + ", desc='" + desc + '\'' + + '}'; + } + } +} From 21acff5ba2fb975dbc967db10bfd0aaf7d6fc7e8 Mon Sep 17 00:00:00 2001 From: mkyong Date: Tue, 18 Jan 2022 12:45:41 +0800 Subject: [PATCH 05/15] byte to string --- .../mkyong/string/ConvertBytesToString2.java | 29 +++++++++++++ .../string/ConvertBytesToStringBase64.java | 41 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 java-string/src/main/java/com/mkyong/string/ConvertBytesToString2.java create mode 100644 java-string/src/main/java/com/mkyong/string/ConvertBytesToStringBase64.java diff --git a/java-string/src/main/java/com/mkyong/string/ConvertBytesToString2.java b/java-string/src/main/java/com/mkyong/string/ConvertBytesToString2.java new file mode 100644 index 0000000..1a04dce --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/ConvertBytesToString2.java @@ -0,0 +1,29 @@ +package com.mkyong.string; + +import java.nio.charset.StandardCharsets; + +public class ConvertBytesToString2 { + + public static void main(String[] args) { + + String str = "This is raw text!"; + + // string to byte[] + byte[] bytes = str.getBytes(StandardCharsets.UTF_8); + + System.out.println("Text : " + str); + System.out.println("Text [Byte Format] : " + bytes); + + // no, don't do this, it returns the address of the object in memory + System.out.println("Text [Byte Format] toString() : " + bytes.toString()); + + // convert byte[] to string + String s = new String(bytes, StandardCharsets.UTF_8); + System.out.println("Output : " + s); + + // old code, UnsupportedEncodingException + // String s1 = new String(bytes, "UTF_8"); + + } + +} \ No newline at end of file diff --git a/java-string/src/main/java/com/mkyong/string/ConvertBytesToStringBase64.java b/java-string/src/main/java/com/mkyong/string/ConvertBytesToStringBase64.java new file mode 100644 index 0000000..ae578aa --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/ConvertBytesToStringBase64.java @@ -0,0 +1,41 @@ +package com.mkyong.string; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Base64; + +public class ConvertBytesToStringBase64 { + + public static void main(String[] args) { + + String filepath = "/Users/mkyong/phone.png"; + Path path = Paths.get(filepath); + + if (Files.notExists(path)) { + throw new IllegalArgumentException("File is not exists!"); + } + + try { + + // convert the file's content to byte[] + byte[] bytes = Files.readAllBytes(path); + + // encode, byte[] to Base64 encoded string + String s = Base64.getEncoder().encodeToString(bytes); + System.out.println(s); + + // decode, Base64 encoded string to byte[] + byte[] decode = Base64.getDecoder().decode(s); + + // save into another image file. + Files.write(Paths.get("/Users/mkyong/phone2.png"), decode); + + } catch (IOException e) { + e.printStackTrace(); + } + + } + +} \ No newline at end of file From a07eb100ffd8159845db4653e616e71038411590 Mon Sep 17 00:00:00 2001 From: mkyong Date: Tue, 25 Jan 2022 15:23:08 +0800 Subject: [PATCH 06/15] add compare strings --- java-17/pom.xml | 38 --------------- java-basic/pom.xml | 20 ++++++-- .../mkyong/string/compare/StringCompare.java | 40 ++++++++++++++++ .../compare/StringCompareContentEquals.java | 26 ++++++++++ .../string/compare/StringCompareEquals.java | 15 ++++++ .../string/compare/StringCompareEquals2.java | 15 ++++++ .../StringCompareEqualsIgnoreCase.java | 15 ++++++ .../string/compare/StringCompareIntern.java | 27 +++++++++++ .../string/compare/StringCompareNull.java | 21 ++++++++ .../compare/StringCompareObjectsEquals.java | 29 +++++++++++ .../string/compare/StringCompareTo.java | 48 +++++++++++++++++++ 11 files changed, 253 insertions(+), 41 deletions(-) delete mode 100644 java-17/pom.xml create mode 100644 java-string/src/main/java/com/mkyong/string/compare/StringCompare.java create mode 100644 java-string/src/main/java/com/mkyong/string/compare/StringCompareContentEquals.java create mode 100644 java-string/src/main/java/com/mkyong/string/compare/StringCompareEquals.java create mode 100644 java-string/src/main/java/com/mkyong/string/compare/StringCompareEquals2.java create mode 100644 java-string/src/main/java/com/mkyong/string/compare/StringCompareEqualsIgnoreCase.java create mode 100644 java-string/src/main/java/com/mkyong/string/compare/StringCompareIntern.java create mode 100644 java-string/src/main/java/com/mkyong/string/compare/StringCompareNull.java create mode 100644 java-string/src/main/java/com/mkyong/string/compare/StringCompareObjectsEquals.java create mode 100644 java-string/src/main/java/com/mkyong/string/compare/StringCompareTo.java diff --git a/java-17/pom.xml b/java-17/pom.xml deleted file mode 100644 index 0c1c6e0..0000000 --- a/java-17/pom.xml +++ /dev/null @@ -1,38 +0,0 @@ - - 4.0.0 - com.mkyong - java17 - 1.0 - - java-17 - https://www.mkyong.com - - - UTF-8 - 17 - 17 - 17 - - - - - - - java17 - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 17 - 17 - --enable-preview - - - - - diff --git a/java-basic/pom.xml b/java-basic/pom.xml index 1fd652e..224019c 100644 --- a/java-basic/pom.xml +++ b/java-basic/pom.xml @@ -14,9 +14,9 @@ UTF-8 - 11 - 11 - 11 + 17 + 17 + 17 5.4.0 @@ -35,6 +35,20 @@ test + + + + com.sun.activation + jakarta.activation + 2.0.1 + + diff --git a/java-string/src/main/java/com/mkyong/string/compare/StringCompare.java b/java-string/src/main/java/com/mkyong/string/compare/StringCompare.java new file mode 100644 index 0000000..695bfdd --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/compare/StringCompare.java @@ -0,0 +1,40 @@ +package com.mkyong.string.compare; + +public class StringCompare { + + public static void main(String[] args) { + + String str1 = "apple"; + if (str1.equals("apple")) { + System.out.println("I have an apple."); + } + + String str2 = "apple"; + if (str2.equalsIgnoreCase("APPLE")) { + System.out.println("I have an APPLE."); + } + + + // true + boolean result = new String("mkyong").equals("mkyong"); + System.out.println(result); + + // true + boolean result2 = "mkyong".equals(new String("mkyong")); + System.out.println(result2); + + // true + boolean result3 = "mkyong".equals("mkyong"); + System.out.println(result3); + + // false, equals is case-sensitive + boolean result4 = new String("mkyong").equals("MKYONG"); + System.out.println(result4); + + // true, equalsIgnoreCase is case-insensitive + boolean result5 = new String("mkyong").equalsIgnoreCase("MKYONG"); + System.out.println(result5); + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/compare/StringCompareContentEquals.java b/java-string/src/main/java/com/mkyong/string/compare/StringCompareContentEquals.java new file mode 100644 index 0000000..6f270d2 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/compare/StringCompareContentEquals.java @@ -0,0 +1,26 @@ +package com.mkyong.string.compare; + +public class StringCompareContentEquals { + + public static void main(String[] args) { + + String str1 = "apple"; + String str2 = "apple"; + StringBuilder sb = new StringBuilder("apple"); + StringBuffer buffer = new StringBuffer("apple"); + + // true + System.out.println(str1.equals(str2)); + // false, .equals cant compare StringBuilder + System.out.println(str1.equals(sb)); + + // .contentEquals supports CharSequence + // CharSequence implementations: StringBuffer, StringBuilder, String, etc. + // true + System.out.println(str1.contentEquals(sb)); + // true + System.out.println(str1.contentEquals(buffer)); + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/compare/StringCompareEquals.java b/java-string/src/main/java/com/mkyong/string/compare/StringCompareEquals.java new file mode 100644 index 0000000..a1f624f --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/compare/StringCompareEquals.java @@ -0,0 +1,15 @@ +package com.mkyong.string.compare; + +public class StringCompareEquals { + + public static void main(String[] args) { + + String str1 = "apple"; + + boolean result = str1.equals("apple"); + + System.out.println(result); // true + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/compare/StringCompareEquals2.java b/java-string/src/main/java/com/mkyong/string/compare/StringCompareEquals2.java new file mode 100644 index 0000000..a25cb84 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/compare/StringCompareEquals2.java @@ -0,0 +1,15 @@ +package com.mkyong.string.compare; + +public class StringCompareEquals2 { + + public static void main(String[] args) { + + String str1 = "apple"; + + boolean result = str1.equals("Apple"); + + System.out.println(result); // false + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/compare/StringCompareEqualsIgnoreCase.java b/java-string/src/main/java/com/mkyong/string/compare/StringCompareEqualsIgnoreCase.java new file mode 100644 index 0000000..f505261 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/compare/StringCompareEqualsIgnoreCase.java @@ -0,0 +1,15 @@ +package com.mkyong.string.compare; + +public class StringCompareEqualsIgnoreCase { + + public static void main(String[] args) { + + String str1 = "apple"; + + boolean result = str1.equalsIgnoreCase("Apple"); + + System.out.println(result); // true + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/compare/StringCompareIntern.java b/java-string/src/main/java/com/mkyong/string/compare/StringCompareIntern.java new file mode 100644 index 0000000..8775b7b --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/compare/StringCompareIntern.java @@ -0,0 +1,27 @@ +package com.mkyong.string.compare; + +public class StringCompareIntern { + + public static void main(String[] args) { + + String str1 = "apple"; + String str2 = "apple"; + + // true, why true because of the string constant pool + System.out.println(str1 == str2); + + String str3 = new String("apple"); + // false + System.out.println(str1 == str3); + + // add this to string pool. + String str4 = str3.intern(); + + // true + System.out.println(str1 == str4); + + // still false + System.out.println(str1 == str3); + + } +} diff --git a/java-string/src/main/java/com/mkyong/string/compare/StringCompareNull.java b/java-string/src/main/java/com/mkyong/string/compare/StringCompareNull.java new file mode 100644 index 0000000..45d7743 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/compare/StringCompareNull.java @@ -0,0 +1,21 @@ +package com.mkyong.string.compare; + +public class StringCompareNull { + + public static void main(String[] args) { + + String str1 = null; + + // throw NullPointerException + /*if (str1.equals("hello")) { + System.out.println("equals"); + }*/ + + // check null + if (str1 != null && str1.equals("hello")) { + System.out.println("equals"); + } + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/compare/StringCompareObjectsEquals.java b/java-string/src/main/java/com/mkyong/string/compare/StringCompareObjectsEquals.java new file mode 100644 index 0000000..107cbb5 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/compare/StringCompareObjectsEquals.java @@ -0,0 +1,29 @@ +package com.mkyong.string.compare; + +import java.util.Objects; + +public class StringCompareObjectsEquals { + + public static void main(String[] args) { + + String str1 = "apple"; + String str2 = "banana"; + + // false + System.out.println(Objects.equals(str1, str2)); + + // true + System.out.println(Objects.equals(str1, new String("apple"))); + + // false + System.out.println(Objects.equals(null, str2)); + + // false + System.out.println(Objects.equals(str1, null)); + + // true + System.out.println(Objects.equals(null, null)); + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/compare/StringCompareTo.java b/java-string/src/main/java/com/mkyong/string/compare/StringCompareTo.java new file mode 100644 index 0000000..6df5fed --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/compare/StringCompareTo.java @@ -0,0 +1,48 @@ +package com.mkyong.string.compare; + +public class StringCompareTo { + + public static void main(String[] args) { + + System.out.println("-Negative Number-"); + System.out.println("a".compareTo("b")); // -1 + System.out.println("a".compareTo("c")); // -2 + System.out.println("a".compareTo("d")); // -3 + System.out.println("a".compareTo("e")); // -4 + + System.out.println("1".compareTo("2")); // -1 + System.out.println("1".compareTo("3")); // -2 + System.out.println("1".compareTo("4")); // -3 + System.out.println("1".compareTo("5")); // -4 + + System.out.println("-Positive Number-"); + System.out.println("b".compareTo("a")); // 1 + System.out.println("c".compareTo("a")); // 2 + System.out.println("d".compareTo("a")); // 3 + System.out.println("e".compareTo("a")); // 4 + + System.out.println("2".compareTo("1")); // 1 + System.out.println("3".compareTo("1")); // 2 + System.out.println("4".compareTo("1")); // 3 + System.out.println("5".compareTo("1")); // 4 + + System.out.println("-Zero-"); + System.out.println("a".compareTo("a")); // 0 + System.out.println("1".compareTo("1")); // 0 + + System.out.println("-Vary Length-"); + System.out.println("a".compareTo("ab")); // -1 + System.out.println("a".compareTo("abc")); // -2 + System.out.println("a".compareTo("abcd")); // -3 + + System.out.println("11".compareTo("112")); // -1 + System.out.println("11".compareTo("1123")); // -2 + System.out.println("11".compareTo("11234")); // -3 + + System.out.println("-compareToIgnoreCase-"); + System.out.println("a".compareTo("A")); // 32 + System.out.println("a".compareToIgnoreCase("A")); // 0 + + } + +} From 4fe61caa4de4b40825d60dc958418fb335db23ba Mon Sep 17 00:00:00 2001 From: mkyong Date: Wed, 9 Feb 2022 16:38:19 +0800 Subject: [PATCH 07/15] split a string --- .../com/mkyong/string/ConvertStringToInt.java | 26 ++++++++ .../mkyong/string/ConvertStringToInt2.java | 21 ++++++ .../mkyong/string/ConvertStringToInteger.java | 26 ++++++++ .../string/ConvertStringToIntegerJava8.java | 37 +++++++++++ .../com/mkyong/string/split/StringSplit.java | 20 ++++++ .../string/split/StringSplitContains.java | 21 ++++++ .../mkyong/string/split/StringSplitJava8.java | 25 ++++++++ .../mkyong/string/split/StringSplitLimit.java | 22 +++++++ .../string/split/StringSplitLookAround.java | 27 ++++++++ .../split/StringSplitMultiDelimiters.java | 27 ++++++++ .../string/split/StringSplitNewLines.java | 38 +++++++++++ .../string/split/StringSplitSpaces.java | 16 +++++ .../split/StringSplitSpecialBackslash.java | 22 +++++++ .../split/StringSplitSpecialPeriod.java | 22 +++++++ .../string/split/StringSplitSpecialPipe.java | 24 +++++++ .../split/StringSplitStringTokenizer.java | 21 ++++++ .../string/utils/CustomStringUtils.java | 27 ++++++++ .../ConvertStringToIntTest.java | 64 +++++++++++++++++++ 18 files changed, 486 insertions(+) create mode 100644 java-string/src/main/java/com/mkyong/string/ConvertStringToInt.java create mode 100644 java-string/src/main/java/com/mkyong/string/ConvertStringToInt2.java create mode 100644 java-string/src/main/java/com/mkyong/string/ConvertStringToInteger.java create mode 100644 java-string/src/main/java/com/mkyong/string/ConvertStringToIntegerJava8.java create mode 100644 java-string/src/main/java/com/mkyong/string/split/StringSplit.java create mode 100644 java-string/src/main/java/com/mkyong/string/split/StringSplitContains.java create mode 100644 java-string/src/main/java/com/mkyong/string/split/StringSplitJava8.java create mode 100644 java-string/src/main/java/com/mkyong/string/split/StringSplitLimit.java create mode 100644 java-string/src/main/java/com/mkyong/string/split/StringSplitLookAround.java create mode 100644 java-string/src/main/java/com/mkyong/string/split/StringSplitMultiDelimiters.java create mode 100644 java-string/src/main/java/com/mkyong/string/split/StringSplitNewLines.java create mode 100644 java-string/src/main/java/com/mkyong/string/split/StringSplitSpaces.java create mode 100644 java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialBackslash.java create mode 100644 java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialPeriod.java create mode 100644 java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialPipe.java create mode 100644 java-string/src/main/java/com/mkyong/string/split/StringSplitStringTokenizer.java create mode 100644 java-string/src/main/java/com/mkyong/string/utils/CustomStringUtils.java create mode 100644 java-string/src/test/java/com.mkyong.string/ConvertStringToIntTest.java diff --git a/java-string/src/main/java/com/mkyong/string/ConvertStringToInt.java b/java-string/src/main/java/com/mkyong/string/ConvertStringToInt.java new file mode 100644 index 0000000..8a2c7ed --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/ConvertStringToInt.java @@ -0,0 +1,26 @@ +package com.mkyong.string; + +public class ConvertStringToInt { + + public static void main(String[] args) { + + /*String number = "1"; + + // String to int + int result = Integer.parseInt(number); + + // 1 + System.out.println(result);*/ + + String number = "1A"; + try { + int result = Integer.parseInt(number); + System.out.println(result); + } catch (NumberFormatException e) { + //do something for the exception. + System.err.println("Invalid number format : " + number); + } + + } + +} \ No newline at end of file diff --git a/java-string/src/main/java/com/mkyong/string/ConvertStringToInt2.java b/java-string/src/main/java/com/mkyong/string/ConvertStringToInt2.java new file mode 100644 index 0000000..c73c7a3 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/ConvertStringToInt2.java @@ -0,0 +1,21 @@ +package com.mkyong.string; + +public class ConvertStringToInt2 { + + public static void main(String[] args) { + + // 2147483647 + System.out.println(Integer.MAX_VALUE); + + String number = "2147483648"; + try { + int result = Integer.parseInt(number); + System.out.println(result); + } catch (NumberFormatException e) { + //do something for the exception. + System.err.println("Invalid number format : " + number); + } + + } + +} \ No newline at end of file diff --git a/java-string/src/main/java/com/mkyong/string/ConvertStringToInteger.java b/java-string/src/main/java/com/mkyong/string/ConvertStringToInteger.java new file mode 100644 index 0000000..982bd86 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/ConvertStringToInteger.java @@ -0,0 +1,26 @@ +package com.mkyong.string; + +public class ConvertStringToInteger { + + public static void main(String[] args) { + + /*String number = "99"; + + // String to integer + Integer result = Integer.valueOf(number); + + // 99 + System.out.println(result);*/ + + String number = "D99"; + try { + Integer result = Integer.valueOf(number); + System.out.println(result); + } catch (NumberFormatException e) { + //do something for the exception. + System.err.println("Invalid number format : " + number); + } + + } + +} \ No newline at end of file diff --git a/java-string/src/main/java/com/mkyong/string/ConvertStringToIntegerJava8.java b/java-string/src/main/java/com/mkyong/string/ConvertStringToIntegerJava8.java new file mode 100644 index 0000000..da8c298 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/ConvertStringToIntegerJava8.java @@ -0,0 +1,37 @@ +package com.mkyong.string; + +import java.util.Optional; + +public class ConvertStringToIntegerJava8 { + + public static void main(String[] args) { + + String number = "99"; + + Optional result = convertStringToInteger(number); + + if (result.isPresent()) { + System.out.println(result.get()); + } else { + System.err.println("Unable to convert the number : " + number); + } + + } + + private static Optional convertStringToInteger(String input) { + + if (input == null) return Optional.empty(); + + input = input.trim(); + + if (input.isEmpty()) return Optional.empty(); + + try { + return Optional.of(Integer.valueOf(input)); + } catch (NumberFormatException e) { + return Optional.empty(); + } + + } + +} \ No newline at end of file diff --git a/java-string/src/main/java/com/mkyong/string/split/StringSplit.java b/java-string/src/main/java/com/mkyong/string/split/StringSplit.java new file mode 100644 index 0000000..d9e416f --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/split/StringSplit.java @@ -0,0 +1,20 @@ +package com.mkyong.string.split; + +public class StringSplit { + + public static void main(String[] args) { + + String phone = "012-3456789"; + String[] output = phone.split("-"); + + System.out.println(output.length); // 2 + + String part1 = output[0]; // 012 + String part2 = output[1]; // 3456789 + + System.out.println(part1); // 012 + System.out.println(part2); // 3456789 + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/split/StringSplitContains.java b/java-string/src/main/java/com/mkyong/string/split/StringSplitContains.java new file mode 100644 index 0000000..b79902c --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/split/StringSplitContains.java @@ -0,0 +1,21 @@ +package com.mkyong.string.split; + +public class StringSplitContains { + + public static void main(String[] args) { + + String phone = "012-3456789"; + + if (phone.contains("-")) { + + String[] output = phone.split("-"); + System.out.println(output[0]); // 012 + System.out.println(output[1]); // 3456789 + + } else { + throw new IllegalArgumentException("String " + phone + " does not contain -"); + } + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/split/StringSplitJava8.java b/java-string/src/main/java/com/mkyong/string/split/StringSplitJava8.java new file mode 100644 index 0000000..8993918 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/split/StringSplitJava8.java @@ -0,0 +1,25 @@ +package com.mkyong.string.split; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class StringSplitJava8 { + + public static void main(String[] args) { + + String phone = "012-3456789"; + + /*List output = Pattern.compile("-") + .splitAsStream(phone) + .collect(Collectors.toList());*/ + + List output = Arrays.stream(phone.split("-")) + .collect(Collectors.toList()); + + System.out.println(output); + + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/split/StringSplitLimit.java b/java-string/src/main/java/com/mkyong/string/split/StringSplitLimit.java new file mode 100644 index 0000000..bde8c93 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/split/StringSplitLimit.java @@ -0,0 +1,22 @@ +package com.mkyong.string.split; + +public class StringSplitLimit { + + public static void main(String[] args) { + + String phone = "012-345-678-9"; + String[] output = phone.split("-", 3); + + System.out.println(output.length); // 3 + + String part1 = output[0]; // 012 + String part2 = output[1]; // 345 + String part3 = output[2]; // 678-9 + + System.out.println(part1); + System.out.println(part2); + System.out.println(part3); + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/split/StringSplitLookAround.java b/java-string/src/main/java/com/mkyong/string/split/StringSplitLookAround.java new file mode 100644 index 0000000..cfe9388 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/split/StringSplitLookAround.java @@ -0,0 +1,27 @@ +package com.mkyong.string.split; + +public class StringSplitLookAround { + + public static void main(String[] args) { + + String phone = "012-3456789"; + + if (phone.contains("-")) { + + // positive lookahead, split char at right-hand side + String[] output = phone.split("(?=-)"); + System.out.println(output[0]); // 012 + System.out.println(output[1]); // -3456789 + + // positive lookbehind, split char at left-hand side + String[] output2 = phone.split("(?<=-)"); + System.out.println(output2[0]); // 012- + System.out.println(output2[1]); // 3456789 + + } else { + throw new IllegalArgumentException("String " + phone + " does not contain -"); + } + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/split/StringSplitMultiDelimiters.java b/java-string/src/main/java/com/mkyong/string/split/StringSplitMultiDelimiters.java new file mode 100644 index 0000000..ca5e599 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/split/StringSplitMultiDelimiters.java @@ -0,0 +1,27 @@ +package com.mkyong.string.split; + +public class StringSplitMultiDelimiters { + + public static void main(String[] args) { + + String dir = "apple|9|1.88;2.78|0#10"; + String[] output = dir.split("[|;#]"); + + System.out.println(output.length); // 6 + + for (String s : output) { + System.out.println(s); + } + + /* + System.out.println(output[0]); // apple + System.out.println(output[1]); // 9 + System.out.println(output[2]); // 1.88 + System.out.println(output[3]); // 2.78 + System.out.println(output[4]); // 0 + System.out.println(output[5]); // 10 + */ + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/split/StringSplitNewLines.java b/java-string/src/main/java/com/mkyong/string/split/StringSplitNewLines.java new file mode 100644 index 0000000..95c6a4e --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/split/StringSplitNewLines.java @@ -0,0 +1,38 @@ +package com.mkyong.string.split; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class StringSplitNewLines { + + public static void main(String[] args) { + + StringBuilder sb = new StringBuilder(); + sb.append("aaa \n"); + sb.append("bbb \r\n"); + sb.append("ccc\n"); + sb.append("\n"); + sb.append("ddd\r\n"); + sb.append("\r\n"); + sb.append("eee\n"); + + String text = sb.toString(); + System.out.println("---Original---"); + System.out.println(text); + + System.out.println("---Split---"); + + // split by new line, trim and filter empty line + List lines = Arrays.stream(text.split("\\r?\\n")) + .map(x -> x.trim()) + .filter(x -> x.length() > 0) + .collect(Collectors.toList()); + + for (String line : lines) { + System.out.println(line); + } + + } + +} \ No newline at end of file diff --git a/java-string/src/main/java/com/mkyong/string/split/StringSplitSpaces.java b/java-string/src/main/java/com/mkyong/string/split/StringSplitSpaces.java new file mode 100644 index 0000000..ac21410 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/split/StringSplitSpaces.java @@ -0,0 +1,16 @@ +package com.mkyong.string.split; + +public class StringSplitSpaces { + + public static void main(String[] args) { + + String str = "1 2 3 4 5"; + String[] output = str.split("\\s+"); + + for (String s : output) { + System.out.println(s); + } + + } + +} \ No newline at end of file diff --git a/java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialBackslash.java b/java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialBackslash.java new file mode 100644 index 0000000..6eb9a73 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialBackslash.java @@ -0,0 +1,22 @@ +package com.mkyong.string.split; + +import java.util.regex.Pattern; + +public class StringSplitSpecialBackslash { + + public static void main(String[] args) { + + String dir = "C:\\Users\\mkyong\\projects\\mkyong-tutorials"; + + // three ways to escape regex special character + //String[] output = dir.split("\\\\"); + //String[] output = dir.split("[\\\\]"); + String[] output = dir.split(Pattern.quote("\\")); + + for (String s : output) { + System.out.println(s); + } + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialPeriod.java b/java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialPeriod.java new file mode 100644 index 0000000..8e8c584 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialPeriod.java @@ -0,0 +1,22 @@ +package com.mkyong.string.split; + +import java.util.regex.Pattern; + +public class StringSplitSpecialPeriod { + + public static void main(String[] args) { + + String dir = "a.b.c.d.e"; + + // three ways to escape regex special character + //String[] output = dir.split("\\."); + //String[] output = dir.split("[.]"); + String[] output = dir.split(Pattern.quote(".")); + + for (String s : output) { + System.out.println(s); + } + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialPipe.java b/java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialPipe.java new file mode 100644 index 0000000..a57b5fa --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialPipe.java @@ -0,0 +1,24 @@ +package com.mkyong.string.split; + +import java.util.regex.Pattern; + +public class StringSplitSpecialPipe { + + public static void main(String[] args) { + + String csv = "a|b|c|d"; + + // three ways to escape regex special character + // String[] output = csv.split("\\|"); + // String[] output = csv.split("[|]"); + String[] output = csv.split(Pattern.quote("|")); + + //System.out.println(output.length); + + for (String s : output) { + System.out.println(s); + } + + } + +} diff --git a/java-string/src/main/java/com/mkyong/string/split/StringSplitStringTokenizer.java b/java-string/src/main/java/com/mkyong/string/split/StringSplitStringTokenizer.java new file mode 100644 index 0000000..06afdb4 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/split/StringSplitStringTokenizer.java @@ -0,0 +1,21 @@ +package com.mkyong.string.split; + +import java.util.StringTokenizer; + +// This `StringTokenizer` is a legacy class, retained for compatibility reasons; +// the use is discouraged! Please upgrade the code to `String#split()`. +public class StringSplitStringTokenizer { + + public static void main(String[] args) { + + String test = "abc.def.123"; + // the delimiter is a string, not regex, no need to escape the dot + StringTokenizer token = new StringTokenizer(test, "."); + + while (token.hasMoreTokens()) { + System.out.println(token.nextToken()); + } + + } + +} \ No newline at end of file diff --git a/java-string/src/main/java/com/mkyong/string/utils/CustomStringUtils.java b/java-string/src/main/java/com/mkyong/string/utils/CustomStringUtils.java new file mode 100644 index 0000000..b50d6bb --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/utils/CustomStringUtils.java @@ -0,0 +1,27 @@ +package com.mkyong.string.utils; + +public class CustomStringUtils { + + public static boolean isNumber(String input) { + + // if null return false. + if (input == null) return false; + + // trim for extra spaces + input = input.trim(); + + // if empty return false + if ("".equals(input)) return false; + + if (input.startsWith("-") || input.startsWith("+")) { + // positive or negative numbers, cut the first char + // +1 -> 1, -1 -> 1 + return input.substring(1).matches("[0-9]+"); + } else { + // other numbers, let check it + return input.matches("[0-9]+"); + } + + } + +} diff --git a/java-string/src/test/java/com.mkyong.string/ConvertStringToIntTest.java b/java-string/src/test/java/com.mkyong.string/ConvertStringToIntTest.java new file mode 100644 index 0000000..89c6f40 --- /dev/null +++ b/java-string/src/test/java/com.mkyong.string/ConvertStringToIntTest.java @@ -0,0 +1,64 @@ +package com.mkyong.string; + +import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ConvertStringToIntTest { + + /*@ParameterizedTest(name = "#{index} - Run test with args={0}") + @MethodSource("stringProvider") + void testMethod(String input, int expected) { + assertEquals(Integer.parseInt(input), expected); + } + + static Stream stringProvider() { + return Stream.of( + arguments("20", 20), + arguments("+20", 20), + arguments("-20", -20) + ); + }*/ + + /*@ParameterizedTest(name = "#{index} - Run test with args={0}") + @ValueSource(strings = {" 1", "1 ", " 1 ", "+1", "-1", "100", "999", "2147483647"}) + void testStringToNumberValid(String input) { + assertTrue(StringUtils.isNumeric(input)); + } + + @ParameterizedTest(name = "#{index} - Run test with args={0}") + @ValueSource(strings = {"10A", "++1", "--1", "1.1", "10-1", "A10", "2147483648"}) + void testStringToNumberInValid(String input) { + assertFalse(StringUtils.isNumeric(input)); + }*/ + + @ParameterizedTest(name = "#{index} - Run test with args={0}") + @NullSource + @ValueSource(strings = {"", " "}) + void testBlankIncludeNull3(String input) { + assertTrue(StringUtils.isBlank(input)); + } + + @ParameterizedTest(name = "#{index} - Run test with args={0}") + @NullSource + @ValueSource(strings = {"", " "}) + void testBlankIncludeNull(String input) { + assertTrue(StringUtils.isBlank(input)); + } + + @ParameterizedTest(name = "#{index} - Run test with args={0}") + @MethodSource("blankOrNullStrings") + void testBlankIncludeNull2(String input) { + assertTrue(StringUtils.isBlank(input)); + } + + static Stream blankOrNullStrings() { + return Stream.of("", " ", null); + } +} From 09c1d4fc75e8bcad351ae4529b06485a120f4197 Mon Sep 17 00:00:00 2001 From: mkyong Date: Sun, 13 Feb 2022 16:03:44 +0800 Subject: [PATCH 08/15] inputstream to string --- .../string/ConvertInputStreamToString.java | 106 ++++++++++++++++++ .../string/ConvertStringToInputStream.java | 37 ++++++ 2 files changed, 143 insertions(+) create mode 100644 java-string/src/main/java/com/mkyong/string/ConvertInputStreamToString.java create mode 100644 java-string/src/main/java/com/mkyong/string/ConvertStringToInputStream.java diff --git a/java-string/src/main/java/com/mkyong/string/ConvertInputStreamToString.java b/java-string/src/main/java/com/mkyong/string/ConvertInputStreamToString.java new file mode 100644 index 0000000..28db45b --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/ConvertInputStreamToString.java @@ -0,0 +1,106 @@ +package com.mkyong.string; + +import java.io.*; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ConvertInputStreamToString { + + public static final int DEFAULT_BUFFER_SIZE = 8192; + + public static void main(String[] args) throws IOException { + + URI uri = URI.create("https://www.google.com/"); + try (InputStream inputStream = uri.toURL().openStream()) { + + // Convert InputStream -> String + String result = convertInputStreamToString4(inputStream); + + System.out.println(result); + + } + + } + + // Plain Java + private static String convertInputStreamToString(InputStream is) throws IOException { + + ByteArrayOutputStream result = new ByteArrayOutputStream(); + byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; + int length; + while ((length = is.read(buffer)) != -1) { + result.write(buffer, 0, length); + } + + // Java 1.1 + //return result.toString(StandardCharsets.UTF_8.name()); + + return result.toString("UTF-8"); + + // Java 10 + //return result.toString(StandardCharsets.UTF_8); + + } + + // @Java 9 -> inputStream.readAllBytes() + // max bytes Integer.MAX_VALUE, 2147483647, which is 2G + private static String convertInputStreamToStringJava9(InputStream inputStream) + throws IOException { + + return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + } + + // InputStreamReader + StringBuilder + private static String convertInputStreamToString2(InputStream inputStream) + throws IOException { + + final char[] buffer = new char[8192]; + final StringBuilder result = new StringBuilder(); + + // InputStream -> Reader + try (Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { + int charsRead; + while ((charsRead = reader.read(buffer, 0, buffer.length)) > 0) { + result.append(buffer, 0, charsRead); + } + } + + return result.toString(); + + } + + // InputStreamReader + BufferedReader (modify line breaks) + private static String convertInputStreamToString3(InputStream inputStream) + throws IOException { + + String newLine = System.getProperty("line.separator"); + StringBuilder result = new StringBuilder(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { + String line; + while ((line = reader.readLine()) != null) { + result + .append(line) + .append(newLine); + } + } + return result.toString(); + + } + + // Java 8 BufferedReader#lines (modify line breaks) + private static String convertInputStreamToString4(InputStream inputStream) + throws IOException { + + String newLine = System.getProperty("line.separator"); + String result; + try (Stream lines = new BufferedReader(new InputStreamReader(inputStream)).lines()) { + result = lines.collect(Collectors.joining(newLine)); + } + + return result; + + } + +} \ No newline at end of file diff --git a/java-string/src/main/java/com/mkyong/string/ConvertStringToInputStream.java b/java-string/src/main/java/com/mkyong/string/ConvertStringToInputStream.java new file mode 100644 index 0000000..4b61573 --- /dev/null +++ b/java-string/src/main/java/com/mkyong/string/ConvertStringToInputStream.java @@ -0,0 +1,37 @@ +package com.mkyong.string; + +import java.io.*; +import java.nio.charset.StandardCharsets; + +public class ConvertStringToInputStream { + + public static final int DEFAULT_BUFFER_SIZE = 8192; + + public static void main(String[] args) throws IOException { + + String name = "mkyong.com"; + + // String to InputStream + InputStream is = new ByteArrayInputStream(name.getBytes(StandardCharsets.UTF_8)); + + save(is, "c:\\test\\file.txt"); + + } + + // save the InputStream to a File + private static void save(final InputStream is, final String fileName) + throws IOException { + + // read bytes from InputStream and write it to FileOutputStream + try (FileOutputStream outputStream = + new FileOutputStream(new File(fileName), false)) { + int read; + byte[] bytes = new byte[DEFAULT_BUFFER_SIZE]; + while ((read = is.read(bytes)) != -1) { + outputStream.write(bytes, 0, read); + } + } + + } + +} \ No newline at end of file From fa33c45ea819de9e1dcb5a89aafae12bcddbafd7 Mon Sep 17 00:00:00 2001 From: mkyong Date: Sun, 13 Feb 2022 16:04:45 +0800 Subject: [PATCH 09/15] add common lang3 --- java-string/pom.xml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/java-string/pom.xml b/java-string/pom.xml index 7eef9d9..250717b 100644 --- a/java-string/pom.xml +++ b/java-string/pom.xml @@ -17,7 +17,8 @@ 17 17 17 - 5.4.0 + 5.8.2 + 3.12.0 @@ -25,10 +26,18 @@ org.junit.jupiter junit-jupiter-params - ${junit.version} + ${junit5.version} test + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + From 8542d187bd3bd9d9b6fa67de63f0e81b66e8b4c1 Mon Sep 17 00:00:00 2001 From: mkyong Date: Wed, 27 Jul 2022 19:01:34 +0800 Subject: [PATCH 10/15] prevent xxe --- .../mkyong/xml/jdom/ModifyXmlJDomParser.java | 7 ++++ .../xml/jdom/ReadXmlAlexaApiJDomParser.java | 7 ++++ .../mkyong/xml/jdom/ReadXmlJDomParser.java | 8 ++++ .../com/mkyong/xml/jdom/WriteXmlJDom.java | 2 +- .../com/mkyong/xml/sax/ReadXmlSaxParser.java | 18 ++++++--- .../mkyong/xml/sax/ReadXmlSaxParserXXE.java | 38 +++++++++++++++++++ .../xml/stax/ReadXmlStAXCursorParser.java | 13 ++++--- .../xml/stax/ReadXmlStAXEventParser.java | 7 ++++ java-xml/src/main/resources/staff-xxe.xml | 11 ++++++ 9 files changed, 98 insertions(+), 13 deletions(-) create mode 100644 java-xml/src/main/java/com/mkyong/xml/sax/ReadXmlSaxParserXXE.java create mode 100644 java-xml/src/main/resources/staff-xxe.xml diff --git a/java-xml/src/main/java/com/mkyong/xml/jdom/ModifyXmlJDomParser.java b/java-xml/src/main/java/com/mkyong/xml/jdom/ModifyXmlJDomParser.java index 7334e6e..fd5f102 100644 --- a/java-xml/src/main/java/com/mkyong/xml/jdom/ModifyXmlJDomParser.java +++ b/java-xml/src/main/java/com/mkyong/xml/jdom/ModifyXmlJDomParser.java @@ -9,6 +9,7 @@ import org.jdom2.output.Format; import org.jdom2.output.XMLOutputter; +import javax.xml.XMLConstants; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -21,6 +22,12 @@ public class ModifyXmlJDomParser { public static void main(String[] args) throws JDOMException, IOException { SAXBuilder sax = new SAXBuilder(); + + // https://rules.sonarsource.com/java/RSPEC-2755 + // prevent xxe + sax.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + sax.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + Document doc = sax.build(new File(FILENAME)); Element rootNode = doc.getRootElement(); diff --git a/java-xml/src/main/java/com/mkyong/xml/jdom/ReadXmlAlexaApiJDomParser.java b/java-xml/src/main/java/com/mkyong/xml/jdom/ReadXmlAlexaApiJDomParser.java index 87bdeef..0207485 100644 --- a/java-xml/src/main/java/com/mkyong/xml/jdom/ReadXmlAlexaApiJDomParser.java +++ b/java-xml/src/main/java/com/mkyong/xml/jdom/ReadXmlAlexaApiJDomParser.java @@ -5,6 +5,7 @@ import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; +import javax.xml.XMLConstants; import java.io.IOException; import java.net.URL; import java.util.List; @@ -18,6 +19,12 @@ public static void main(String[] args) { try { SAXBuilder sax = new SAXBuilder(); + + // https://rules.sonarsource.com/java/RSPEC-2755 + // prevent xxe + sax.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + sax.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + // XML is in a web-based location Document doc = sax.build(new URL(REMOTE_URL)); diff --git a/java-xml/src/main/java/com/mkyong/xml/jdom/ReadXmlJDomParser.java b/java-xml/src/main/java/com/mkyong/xml/jdom/ReadXmlJDomParser.java index fe3eae3..545c09e 100644 --- a/java-xml/src/main/java/com/mkyong/xml/jdom/ReadXmlJDomParser.java +++ b/java-xml/src/main/java/com/mkyong/xml/jdom/ReadXmlJDomParser.java @@ -5,6 +5,7 @@ import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; +import javax.xml.XMLConstants; import java.io.File; import java.io.IOException; import java.util.List; @@ -13,6 +14,7 @@ public class ReadXmlJDomParser { private static final String FILENAME = "src/main/resources/staff.xml"; + //private static final String FILENAME = "c://test//staff.xml"; // https://github.com/hunterhacker/jdom/wiki/JDOM2-A-Primer @@ -21,6 +23,12 @@ public static void main(String[] args) { try { SAXBuilder sax = new SAXBuilder(); + + // https://rules.sonarsource.com/java/RSPEC-2755 + // prevent xxe + sax.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + sax.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + // XML is a local file Document doc = sax.build(new File(FILENAME)); diff --git a/java-xml/src/main/java/com/mkyong/xml/jdom/WriteXmlJDom.java b/java-xml/src/main/java/com/mkyong/xml/jdom/WriteXmlJDom.java index e1c22c7..5924192 100644 --- a/java-xml/src/main/java/com/mkyong/xml/jdom/WriteXmlJDom.java +++ b/java-xml/src/main/java/com/mkyong/xml/jdom/WriteXmlJDom.java @@ -114,4 +114,4 @@ private static void writeSimpleXml() throws JDOMException, IOException { } -} +} \ No newline at end of file diff --git a/java-xml/src/main/java/com/mkyong/xml/sax/ReadXmlSaxParser.java b/java-xml/src/main/java/com/mkyong/xml/sax/ReadXmlSaxParser.java index b6ced15..cc35a4f 100644 --- a/java-xml/src/main/java/com/mkyong/xml/sax/ReadXmlSaxParser.java +++ b/java-xml/src/main/java/com/mkyong/xml/sax/ReadXmlSaxParser.java @@ -1,7 +1,8 @@ package com.mkyong.xml.sax; -import com.mkyong.xml.sax.handler.CountElementHandlerSax; +import com.mkyong.xml.sax.handler.PrintAllHandlerSax; import org.xml.sax.SAXException; + import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; @@ -19,10 +20,15 @@ public static void main(String[] args) { try { + // https://rules.sonarsource.com/java/RSPEC-2755 + // prevent XXE, completely disable DOCTYPE declaration: + // factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + SAXParser saxParser = factory.newSAXParser(); - // PrintAllHandlerSax handler = new PrintAllHandlerSax(); - // saxParser.parse(FILENAME, handler); + PrintAllHandlerSax handler = new PrintAllHandlerSax(); + + saxParser.parse(FILENAME, handler); /*XMLReader xmlReader = saxParser.getXMLReader(); xmlReader.setContentHandler(handler); @@ -32,10 +38,10 @@ public static void main(String[] args) { xmlReader.parse(source);*/ // count elements name known as "staff" - CountElementHandlerSax countStaffHandler = new CountElementHandlerSax("staff"); + /*CountElementHandlerSax countStaffHandler = new CountElementHandlerSax("staff"); saxParser.parse(FILENAME, countStaffHandler); - System.out.println("Number of staff elements : " + countStaffHandler.getCount()); + System.out.println("Number of staff elements : " + countStaffHandler.getCount());*/ } catch (ParserConfigurationException | SAXException | IOException e) { e.printStackTrace(); @@ -43,4 +49,4 @@ public static void main(String[] args) { } -} +} \ No newline at end of file diff --git a/java-xml/src/main/java/com/mkyong/xml/sax/ReadXmlSaxParserXXE.java b/java-xml/src/main/java/com/mkyong/xml/sax/ReadXmlSaxParserXXE.java new file mode 100644 index 0000000..c26ed51 --- /dev/null +++ b/java-xml/src/main/java/com/mkyong/xml/sax/ReadXmlSaxParserXXE.java @@ -0,0 +1,38 @@ +package com.mkyong.xml.sax; + +import com.mkyong.xml.sax.handler.PrintAllHandlerSax; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.IOException; + +public class ReadXmlSaxParserXXE { + + //private static final String FILENAME = "src/main/resources/staff.xml"; + private static final String FILENAME = "src/main/resources/staff-xxe.xml"; + + public static void main(String[] args) { + + SAXParserFactory factory = SAXParserFactory.newInstance(); + + try { + + // https://rules.sonarsource.com/java/RSPEC-2755 + // prevent XXE, completely disable DOCTYPE declaration: + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + + SAXParser saxParser = factory.newSAXParser(); + + PrintAllHandlerSax handler = new PrintAllHandlerSax(); + + saxParser.parse(FILENAME, handler); + + } catch (ParserConfigurationException | SAXException | IOException e) { + e.printStackTrace(); + } + + } + +} \ No newline at end of file diff --git a/java-xml/src/main/java/com/mkyong/xml/stax/ReadXmlStAXCursorParser.java b/java-xml/src/main/java/com/mkyong/xml/stax/ReadXmlStAXCursorParser.java index bc3872a..91b80df 100644 --- a/java-xml/src/main/java/com/mkyong/xml/stax/ReadXmlStAXCursorParser.java +++ b/java-xml/src/main/java/com/mkyong/xml/stax/ReadXmlStAXCursorParser.java @@ -1,19 +1,14 @@ package com.mkyong.xml.stax; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLEventReader; +import javax.xml.XMLConstants; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; -import javax.xml.stream.events.Attribute; -import javax.xml.stream.events.EndElement; -import javax.xml.stream.events.StartElement; import javax.xml.stream.events.XMLEvent; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Arrays; public class ReadXmlStAXCursorParser { @@ -76,6 +71,12 @@ private static void printXmlByXmlCursorReader(Path path) throws FileNotFoundException, XMLStreamException { XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); + + // https://rules.sonarsource.com/java/RSPEC-2755 + // prevent xxe + xmlInputFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + xmlInputFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + XMLStreamReader reader = xmlInputFactory.createXMLStreamReader( new FileInputStream(path.toFile())); diff --git a/java-xml/src/main/java/com/mkyong/xml/stax/ReadXmlStAXEventParser.java b/java-xml/src/main/java/com/mkyong/xml/stax/ReadXmlStAXEventParser.java index acbfb6a..9cccb18 100644 --- a/java-xml/src/main/java/com/mkyong/xml/stax/ReadXmlStAXEventParser.java +++ b/java-xml/src/main/java/com/mkyong/xml/stax/ReadXmlStAXEventParser.java @@ -1,5 +1,6 @@ package com.mkyong.xml.stax; +import javax.xml.XMLConstants; import javax.xml.namespace.QName; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLInputFactory; @@ -33,6 +34,12 @@ private static void printXmlByXmlEventReader(Path path) throws FileNotFoundException, XMLStreamException { XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); + + // https://rules.sonarsource.com/java/RSPEC-2755 + // prevent xxe + xmlInputFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + xmlInputFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + XMLEventReader reader = xmlInputFactory.createXMLEventReader( new FileInputStream(path.toFile())); diff --git a/java-xml/src/main/resources/staff-xxe.xml b/java-xml/src/main/resources/staff-xxe.xml new file mode 100644 index 0000000..60632ec --- /dev/null +++ b/java-xml/src/main/resources/staff-xxe.xml @@ -0,0 +1,11 @@ + + ]> + + + &xxe; + support + 5000 + + testing]]> + + \ No newline at end of file From c8afc0b26ad43f8e559320a5f7f1cae4e000df6e Mon Sep 17 00:00:00 2001 From: mkyong Date: Fri, 29 Jul 2022 15:47:20 +0800 Subject: [PATCH 11/15] convert string to xml --- .../xml/tips/ConvertStringToXmlDom.java | 89 +++++++++++++++++++ .../xml/tips/ConvertStringToXmlJDom2.java | 79 ++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 java-xml/src/main/java/com/mkyong/xml/tips/ConvertStringToXmlDom.java create mode 100644 java-xml/src/main/java/com/mkyong/xml/tips/ConvertStringToXmlJDom2.java diff --git a/java-xml/src/main/java/com/mkyong/xml/tips/ConvertStringToXmlDom.java b/java-xml/src/main/java/com/mkyong/xml/tips/ConvertStringToXmlDom.java new file mode 100644 index 0000000..3b962e4 --- /dev/null +++ b/java-xml/src/main/java/com/mkyong/xml/tips/ConvertStringToXmlDom.java @@ -0,0 +1,89 @@ +package com.mkyong.xml.tips; + +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; + +// DOM Parser +public class ConvertStringToXmlDom { + + final static String str = "\n" + + "\n" + + " \n" + + " mkyong\n" + + " support\n" + + " 5000\n" + + " \n" + + " testing]]>\n" + + " \n" + + " \n" + + " yflow\n" + + " admin\n" + + " 8000\n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + + // String to XML Document + Document document = convertStringToXml(str); + + // XML Document to String + String xml = convertXmlToString(document); + + System.out.println(xml); + + } + + private static String convertXmlToString(Document doc) { + DOMSource domSource = new DOMSource(doc); + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = null; + try { + transformer = tf.newTransformer(); + transformer.transform(domSource, result); + } catch (TransformerException e) { + throw new RuntimeException(e); + } + return writer.toString(); + } + + private static Document convertStringToXml(String xmlString) { + + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + + try { + + // optional, but recommended + // process XML securely, avoid attacks like XML External Entities (XXE) + dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + + DocumentBuilder builder = dbf.newDocumentBuilder(); + + Document doc = builder.parse(new InputSource(new StringReader(xmlString))); + + return doc; + + } catch (ParserConfigurationException | IOException | SAXException e) { + throw new RuntimeException(e); + } + + } + +} \ No newline at end of file diff --git a/java-xml/src/main/java/com/mkyong/xml/tips/ConvertStringToXmlJDom2.java b/java-xml/src/main/java/com/mkyong/xml/tips/ConvertStringToXmlJDom2.java new file mode 100644 index 0000000..748b3c5 --- /dev/null +++ b/java-xml/src/main/java/com/mkyong/xml/tips/ConvertStringToXmlJDom2.java @@ -0,0 +1,79 @@ +package com.mkyong.xml.tips; + +import org.jdom2.Document; +import org.jdom2.JDOMException; +import org.jdom2.input.SAXBuilder; +import org.jdom2.output.Format; +import org.jdom2.output.XMLOutputter; + +import javax.xml.XMLConstants; +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; + +// JDOM2 Parser +public class ConvertStringToXmlJDom2 { + + final static String str = "\n" + + "\n" + + " \n" + + " mkyong\n" + + " support\n" + + " 5000\n" + + " \n" + + " testing]]>\n" + + " \n" + + " \n" + + " yflow\n" + + " admin\n" + + " 8000\n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + + // String to XML Document + Document document = convertStringToXml(str); + + // XML Document to String + String xml = convertXmlDocumentToString(document); + + System.out.println(xml); + + } + + private static String convertXmlDocumentToString(Document doc) { + XMLOutputter xmlOutput = new XMLOutputter(); + xmlOutput.setFormat(Format.getPrettyFormat()); + + StringWriter result = new StringWriter(); + try { + xmlOutput.output(doc, result); + } catch (IOException e) { + throw new RuntimeException(e); + } + return result.toString(); + } + + private static Document convertStringToXml(String xmlString) { + + SAXBuilder sax = new SAXBuilder(); + + // https://rules.sonarsource.com/java/RSPEC-2755 + // prevent xxe + sax.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + sax.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + + try { + + Document doc = sax.build(new StringReader(xmlString)); + return doc; + + } catch (JDOMException | IOException e) { + throw new RuntimeException(e); + } + + } + +} \ No newline at end of file From ba989a0896638039334602e66dceb7963b77aea2 Mon Sep 17 00:00:00 2001 From: mkyong Date: Mon, 14 Nov 2022 16:53:45 +0800 Subject: [PATCH 12/15] java 18 --- java-18/pom.xml | 38 ++++++++++++++++ .../main/java/com/mkyong/java18/HelloApp.java | 9 ++++ .../java/com/mkyong/java18/jep418/JEP418.java | 23 ++++++++++ .../java/com/mkyong/java18/jep420/JEP420.java | 21 +++++++++ .../com/mkyong/java18/jep420/JEP420_2.java | 25 +++++++++++ .../java/com/mkyong/java18/jep421/JEP421.java | 43 +++++++++++++++++++ java-18/src/main/resources/test.html | 5 +++ 7 files changed, 164 insertions(+) create mode 100644 java-18/pom.xml create mode 100644 java-18/src/main/java/com/mkyong/java18/HelloApp.java create mode 100644 java-18/src/main/java/com/mkyong/java18/jep418/JEP418.java create mode 100644 java-18/src/main/java/com/mkyong/java18/jep420/JEP420.java create mode 100644 java-18/src/main/java/com/mkyong/java18/jep420/JEP420_2.java create mode 100644 java-18/src/main/java/com/mkyong/java18/jep421/JEP421.java create mode 100644 java-18/src/main/resources/test.html diff --git a/java-18/pom.xml b/java-18/pom.xml new file mode 100644 index 0000000..9f4a0ed --- /dev/null +++ b/java-18/pom.xml @@ -0,0 +1,38 @@ + + 4.0.0 + com.mkyong + java18 + 1.0 + + java-18 + https://mkyong.com + + + UTF-8 + 18 + 18 + 18 + + + + + + + java18 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 18 + 18 + --enable-preview + + + + + diff --git a/java-18/src/main/java/com/mkyong/java18/HelloApp.java b/java-18/src/main/java/com/mkyong/java18/HelloApp.java new file mode 100644 index 0000000..0cdd0c5 --- /dev/null +++ b/java-18/src/main/java/com/mkyong/java18/HelloApp.java @@ -0,0 +1,9 @@ +package com.mkyong.java18; + +public class HelloApp { + + public static void main(String[] args) { + System.out.println("Hello Java 17"); + } + +} \ No newline at end of file diff --git a/java-18/src/main/java/com/mkyong/java18/jep418/JEP418.java b/java-18/src/main/java/com/mkyong/java18/jep418/JEP418.java new file mode 100644 index 0000000..cc9173d --- /dev/null +++ b/java-18/src/main/java/com/mkyong/java18/jep418/JEP418.java @@ -0,0 +1,23 @@ +package com.mkyong.java18.jep418; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.net.spi.InetAddressResolver; +import java.net.spi.InetAddressResolverProvider; + +public class JEP418 { + + public static void main(String[] args) throws UnknownHostException { + + // Returns a set of ip address, ipv4 and ipv6. + InetAddress[] machines = InetAddress.getAllByName("google.com"); + for (InetAddress address : machines) { + System.out.println(address.getHostAddress()); + } + + // Returns first address in its set of addresses. + InetAddress ip = InetAddress.getByName("google.com"); + System.out.println(ip.getHostAddress()); + + } +} diff --git a/java-18/src/main/java/com/mkyong/java18/jep420/JEP420.java b/java-18/src/main/java/com/mkyong/java18/jep420/JEP420.java new file mode 100644 index 0000000..a3604a1 --- /dev/null +++ b/java-18/src/main/java/com/mkyong/java18/jep420/JEP420.java @@ -0,0 +1,21 @@ +package com.mkyong.java18.jep420; + +public class JEP420 { + + public static void main(String[] args) { + + } + + // java: this case label is dominated by a preceding case label + /*static void error (Object o){ + switch (o) { + case CharSequence cs -> System.out.println("A sequence of length " + cs.length()); + case String s -> // Error - pattern is dominated by previous pattern + System.out.println("A string: " + s); + default -> { + break; + } + } + }*/ + +} diff --git a/java-18/src/main/java/com/mkyong/java18/jep420/JEP420_2.java b/java-18/src/main/java/com/mkyong/java18/jep420/JEP420_2.java new file mode 100644 index 0000000..67095ac --- /dev/null +++ b/java-18/src/main/java/com/mkyong/java18/jep420/JEP420_2.java @@ -0,0 +1,25 @@ +package com.mkyong.java18.jep420; + +public class JEP420_2 { + + // java: the switch expression does not cover all possible input values + // error + /*static int coverage(Object o) { + return switch (o) { // Error - not exhaustive + case String s -> s.length(); + case Integer i -> i; + }; + }*/ + + static int coverage(Object o) { + return switch (o) { + case String s -> s.length(); + case Integer i -> i; + default -> 0; + }; + } + + public static void main(String[] args) { + System.out.println("Hello JEP 420"); + } +} diff --git a/java-18/src/main/java/com/mkyong/java18/jep421/JEP421.java b/java-18/src/main/java/com/mkyong/java18/jep421/JEP421.java new file mode 100644 index 0000000..ddc1ca3 --- /dev/null +++ b/java-18/src/main/java/com/mkyong/java18/jep421/JEP421.java @@ -0,0 +1,43 @@ +package com.mkyong.java18.jep421; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +public class JEP421 { + + public static void main(String[] args) throws IOException { + + String file1 = "/Home/mkyong/file1"; + String file2 = "/Home/mkyong/file1"; + + FileInputStream input = null; + FileOutputStream output = null; + try { + input = new FileInputStream(file1); + output = new FileOutputStream(file2); + + // copy files from file1 to file 2 + + output.close(); + output = null; + input.close(); + input = null; + } finally { + if (output != null) output.close(); + if (input != null) input.close(); + } + + /*try (FileInputStream input = new FileInputStream(file1); + FileOutputStream output = new FileOutputStream(file2)) { + // + }*/ + + + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + } +} diff --git a/java-18/src/main/resources/test.html b/java-18/src/main/resources/test.html new file mode 100644 index 0000000..67ef16d --- /dev/null +++ b/java-18/src/main/resources/test.html @@ -0,0 +1,5 @@ + + +

Hello, World

+ + \ No newline at end of file From 49e00875c535efaa7a41fd21bdacd80b7afdbac8 Mon Sep 17 00:00:00 2001 From: mkyong Date: Mon, 14 Nov 2022 16:54:31 +0800 Subject: [PATCH 13/15] update --- java-18/src/main/resources/test.html | 5 ----- java-string/pom.xml | 9 +++++++++ .../mkyong/string/split/StringSplitSpecialBackslash.java | 4 ++-- 3 files changed, 11 insertions(+), 7 deletions(-) delete mode 100644 java-18/src/main/resources/test.html diff --git a/java-18/src/main/resources/test.html b/java-18/src/main/resources/test.html deleted file mode 100644 index 67ef16d..0000000 --- a/java-18/src/main/resources/test.html +++ /dev/null @@ -1,5 +0,0 @@ - - -

Hello, World

- - \ No newline at end of file diff --git a/java-string/pom.xml b/java-string/pom.xml index 250717b..150bf01 100644 --- a/java-string/pom.xml +++ b/java-string/pom.xml @@ -19,6 +19,7 @@ 17 5.8.2 3.12.0 + 1.9 @@ -38,6 +39,14 @@ ${commons-lang3.version} + + + + org.apache.commons + commons-text + ${commons-text.version} + + diff --git a/java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialBackslash.java b/java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialBackslash.java index 6eb9a73..811b361 100644 --- a/java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialBackslash.java +++ b/java-string/src/main/java/com/mkyong/string/split/StringSplitSpecialBackslash.java @@ -9,8 +9,8 @@ public static void main(String[] args) { String dir = "C:\\Users\\mkyong\\projects\\mkyong-tutorials"; // three ways to escape regex special character - //String[] output = dir.split("\\\\"); - //String[] output = dir.split("[\\\\]"); + // String[] output = dir.split("\\\\"); + // String[] output = dir.split("[\\\\]"); String[] output = dir.split(Pattern.quote("\\")); for (String s : output) { From b2390d1760b9c81ff3963773b2b3f28cad8e63fd Mon Sep 17 00:00:00 2001 From: mkyong Date: Mon, 28 Nov 2022 07:55:44 +0800 Subject: [PATCH 14/15] java 19 --- .../main/java/com/mkyong/java18/HelloApp.java | 9 --- java-19/pom.xml | 38 +++++++++++++ .../java/com/mkyong/java19/jep405/JEP405.java | 25 ++++++++ .../com/mkyong/java19/jep405/JEP405_1.java | 23 ++++++++ .../com/mkyong/java19/jep424/JEP424_SORT.java | 57 +++++++++++++++++++ .../mkyong/java19/jep424/JEP424_STRLEN.java | 34 +++++++++++ .../java/com/mkyong/java19/jep425/JEP425.java | 32 +++++++++++ .../java/com/mkyong/java19/jep427/JEP427.java | 31 ++++++++++ .../java/com/mkyong/java19/jep428/JEP428.java | 50 ++++++++++++++++ 9 files changed, 290 insertions(+), 9 deletions(-) delete mode 100644 java-18/src/main/java/com/mkyong/java18/HelloApp.java create mode 100644 java-19/pom.xml create mode 100644 java-19/src/main/java/com/mkyong/java19/jep405/JEP405.java create mode 100644 java-19/src/main/java/com/mkyong/java19/jep405/JEP405_1.java create mode 100644 java-19/src/main/java/com/mkyong/java19/jep424/JEP424_SORT.java create mode 100644 java-19/src/main/java/com/mkyong/java19/jep424/JEP424_STRLEN.java create mode 100644 java-19/src/main/java/com/mkyong/java19/jep425/JEP425.java create mode 100644 java-19/src/main/java/com/mkyong/java19/jep427/JEP427.java create mode 100644 java-19/src/main/java/com/mkyong/java19/jep428/JEP428.java diff --git a/java-18/src/main/java/com/mkyong/java18/HelloApp.java b/java-18/src/main/java/com/mkyong/java18/HelloApp.java deleted file mode 100644 index 0cdd0c5..0000000 --- a/java-18/src/main/java/com/mkyong/java18/HelloApp.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.mkyong.java18; - -public class HelloApp { - - public static void main(String[] args) { - System.out.println("Hello Java 17"); - } - -} \ No newline at end of file diff --git a/java-19/pom.xml b/java-19/pom.xml new file mode 100644 index 0000000..3f2c5ce --- /dev/null +++ b/java-19/pom.xml @@ -0,0 +1,38 @@ + + 4.0.0 + com.mkyong + java19 + 1.0 + + java-19 + https://mkyong.com + + + UTF-8 + 19 + 19 + 19 + + + + + + + java19 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 19 + 19 + --enable-preview + + + + + diff --git a/java-19/src/main/java/com/mkyong/java19/jep405/JEP405.java b/java-19/src/main/java/com/mkyong/java19/jep405/JEP405.java new file mode 100644 index 0000000..edc2b29 --- /dev/null +++ b/java-19/src/main/java/com/mkyong/java19/jep405/JEP405.java @@ -0,0 +1,25 @@ +package com.mkyong.java19.jep405; + +public class JEP405 { + + record Point(int x, int y) { + } + + static void printSum(Object o) { + if (o instanceof Point p) { + int x = p.x(); // get x() + int y = p.y(); // get y() + System.out.println(x + y); + } + } + + static void printSumNew(Object o) { + if (o instanceof Point(int x,int y)) { // record pattern + System.out.println(x + y); + } + } + + public static void main(String[] args) { + printSumNew(new Point(10, 20)); // output 30 + } +} \ No newline at end of file diff --git a/java-19/src/main/java/com/mkyong/java19/jep405/JEP405_1.java b/java-19/src/main/java/com/mkyong/java19/jep405/JEP405_1.java new file mode 100644 index 0000000..558ba90 --- /dev/null +++ b/java-19/src/main/java/com/mkyong/java19/jep405/JEP405_1.java @@ -0,0 +1,23 @@ +package com.mkyong.java19.jep405; + +public class JEP405_1 { + + record Point(int x, int y) { + } + + record Total(Point p1, Point p2) { + } + + static void printSum(Object o) { + // record nested pattern + if (o instanceof Total(Point(int x,int y),Point(int x2,int y2))) { + System.out.println(x + y + x2 + y2); + } + } + + public static void main(String[] args) { + + printSum(new Total(new Point(10, 5), new Point(2, 3))); + + } +} diff --git a/java-19/src/main/java/com/mkyong/java19/jep424/JEP424_SORT.java b/java-19/src/main/java/com/mkyong/java19/jep424/JEP424_SORT.java new file mode 100644 index 0000000..56bf31c --- /dev/null +++ b/java-19/src/main/java/com/mkyong/java19/jep424/JEP424_SORT.java @@ -0,0 +1,57 @@ +package com.mkyong.java19.jep424; + +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.Linker; +import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.ValueLayout; +import java.lang.invoke.MethodHandle; + +import static java.lang.foreign.ValueLayout.*; + +public class JEP424_SORT { + + public static void main(String[] args) throws Throwable { + + // 1. Find foreign function on the C library path + Linker linker = Linker.nativeLinker(); + SymbolLookup stdlib = linker.defaultLookup(); + + // 2. Allocate on-heap memory to store strings + String[] javaStrings = {"d", "z", "b", "c", "a"}; + + // 3. Allocate off-heap memory to store pointers + SegmentAllocator allocator = SegmentAllocator.implicitAllocator(); + MemorySegment offHeap = allocator.allocateArray(ValueLayout.ADDRESS, javaStrings.length); + + // 4. Copy the strings from on-heap to off-heap + for (int i = 0; i < javaStrings.length; i++) { + + // Allocate a string off-heap, then store a pointer to it + MemorySegment cString = allocator.allocateUtf8String(javaStrings[i]); + offHeap.setAtIndex(ValueLayout.ADDRESS, i, cString); + } + + MethodHandle radixSort = linker.downcallHandle( + stdlib.lookup("radixsort").orElseThrow(), + FunctionDescriptor.ofVoid(ADDRESS, JAVA_INT, ADDRESS, JAVA_CHAR)); + + // 5. Sort the off-heap data by calling the foreign function + radixSort.invoke(offHeap, javaStrings.length, MemoryAddress.NULL, '\0'); + + // 6. Copy the (reordered) strings from off-heap to on-heap + for (int i = 0; i < javaStrings.length; i++) { + MemoryAddress cStringPtr = offHeap.getAtIndex(ValueLayout.ADDRESS, i); + javaStrings[i] = cStringPtr.getUtf8String(0); + } + + //print sort result + for (String javaString : javaStrings) { + System.out.println(javaString); + } + + } + +} diff --git a/java-19/src/main/java/com/mkyong/java19/jep424/JEP424_STRLEN.java b/java-19/src/main/java/com/mkyong/java19/jep424/JEP424_STRLEN.java new file mode 100644 index 0000000..652638d --- /dev/null +++ b/java-19/src/main/java/com/mkyong/java19/jep424/JEP424_STRLEN.java @@ -0,0 +1,34 @@ +package com.mkyong.java19.jep424; + +import java.lang.foreign.*; +import java.lang.invoke.MethodHandle; + +import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.lang.foreign.ValueLayout.JAVA_LONG; + +public class JEP424_STRLEN { + + public static void main(String[] args) throws Throwable { + + String input = "Hello World"; + + // 1. Find foreign function on the C library path + SymbolLookup stdlib = Linker.nativeLinker().defaultLookup(); + + // 2. Get a handle to the "strlen" function in the C standard library + MethodHandle methodHandle = Linker.nativeLinker().downcallHandle( + stdlib.lookup("strlen").orElseThrow(), + FunctionDescriptor.of(JAVA_LONG, ADDRESS)); + + // 3. Allocate off-heap memory to store strings + MemorySegment memorySegment = SegmentAllocator + .implicitAllocator().allocateUtf8String(input); + + // 4. Runs the foreign function "strlen" + long length = (long) methodHandle.invoke(memorySegment); + + System.out.println("length = " + length); + + } + +} diff --git a/java-19/src/main/java/com/mkyong/java19/jep425/JEP425.java b/java-19/src/main/java/com/mkyong/java19/jep425/JEP425.java new file mode 100644 index 0000000..070cc20 --- /dev/null +++ b/java-19/src/main/java/com/mkyong/java19/jep425/JEP425.java @@ -0,0 +1,32 @@ +package com.mkyong.java19.jep425; + +import java.time.Duration; +import java.util.concurrent.Executors; +import java.util.stream.IntStream; + +public class JEP425 { + + public static void main(String[] args) { + + try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { + IntStream.range(0, 10_000).forEach(i -> { + executor.submit(() -> { + Thread.sleep(Duration.ofSeconds(1)); + return i; + }); + }); + } // executor.close() is called implicitly, and waits + + /*try (var executor = Executors.newFixedThreadPool(20)) { + IntStream.range(0, 10_000).forEach(i -> { + executor.submit(() -> { + Thread.sleep(Duration.ofSeconds(1)); + return i; + }); + }); + }*/ + + System.out.println("Done"); + + } +} diff --git a/java-19/src/main/java/com/mkyong/java19/jep427/JEP427.java b/java-19/src/main/java/com/mkyong/java19/jep427/JEP427.java new file mode 100644 index 0000000..9d6724a --- /dev/null +++ b/java-19/src/main/java/com/mkyong/java19/jep427/JEP427.java @@ -0,0 +1,31 @@ +package com.mkyong.java19.jep427; + +public class JEP427 { + + public static void main(String[] args) { + + testJava19("mkyong"); + testJava19("mkyongmkyong"); + } + + /* Old guarded pattern + static void test(Object o) { + switch (o) { + case String s && s.length() > 6 -> System.out.println("String's length longer than 10!"); + case String s -> System.out.println("String's length is " + s.length()); + default -> { + } + } + }*/ + + //Guarded patterns are replaced with when clauses in switch blocks. + static void testJava19(Object o) { + switch (o) { + case String s + when s.length() > 10 -> System.out.println("String's length longer than 10!"); + case String s -> System.out.println("String's length is " + s.length()); + default -> {} + } + } + +} diff --git a/java-19/src/main/java/com/mkyong/java19/jep428/JEP428.java b/java-19/src/main/java/com/mkyong/java19/jep428/JEP428.java new file mode 100644 index 0000000..7f771f2 --- /dev/null +++ b/java-19/src/main/java/com/mkyong/java19/jep428/JEP428.java @@ -0,0 +1,50 @@ +package com.mkyong.java19.jep428; + +import java.time.Duration; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class JEP428 { + + public static void main(String[] args) throws ExecutionException, InterruptedException { + JEP428 obj = new JEP428(); + obj.handleUnStructureAPI(); + } + + Response handleUnStructureAPI() throws ExecutionException, InterruptedException { + try (var executor = Executors.newFixedThreadPool(10)) { + Future user = executor.submit(this::findUser); + Future order = executor.submit(this::fetchOrder); + String theUser = user.get(); // Join findUser + int theOrder = order.get(); // Join fetchOrder + return new Response(theUser, theOrder); + } + } + + /*Response handleStructureAPI() throws ExecutionException, InterruptedException { + try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { + Future user = scope.fork(this::findUser); + Future order = scope.fork(this::fetchOrder); + + scope.join(); // Join both forks + scope.throwIfFailed(); // ... and propagate errors + + // Here, both forks have succeeded, so compose their results + return new Response(user.resultNow(), order.resultNow()); + } + }*/ + + private String findUser() throws InterruptedException { + Thread.sleep(Duration.ofSeconds(1)); + return "mkyong"; + } + + private Integer fetchOrder() throws InterruptedException { + Thread.sleep(Duration.ofSeconds(1)); + return 1; + } + + record Response(String x, int y) { + } +} From 3e0082dc2305c447759b57a1de412ea5cd934166 Mon Sep 17 00:00:00 2001 From: mkyong Date: Fri, 17 May 2024 17:13:07 +0800 Subject: [PATCH 15/15] update traverse files from a folder --- java-io/pom.xml | 2 +- .../mkyong/io/howto/FileTraverseExample.java | 28 +++++++++++++ .../mkyong/io/howto/FileTraverseExample2.java | 38 ++++++++++++++++++ .../mkyong/io/howto/FileTraverseExample3.java | 40 +++++++++++++++++++ 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 java-io/src/main/java/com/mkyong/io/howto/FileTraverseExample.java create mode 100644 java-io/src/main/java/com/mkyong/io/howto/FileTraverseExample2.java create mode 100644 java-io/src/main/java/com/mkyong/io/howto/FileTraverseExample3.java diff --git a/java-io/pom.xml b/java-io/pom.xml index f2ca168..cbf8ea1 100644 --- a/java-io/pom.xml +++ b/java-io/pom.xml @@ -16,7 +16,7 @@ UTF-8 17 17 - 17 + 21 5.4.0 diff --git a/java-io/src/main/java/com/mkyong/io/howto/FileTraverseExample.java b/java-io/src/main/java/com/mkyong/io/howto/FileTraverseExample.java new file mode 100644 index 0000000..3d23fb5 --- /dev/null +++ b/java-io/src/main/java/com/mkyong/io/howto/FileTraverseExample.java @@ -0,0 +1,28 @@ +package com.mkyong.io.howto; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.stream.Stream; + +public class FileTraverseExample { + + public static void main(String[] args) { + + // Specify the directory we want to traverse + String dirPath = "/Users/yongmookkim/projects/test/"; + + // Traverse the directory and process files + try (Stream paths = Files.walk(Paths.get(dirPath))) { + + paths + .filter(Files::isRegularFile) // ensure it is a file + .forEach(System.out::println); // prints the file path + + } catch (IOException e) { + throw new RuntimeException(e); + } + + } +} diff --git a/java-io/src/main/java/com/mkyong/io/howto/FileTraverseExample2.java b/java-io/src/main/java/com/mkyong/io/howto/FileTraverseExample2.java new file mode 100644 index 0000000..e9a6a83 --- /dev/null +++ b/java-io/src/main/java/com/mkyong/io/howto/FileTraverseExample2.java @@ -0,0 +1,38 @@ +package com.mkyong.io.howto; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.stream.Stream; + +public class FileTraverseExample2 { + + public static void main(String[] args) { + + List result; + + // Specify the directory we want to traverse + String dirPath = "/Users/yongmookkim/projects/test/"; + + // Traverse the directory and process files + try (Stream paths = Files.walk(Paths.get(dirPath))) { + + result = paths + .filter(Files::isRegularFile) // ensure it is a file + .map(p -> p.getFileName().toString()) + .toList(); + + } catch (IOException e) { + throw new RuntimeException(e); + } + + System.out.println("Total files: " + result.size()); + for (String name : result) { + System.out.println("FileName: " + name); + } + + + } +} diff --git a/java-io/src/main/java/com/mkyong/io/howto/FileTraverseExample3.java b/java-io/src/main/java/com/mkyong/io/howto/FileTraverseExample3.java new file mode 100644 index 0000000..1d5c4e7 --- /dev/null +++ b/java-io/src/main/java/com/mkyong/io/howto/FileTraverseExample3.java @@ -0,0 +1,40 @@ +package com.mkyong.io.howto; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Optional; +import java.util.stream.Stream; + +public class FileTraverseExample3 { + + public static void main(String[] args) { + + String dir = "/Users/yongmookkim/projects/test/"; + String findThisFile = "a.txt"; + + try { + + Optional foundFile = findFileByName(Paths.get(dir), findThisFile); + foundFile.ifPresentOrElse( + file -> System.out.println("File found: " + file), + () -> System.out.println("File not found.") + ); + + } catch (IOException e) { + System.err.println("An error occurred while searching for the file: " + e.getMessage()); + } + + } + + public static Optional findFileByName(Path directory, String fileName) throws IOException { + try (Stream stream = Files.walk(directory)) { + return stream + .filter(Files::isRegularFile) + .filter(path -> path.getFileName().toString().equals(fileName)) + .findFirst(); + } + } + +}