Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
1fca4ae95e
|
@ -1,9 +1,14 @@
|
||||||
|
|
||||||
The "REST with Spring" Classes
|
The "REST with Spring" Classes
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
After 5 months of work, here's the Master Class of REST With Spring: <br/>
|
After 5 months of work, here's the Master Class of REST With Spring: <br/>
|
||||||
**[>> THE REST WITH SPRING MASTER CLASS](http://www.baeldung.com/rest-with-spring-course?utm_source=github&utm_medium=social&utm_content=tutorials&utm_campaign=rws#master-class)**
|
**[>> THE REST WITH SPRING MASTER CLASS](http://www.baeldung.com/rest-with-spring-course?utm_source=github&utm_medium=social&utm_content=tutorials&utm_campaign=rws#master-class)**
|
||||||
|
|
||||||
|
And here's the Master Class of Learn Spring Security: <br/>
|
||||||
|
**[>> LEARN SPRING SECURITY MASTER CLASS](http://www.baeldung.com/learn-spring-security-course?utm_source=github&utm_medium=social&utm_content=tutorials&utm_campaign=lss#master-class)**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Spring Tutorials
|
Spring Tutorials
|
||||||
================
|
================
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.baeldung.concurrent.waitandnotify;
|
||||||
|
|
||||||
|
public class Data {
|
||||||
|
private String packet;
|
||||||
|
|
||||||
|
// True if receiver should wait
|
||||||
|
// False if sender should wait
|
||||||
|
private boolean transfer = true;
|
||||||
|
|
||||||
|
public synchronized String receive() {
|
||||||
|
while (transfer) {
|
||||||
|
try {
|
||||||
|
wait();
|
||||||
|
} catch (InterruptedException e) {}
|
||||||
|
}
|
||||||
|
transfer = true;
|
||||||
|
|
||||||
|
notifyAll();
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void send(String packet) {
|
||||||
|
while (!transfer) {
|
||||||
|
try {
|
||||||
|
wait();
|
||||||
|
} catch (InterruptedException e) {}
|
||||||
|
}
|
||||||
|
transfer = false;
|
||||||
|
|
||||||
|
this.packet = packet;
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.baeldung.concurrent.waitandnotify;
|
||||||
|
|
||||||
|
public class NetworkDriver {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Data data = new Data();
|
||||||
|
Thread sender = new Thread(new Sender(data));
|
||||||
|
Thread receiver = new Thread(new Receiver(data));
|
||||||
|
|
||||||
|
sender.start();
|
||||||
|
receiver.start();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.baeldung.concurrent.waitandnotify;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
public class Receiver implements Runnable {
|
||||||
|
private Data load;
|
||||||
|
|
||||||
|
public Receiver(Data load) {
|
||||||
|
this.load = load;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
for(String receivedMessage = load.receive();
|
||||||
|
!"End".equals(receivedMessage) ;
|
||||||
|
receivedMessage = load.receive()) {
|
||||||
|
|
||||||
|
System.out.println(receivedMessage);
|
||||||
|
|
||||||
|
//Thread.sleep() to mimic heavy server-side processing
|
||||||
|
try {
|
||||||
|
Thread.sleep(ThreadLocalRandom.current().nextInt(1000, 5000));
|
||||||
|
} catch (InterruptedException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.baeldung.concurrent.waitandnotify;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
public class Sender implements Runnable {
|
||||||
|
private Data data;
|
||||||
|
|
||||||
|
public Sender(Data data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
String packets[] = {
|
||||||
|
"First packet",
|
||||||
|
"Second packet",
|
||||||
|
"Third packet",
|
||||||
|
"Fourth packet",
|
||||||
|
"End"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (String packet : packets) {
|
||||||
|
data.send(packet);
|
||||||
|
|
||||||
|
//Thread.sleep() to mimic heavy server-side processing
|
||||||
|
try {
|
||||||
|
Thread.sleep(ThreadLocalRandom.current().nextInt(1000, 5000));
|
||||||
|
} catch (InterruptedException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.baeldung.concurrent.waitandnotify;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class NetworkIntegrationTest {
|
||||||
|
|
||||||
|
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
|
||||||
|
private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
|
||||||
|
private String expected;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUpStreams() {
|
||||||
|
System.setOut(new PrintStream(outContent));
|
||||||
|
System.setErr(new PrintStream(errContent));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUpExpectedOutput() {
|
||||||
|
StringWriter expectedStringWriter = new StringWriter();
|
||||||
|
|
||||||
|
PrintWriter printWriter = new PrintWriter(expectedStringWriter);
|
||||||
|
printWriter.println("First packet");
|
||||||
|
printWriter.println("Second packet");
|
||||||
|
printWriter.println("Third packet");
|
||||||
|
printWriter.println("Fourth packet");
|
||||||
|
printWriter.close();
|
||||||
|
|
||||||
|
expected = expectedStringWriter.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void cleanUpStreams() {
|
||||||
|
System.setOut(null);
|
||||||
|
System.setErr(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenSenderAndReceiver_whenSendingPackets_thenNetworkSynchronized() {
|
||||||
|
Data data = new Data();
|
||||||
|
Thread sender = new Thread(new Sender(data));
|
||||||
|
Thread receiver = new Thread(new Receiver(data));
|
||||||
|
|
||||||
|
sender.start();
|
||||||
|
receiver.start();
|
||||||
|
|
||||||
|
//wait for sender and receiver to finish before we test against expected
|
||||||
|
try {
|
||||||
|
sender.join();
|
||||||
|
receiver.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(expected, outContent.toString());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +0,0 @@
|
||||||
package com.baeldung.nestedclass;
|
|
||||||
|
|
||||||
public class Enclosing {
|
|
||||||
|
|
||||||
public static class Nested {
|
|
||||||
|
|
||||||
public void test() {
|
|
||||||
System.out.println("Calling test...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package com.baeldung.nestedclass;
|
|
||||||
|
|
||||||
public class Outer {
|
|
||||||
|
|
||||||
public class Inner {
|
|
||||||
|
|
||||||
public void test() {
|
|
||||||
System.out.println("Calling test...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
package com.baeldung.nestedclass;
|
|
||||||
|
|
||||||
abstract class SimpleAbstractClass {
|
|
||||||
abstract void run();
|
|
||||||
}
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.baeldung.polymorphism;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class FileManager {
|
||||||
|
|
||||||
|
final static Logger logger = LoggerFactory.getLogger(FileManager.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
GenericFile file1 = new TextFile("SampleTextFile", "This is a sample text content", "v1.0.0");
|
||||||
|
logger.info("File Info: \n" + file1.getFileInfo() + "\n");
|
||||||
|
ImageFile imageFile = new ImageFile("SampleImageFile", 200, 100, new BufferedImage(100, 200, BufferedImage.TYPE_INT_RGB).toString()
|
||||||
|
.getBytes(), "v1.0.0");
|
||||||
|
logger.info("File Info: \n" + imageFile.getFileInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ImageFile createImageFile(String name, int height, int width, byte[] content, String version) {
|
||||||
|
ImageFile imageFile = new ImageFile(name, height, width, content, version);
|
||||||
|
logger.info("File 2 Info: \n" + imageFile.getFileInfo());
|
||||||
|
return imageFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GenericFile createTextFile(String name, String content, String version) {
|
||||||
|
GenericFile file1 = new TextFile(name, content, version);
|
||||||
|
logger.info("File 1 Info: \n" + file1.getFileInfo() + "\n");
|
||||||
|
return file1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TextFile createTextFile2(String name, String content, String version) {
|
||||||
|
TextFile file1 = new TextFile(name, content, version);
|
||||||
|
logger.info("File 1 Info: \n" + file1.getFileInfo() + "\n");
|
||||||
|
return file1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.baeldung.polymorphism;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class GenericFile {
|
||||||
|
private String name;
|
||||||
|
private String extension;
|
||||||
|
private Date dateCreated;
|
||||||
|
private String version;
|
||||||
|
private byte[] content;
|
||||||
|
|
||||||
|
public GenericFile() {
|
||||||
|
this.setDateCreated(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExtension() {
|
||||||
|
return extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExtension(String extension) {
|
||||||
|
this.extension = extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDateCreated() {
|
||||||
|
return dateCreated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDateCreated(Date dateCreated) {
|
||||||
|
this.dateCreated = dateCreated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVersion(String version) {
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(byte[] content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileInfo() {
|
||||||
|
return "File Name: " + this.getName() + "\n" + "Extension: " + this.getExtension() + "\n" + "Date Created: " + this.getDateCreated() + "\n" + "Version: " + this.getVersion() + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object read() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.baeldung.polymorphism;
|
||||||
|
|
||||||
|
public class ImageFile extends GenericFile {
|
||||||
|
private int height;
|
||||||
|
private int width;
|
||||||
|
|
||||||
|
public ImageFile(String name, int height, int width, byte[] content, String version) {
|
||||||
|
this.setHeight(height);
|
||||||
|
this.setWidth(width);
|
||||||
|
this.setContent(content);
|
||||||
|
this.setName(name);
|
||||||
|
this.setVersion(version);
|
||||||
|
this.setExtension(".jpg");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeight(int height) {
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWidth(int width) {
|
||||||
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileInfo() {
|
||||||
|
return super.getFileInfo() + "Height: " + this.getHeight() + "\n" + "Width: " + this.getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String read() {
|
||||||
|
return this.getContent()
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.baeldung.polymorphism;
|
||||||
|
|
||||||
|
public class TextFile extends GenericFile {
|
||||||
|
private int wordCount;
|
||||||
|
|
||||||
|
public TextFile(String name, String content, String version) {
|
||||||
|
String[] words = content.split(" ");
|
||||||
|
this.setWordCount(words.length > 0 ? words.length : 1);
|
||||||
|
this.setContent(content.getBytes());
|
||||||
|
this.setName(name);
|
||||||
|
this.setVersion(version);
|
||||||
|
this.setExtension(".txt");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWordCount() {
|
||||||
|
return wordCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWordCount(int wordCount) {
|
||||||
|
this.wordCount = wordCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileInfo() {
|
||||||
|
return super.getFileInfo() + "Word Count: " + wordCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String read() {
|
||||||
|
return this.getContent()
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String read(int limit) {
|
||||||
|
return this.getContent()
|
||||||
|
.toString()
|
||||||
|
.substring(0, limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String read(int start, int stop) {
|
||||||
|
return this.getContent()
|
||||||
|
.toString()
|
||||||
|
.substring(start, stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,10 +2,14 @@ package com.baeldung.nestedclass;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class AnonymousInnerTest {
|
abstract class SimpleAbstractClass {
|
||||||
|
abstract void run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AnonymousInner {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenRunAnonymousClass_thenCorrect() {
|
public void run() {
|
||||||
SimpleAbstractClass simpleAbstractClass = new SimpleAbstractClass() {
|
SimpleAbstractClass simpleAbstractClass = new SimpleAbstractClass() {
|
||||||
void run() {
|
void run() {
|
||||||
System.out.println("Running Anonymous Class...");
|
System.out.println("Running Anonymous Class...");
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.baeldung.nestedclass;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class Enclosing {
|
||||||
|
|
||||||
|
private static int x = 1;
|
||||||
|
|
||||||
|
public static class StaticNested {
|
||||||
|
|
||||||
|
private void run() {
|
||||||
|
System.out.println("x = " + x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
Enclosing.StaticNested nested = new Enclosing.StaticNested();
|
||||||
|
nested.run();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +0,0 @@
|
||||||
package com.baeldung.nestedclass;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class InnerClassTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void givenInnerClassWhenInstantiating_thenCorrect() {
|
|
||||||
Outer outer = new Outer();
|
|
||||||
Outer.Inner inner = outer.new Inner();
|
|
||||||
inner.test();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
package com.baeldung.nestedclass;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class LocalClassTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void whenTestingLocalClass_thenCorrect() {
|
|
||||||
NewEnclosing newEnclosing = new NewEnclosing();
|
|
||||||
newEnclosing.run();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
package com.baeldung.nestedclass;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class NestedClassTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void whenInstantiatingStaticNestedClass_thenCorrect() {
|
|
||||||
Enclosing.Nested nested = new Enclosing.Nested();
|
|
||||||
nested.test();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +1,11 @@
|
||||||
package com.baeldung.nestedclass;
|
package com.baeldung.nestedclass;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
public class NewEnclosing {
|
public class NewEnclosing {
|
||||||
|
|
||||||
void run() {
|
private void run() {
|
||||||
class Local {
|
class Local {
|
||||||
|
|
||||||
void run() {
|
void run() {
|
||||||
System.out.println("Welcome to Baeldung!");
|
System.out.println("Welcome to Baeldung!");
|
||||||
}
|
}
|
||||||
|
@ -12,4 +13,10 @@ public class NewEnclosing {
|
||||||
Local local = new Local();
|
Local local = new Local();
|
||||||
local.run();
|
local.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
NewEnclosing newEnclosing = new NewEnclosing();
|
||||||
|
newEnclosing.run();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.baeldung.nestedclass;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class NewOuter {
|
||||||
|
|
||||||
|
int a = 1;
|
||||||
|
static int b = 2;
|
||||||
|
|
||||||
|
public class InnerClass {
|
||||||
|
int a = 3;
|
||||||
|
static final int b = 4;
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
System.out.println("a = " + a);
|
||||||
|
System.out.println("b = " + b);
|
||||||
|
System.out.println("NewOuterTest.this.a = " + NewOuter.this.a);
|
||||||
|
System.out.println("NewOuterTest.b = " + NewOuter.b);
|
||||||
|
System.out.println("NewOuterTest.this.b = " + NewOuter.this.b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
NewOuter outer = new NewOuter();
|
||||||
|
NewOuter.InnerClass inner = outer.new InnerClass();
|
||||||
|
inner.run();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,32 +0,0 @@
|
||||||
package com.baeldung.nestedclass;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class NewOuterTest {
|
|
||||||
|
|
||||||
int a = 1;
|
|
||||||
static int b = 2;
|
|
||||||
|
|
||||||
public class InnerClass {
|
|
||||||
int a = 3;
|
|
||||||
static final int b = 4;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void whenShadowing_thenCorrect() {
|
|
||||||
assertEquals(3, a);
|
|
||||||
assertEquals(4, b);
|
|
||||||
assertEquals(1, NewOuterTest.this.a);
|
|
||||||
assertEquals(2, NewOuterTest.b);
|
|
||||||
assertEquals(2, NewOuterTest.this.b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void shadowingTest() {
|
|
||||||
NewOuterTest outer = new NewOuterTest();
|
|
||||||
NewOuterTest.InnerClass inner = outer.new InnerClass();
|
|
||||||
inner.whenShadowing_thenCorrect();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.baeldung.nestedclass;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class Outer {
|
||||||
|
|
||||||
|
public class Inner {
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
System.out.println("Calling test...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
Outer outer = new Outer();
|
||||||
|
Outer.Inner inner = outer.new Inner();
|
||||||
|
inner.run();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.baeldung.polymorphism;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class PolymorphismUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenImageFile_whenFileCreated_shouldSucceed() {
|
||||||
|
ImageFile imageFile = FileManager.createImageFile("SampleImageFile", 200, 100, new BufferedImage(100, 200, BufferedImage.TYPE_INT_RGB).toString()
|
||||||
|
.getBytes(), "v1.0.0");
|
||||||
|
assertEquals(200, imageFile.getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Downcasting then Upcasting
|
||||||
|
@Test
|
||||||
|
public void givenTextFile_whenTextFileCreatedAndAssignedToGenericFileAndCastBackToTextFileOnGetWordCount_shouldSucceed() {
|
||||||
|
GenericFile textFile = FileManager.createTextFile("SampleTextFile", "This is a sample text content", "v1.0.0");
|
||||||
|
TextFile textFile2 = (TextFile) textFile;
|
||||||
|
assertEquals(6, textFile2.getWordCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Downcasting
|
||||||
|
@Test(expected = ClassCastException.class)
|
||||||
|
public void givenGenericFile_whenCastToTextFileAndInvokeGetWordCount_shouldFail() {
|
||||||
|
GenericFile genericFile = new GenericFile();
|
||||||
|
TextFile textFile = (TextFile) genericFile;
|
||||||
|
System.out.println(textFile.getWordCount());
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
1
pom.xml
1
pom.xml
|
@ -141,6 +141,7 @@
|
||||||
<module>spark-java</module>
|
<module>spark-java</module>
|
||||||
<!-- <module>spring-5</module>-->
|
<!-- <module>spring-5</module>-->
|
||||||
<module>spring-5-mvc</module>
|
<module>spring-5-mvc</module>
|
||||||
|
<module>spring-acl</module>
|
||||||
<module>spring-activiti</module>
|
<module>spring-activiti</module>
|
||||||
<module>spring-akka</module>
|
<module>spring-akka</module>
|
||||||
<module>spring-amqp</module>
|
<module>spring-amqp</module>
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>spring-acl</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
|
||||||
|
<name>spring-acl</name>
|
||||||
|
<description>Spring ACL</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<artifactId>parent-boot-5</artifactId>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../parent-boot-5</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-acl</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-config</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-context-support</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.sf.ehcache</groupId>
|
||||||
|
<artifactId>ehcache-core</artifactId>
|
||||||
|
<version>2.6.11</version>
|
||||||
|
<type>jar</type>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,80 @@
|
||||||
|
package org.baeldung.acl.config;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.cache.ehcache.EhCacheFactoryBean;
|
||||||
|
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||||
|
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||||
|
import org.springframework.security.acls.AclPermissionCacheOptimizer;
|
||||||
|
import org.springframework.security.acls.AclPermissionEvaluator;
|
||||||
|
import org.springframework.security.acls.domain.AclAuthorizationStrategy;
|
||||||
|
import org.springframework.security.acls.domain.AclAuthorizationStrategyImpl;
|
||||||
|
import org.springframework.security.acls.domain.ConsoleAuditLogger;
|
||||||
|
import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy;
|
||||||
|
import org.springframework.security.acls.domain.EhCacheBasedAclCache;
|
||||||
|
import org.springframework.security.acls.jdbc.BasicLookupStrategy;
|
||||||
|
import org.springframework.security.acls.jdbc.JdbcMutableAclService;
|
||||||
|
import org.springframework.security.acls.jdbc.LookupStrategy;
|
||||||
|
import org.springframework.security.acls.model.PermissionGrantingStrategy;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableAutoConfiguration
|
||||||
|
public class ACLContext {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
DataSource dataSource;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public EhCacheBasedAclCache aclCache() {
|
||||||
|
return new EhCacheBasedAclCache(aclEhCacheFactoryBean().getObject(), permissionGrantingStrategy(), aclAuthorizationStrategy());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public EhCacheFactoryBean aclEhCacheFactoryBean() {
|
||||||
|
EhCacheFactoryBean ehCacheFactoryBean = new EhCacheFactoryBean();
|
||||||
|
ehCacheFactoryBean.setCacheManager(aclCacheManager().getObject());
|
||||||
|
ehCacheFactoryBean.setCacheName("aclCache");
|
||||||
|
return ehCacheFactoryBean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public EhCacheManagerFactoryBean aclCacheManager() {
|
||||||
|
return new EhCacheManagerFactoryBean();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PermissionGrantingStrategy permissionGrantingStrategy() {
|
||||||
|
return new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AclAuthorizationStrategy aclAuthorizationStrategy() {
|
||||||
|
return new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_ADMIN"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public MethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler() {
|
||||||
|
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
|
||||||
|
AclPermissionEvaluator permissionEvaluator = new AclPermissionEvaluator(aclService());
|
||||||
|
expressionHandler.setPermissionEvaluator(permissionEvaluator);
|
||||||
|
expressionHandler.setPermissionCacheOptimizer(new AclPermissionCacheOptimizer(aclService()));
|
||||||
|
return expressionHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public LookupStrategy lookupStrategy() {
|
||||||
|
return new BasicLookupStrategy(dataSource, aclCache(), aclAuthorizationStrategy(), new ConsoleAuditLogger());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JdbcMutableAclService aclService() {
|
||||||
|
return new JdbcMutableAclService(dataSource, lookupStrategy(), aclCache());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package org.baeldung.acl.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||||
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
|
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||||
|
public class AclMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
MethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MethodSecurityExpressionHandler createExpressionHandler() {
|
||||||
|
return defaultMethodSecurityExpressionHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package org.baeldung.acl.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.PropertySource;
|
||||||
|
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||||
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableTransactionManagement
|
||||||
|
@EnableJpaRepositories(basePackages = "org.baeldung.acl.persistence.dao")
|
||||||
|
@PropertySource("classpath:org.baeldung.acl.datasource.properties")
|
||||||
|
@EntityScan(basePackages={ "org.baeldung.acl.persistence.entity" })
|
||||||
|
public class JPAPersistenceConfig {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.baeldung.acl.persistence.dao;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.baeldung.acl.persistence.entity.NoticeMessage;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
import org.springframework.security.access.prepost.PostAuthorize;
|
||||||
|
import org.springframework.security.access.prepost.PostFilter;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
|
||||||
|
public interface NoticeMessageRepository extends JpaRepository<NoticeMessage, Long>{
|
||||||
|
|
||||||
|
@PostFilter("hasPermission(filterObject, 'READ')")
|
||||||
|
List<NoticeMessage> findAll();
|
||||||
|
|
||||||
|
@PostAuthorize("hasPermission(returnObject, 'READ')")
|
||||||
|
NoticeMessage findById(Integer id);
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@PreAuthorize("hasPermission(#noticeMessage, 'WRITE')")
|
||||||
|
NoticeMessage save(@Param("noticeMessage")NoticeMessage noticeMessage);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.baeldung.acl.persistence.entity;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="system_message")
|
||||||
|
public class NoticeMessage {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column
|
||||||
|
private Integer id;
|
||||||
|
@Column
|
||||||
|
private String content;
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
INSERT INTO system_message(id,content) VALUES (1,'First Level Message');
|
||||||
|
INSERT INTO system_message(id,content) VALUES (2,'Second Level Message');
|
||||||
|
INSERT INTO system_message(id,content) VALUES (3,'Third Level Message');
|
||||||
|
|
||||||
|
INSERT INTO acl_class (id, class) VALUES
|
||||||
|
(1, 'org.baeldung.acl.persistence.entity.NoticeMessage');
|
||||||
|
|
||||||
|
INSERT INTO acl_sid (id, principal, sid) VALUES
|
||||||
|
(1, 1, 'manager'),
|
||||||
|
(2, 1, 'hr'),
|
||||||
|
(3, 1, 'admin'),
|
||||||
|
(4, 0, 'ROLE_EDITOR');
|
||||||
|
|
||||||
|
INSERT INTO acl_object_identity (id, object_id_class, object_id_identity, parent_object, owner_sid, entries_inheriting) VALUES
|
||||||
|
(1, 1, 1, NULL, 3, 0),
|
||||||
|
(2, 1, 2, NULL, 3, 0),
|
||||||
|
(3, 1, 3, NULL, 3, 0)
|
||||||
|
;
|
||||||
|
|
||||||
|
INSERT INTO acl_entry (id, acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure) VALUES
|
||||||
|
(1, 1, 1, 1, 1, 1, 1, 1),
|
||||||
|
(2, 1, 2, 1, 2, 1, 1, 1),
|
||||||
|
(3, 1, 3, 4, 1, 1, 1, 1),
|
||||||
|
(4, 2, 1, 2, 1, 1, 1, 1),
|
||||||
|
(5, 2, 2, 4, 1, 1, 1, 1),
|
||||||
|
(6, 3, 1, 4, 1, 1, 1, 1),
|
||||||
|
(7, 3, 2, 4, 2, 1, 1, 1)
|
||||||
|
;
|
|
@ -0,0 +1,58 @@
|
||||||
|
create table system_message (id integer not null, content varchar(255), primary key (id));
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS acl_sid (
|
||||||
|
id bigint(20) NOT NULL AUTO_INCREMENT,
|
||||||
|
principal tinyint(1) NOT NULL,
|
||||||
|
sid varchar(100) NOT NULL,
|
||||||
|
PRIMARY KEY (id),
|
||||||
|
UNIQUE KEY unique_uk_1 (sid,principal)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS acl_class (
|
||||||
|
id bigint(20) NOT NULL AUTO_INCREMENT,
|
||||||
|
class varchar(255) NOT NULL,
|
||||||
|
PRIMARY KEY (id),
|
||||||
|
UNIQUE KEY unique_uk_2 (class)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS acl_entry (
|
||||||
|
id bigint(20) NOT NULL AUTO_INCREMENT,
|
||||||
|
acl_object_identity bigint(20) NOT NULL,
|
||||||
|
ace_order int(11) NOT NULL,
|
||||||
|
sid bigint(20) NOT NULL,
|
||||||
|
mask int(11) NOT NULL,
|
||||||
|
granting tinyint(1) NOT NULL,
|
||||||
|
audit_success tinyint(1) NOT NULL,
|
||||||
|
audit_failure tinyint(1) NOT NULL,
|
||||||
|
PRIMARY KEY (id),
|
||||||
|
UNIQUE KEY unique_uk_4 (acl_object_identity,ace_order)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS acl_object_identity (
|
||||||
|
id bigint(20) NOT NULL AUTO_INCREMENT,
|
||||||
|
object_id_class bigint(20) NOT NULL,
|
||||||
|
object_id_identity bigint(20) NOT NULL,
|
||||||
|
parent_object bigint(20) DEFAULT NULL,
|
||||||
|
owner_sid bigint(20) DEFAULT NULL,
|
||||||
|
entries_inheriting tinyint(1) NOT NULL,
|
||||||
|
PRIMARY KEY (id),
|
||||||
|
UNIQUE KEY unique_uk_3 (object_id_class,object_id_identity)
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE acl_entry
|
||||||
|
ADD FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity(id);
|
||||||
|
|
||||||
|
ALTER TABLE acl_entry
|
||||||
|
ADD FOREIGN KEY (sid) REFERENCES acl_sid(id);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints for table acl_object_identity
|
||||||
|
--
|
||||||
|
ALTER TABLE acl_object_identity
|
||||||
|
ADD FOREIGN KEY (parent_object) REFERENCES acl_object_identity (id);
|
||||||
|
|
||||||
|
ALTER TABLE acl_object_identity
|
||||||
|
ADD FOREIGN KEY (object_id_class) REFERENCES acl_class (id);
|
||||||
|
|
||||||
|
ALTER TABLE acl_object_identity
|
||||||
|
ADD FOREIGN KEY (owner_sid) REFERENCES acl_sid (id);
|
|
@ -0,0 +1,12 @@
|
||||||
|
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
|
||||||
|
spring.datasource.username=sa
|
||||||
|
spring.datasource.password=
|
||||||
|
spring.datasource.driverClassName=org.h2.Driver
|
||||||
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
|
||||||
|
|
||||||
|
spring.h2.console.path=/myconsole
|
||||||
|
spring.h2.console.enabled=true
|
||||||
|
spring.datasource.initialize=true
|
||||||
|
spring.datasource.schema=classpath:acl-schema.sql
|
||||||
|
spring.datasource.data=classpath:acl-data.sql
|
|
@ -0,0 +1,119 @@
|
||||||
|
package org.baeldung.acl;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.baeldung.acl.persistence.dao.NoticeMessageRepository;
|
||||||
|
import org.baeldung.acl.persistence.entity.NoticeMessage;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
import org.springframework.security.test.context.support.WithMockUser;
|
||||||
|
import org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.TestExecutionListeners;
|
||||||
|
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
|
||||||
|
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
|
||||||
|
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
|
||||||
|
import org.springframework.test.context.web.ServletTestExecutionListener;
|
||||||
|
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration
|
||||||
|
@TestExecutionListeners(listeners={ServletTestExecutionListener.class,
|
||||||
|
DependencyInjectionTestExecutionListener.class,
|
||||||
|
DirtiesContextTestExecutionListener.class,
|
||||||
|
TransactionalTestExecutionListener.class,
|
||||||
|
WithSecurityContextTestExecutionListener.class})
|
||||||
|
public class SpringAclTest extends AbstractJUnit4SpringContextTests{
|
||||||
|
|
||||||
|
private static Integer FIRST_MESSAGE_ID = 1;
|
||||||
|
private static Integer SECOND_MESSAGE_ID = 2;
|
||||||
|
private static Integer THIRD_MESSAGE_ID = 3;
|
||||||
|
private static String EDITTED_CONTENT = "EDITED";
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ComponentScan("org.baeldung.acl.*")
|
||||||
|
public static class SpringConfig {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
NoticeMessageRepository repo;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username="manager")
|
||||||
|
public void givenUsernameManager_whenFindAllMessage_thenReturnFirstMessage(){
|
||||||
|
List<NoticeMessage> details = repo.findAll();
|
||||||
|
assertNotNull(details);
|
||||||
|
assertEquals(1,details.size());
|
||||||
|
assertEquals(FIRST_MESSAGE_ID,details.get(0).getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username="manager")
|
||||||
|
public void givenUsernameManager_whenFindFirstMessageByIdAndUpdateFirstMessageContent_thenOK(){
|
||||||
|
NoticeMessage firstMessage = repo.findById(FIRST_MESSAGE_ID);
|
||||||
|
assertNotNull(firstMessage);
|
||||||
|
assertEquals(FIRST_MESSAGE_ID,firstMessage.getId());
|
||||||
|
|
||||||
|
firstMessage.setContent(EDITTED_CONTENT);
|
||||||
|
repo.save(firstMessage);
|
||||||
|
|
||||||
|
NoticeMessage editedFirstMessage = repo.findById(FIRST_MESSAGE_ID);
|
||||||
|
assertNotNull(editedFirstMessage);
|
||||||
|
assertEquals(FIRST_MESSAGE_ID,editedFirstMessage.getId());
|
||||||
|
assertEquals(EDITTED_CONTENT,editedFirstMessage.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username="hr")
|
||||||
|
public void givenUsernameHr_whenFindMessageById2_thenOK(){
|
||||||
|
NoticeMessage secondMessage = repo.findById(SECOND_MESSAGE_ID);
|
||||||
|
assertNotNull(secondMessage);
|
||||||
|
assertEquals(SECOND_MESSAGE_ID,secondMessage.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=AccessDeniedException.class)
|
||||||
|
@WithMockUser(username="hr")
|
||||||
|
public void givenUsernameHr_whenUpdateMessageWithId2_thenFail(){
|
||||||
|
NoticeMessage secondMessage = new NoticeMessage();
|
||||||
|
secondMessage.setId(SECOND_MESSAGE_ID);
|
||||||
|
secondMessage.setContent(EDITTED_CONTENT);
|
||||||
|
repo.save(secondMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(roles={"EDITOR"})
|
||||||
|
public void givenRoleEditor_whenFindAllMessage_thenReturnThreeMessage(){
|
||||||
|
List<NoticeMessage> details = repo.findAll();
|
||||||
|
assertNotNull(details);
|
||||||
|
assertEquals(3,details.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(roles={"EDITOR"})
|
||||||
|
public void givenRoleEditor_whenUpdateThirdMessage_thenOK(){
|
||||||
|
NoticeMessage thirdMessage = new NoticeMessage();
|
||||||
|
thirdMessage.setId(THIRD_MESSAGE_ID);
|
||||||
|
thirdMessage.setContent(EDITTED_CONTENT);
|
||||||
|
repo.save(thirdMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=AccessDeniedException.class)
|
||||||
|
@WithMockUser(roles={"EDITOR"})
|
||||||
|
public void givenRoleEditor_whenFindFirstMessageByIdAndUpdateFirstMessageContent_thenFail(){
|
||||||
|
NoticeMessage firstMessage = repo.findById(FIRST_MESSAGE_ID);
|
||||||
|
assertNotNull(firstMessage);
|
||||||
|
assertEquals(FIRST_MESSAGE_ID,firstMessage.getId());
|
||||||
|
firstMessage.setContent(EDITTED_CONTENT);
|
||||||
|
repo.save(firstMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,12 +5,13 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.web.support.SpringBootServletInitializer;
|
import org.springframework.boot.web.support.SpringBootServletInitializer;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.FilterType;
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
@ComponentScan(excludeFilters = { @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.voter.*"), @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.multipleauthproviders.*"),
|
@ComponentScan({ "org.baeldung.config", "org.baeldung.persistence", "org.baeldung.security", "org.baeldung.web" })
|
||||||
@ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.multiplelogin.*"), @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.multipleentrypoints.*") })
|
// @ComponentScan(excludeFilters = { @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.voter.*"), @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.multipleauthproviders.*"),
|
||||||
|
// @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.multiplelogin.*"), @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.multipleentrypoints.*"),
|
||||||
|
// @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.rolesauthorities.*"), @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.acl.*") })
|
||||||
public class Application extends SpringBootServletInitializer {
|
public class Application extends SpringBootServletInitializer {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(Application.class, args);
|
SpringApplication.run(Application.class, args);
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>mocks</artifactId>
|
<artifactId>mocks</artifactId>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
Loading…
Reference in New Issue