-
Notifications
You must be signed in to change notification settings - Fork 54.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from eugenp/master
Update local repo
- Loading branch information
Showing
491 changed files
with
22,700 additions
and
734 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
...us-6/src/main/java/com/baeldung/algorithms/topkelements/BruteForceTopKElementsFinder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.baeldung.algorithms.topkelements; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class BruteForceTopKElementsFinder implements TopKElementsFinder<Integer> { | ||
|
||
public List<Integer> findTopK(List<Integer> input, int k) { | ||
List<Integer> array = new ArrayList<>(input); | ||
List<Integer> topKList = new ArrayList<>(); | ||
|
||
for (int i = 0; i < k; i++) { | ||
int maxIndex = 0; | ||
|
||
for (int j = 1; j < array.size(); j++) { | ||
if (array.get(j) > array.get(maxIndex)) { | ||
maxIndex = j; | ||
} | ||
} | ||
|
||
topKList.add(array.remove(maxIndex)); | ||
} | ||
|
||
return topKList; | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
...neous-6/src/main/java/com/baeldung/algorithms/topkelements/MaxHeapTopKElementsFinder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.baeldung.algorithms.topkelements; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.PriorityQueue; | ||
|
||
public class MaxHeapTopKElementsFinder implements TopKElementsFinder<Integer> { | ||
|
||
public List<Integer> findTopK(List<Integer> input, int k) { | ||
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(); | ||
|
||
input.forEach(number -> { | ||
maxHeap.add(number); | ||
|
||
if (maxHeap.size() > k) { | ||
maxHeap.poll(); | ||
} | ||
}); | ||
|
||
List<Integer> topKList = new ArrayList<>(maxHeap); | ||
Collections.reverse(topKList); | ||
|
||
return topKList; | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
...iscellaneous-6/src/main/java/com/baeldung/algorithms/topkelements/TopKElementsFinder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.baeldung.algorithms.topkelements; | ||
|
||
import java.util.List; | ||
|
||
public interface TopKElementsFinder<T extends Comparable<T>> { | ||
List<T> findTopK(List<T> input, int k); | ||
} |
17 changes: 17 additions & 0 deletions
17
...neous-6/src/main/java/com/baeldung/algorithms/topkelements/TreeSetTopKElementsFinder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.baeldung.algorithms.topkelements; | ||
|
||
import java.util.Comparator; | ||
import java.util.List; | ||
import java.util.Set; | ||
import java.util.TreeSet; | ||
import java.util.stream.Collectors; | ||
|
||
public class TreeSetTopKElementsFinder implements TopKElementsFinder<Integer> { | ||
|
||
public List<Integer> findTopK(List<Integer> input, int k) { | ||
Set<Integer> sortedSet = new TreeSet<>(Comparator.reverseOrder()); | ||
sortedSet.addAll(input); | ||
|
||
return sortedSet.stream().limit(k).collect(Collectors.toList()); | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
...eous-6/src/test/java/com/baeldung/algorithms/topkelements/TopKElementsFinderUnitTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package com.baeldung.algorithms.topkelements; | ||
|
||
import org.junit.Test; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
import static org.assertj.core.api.Java6Assertions.assertThat; | ||
|
||
public class TopKElementsFinderUnitTest { | ||
private final TopKElementsFinder<Integer> bruteForceFinder = new BruteForceTopKElementsFinder(); | ||
private final TopKElementsFinder<Integer> maxHeapFinder = new MaxHeapTopKElementsFinder(); | ||
private final TopKElementsFinder<Integer> treeSetFinder = new TreeSetTopKElementsFinder(); | ||
|
||
private final int k = 4; | ||
private final List<Integer> distinctIntegers = Arrays.asList(1, 2, 3, 9, 7, 6, 12); | ||
private final List<Integer> distinctIntegersTopK = Arrays.asList(9, 7, 6, 12); | ||
private final List<Integer> nonDistinctIntegers = Arrays.asList(1, 2, 3, 3, 9, 9, 7, 6, 12); | ||
private final List<Integer> nonDistinctIntegersTopK = Arrays.asList(9, 9, 7, 12); | ||
|
||
|
||
@Test | ||
public void givenArrayDistinctIntegers_whenBruteForceFindTopK_thenReturnKLargest() { | ||
assertThat(bruteForceFinder.findTopK(distinctIntegers, k)).containsOnlyElementsOf(distinctIntegersTopK); | ||
} | ||
|
||
@Test | ||
public void givenArrayDistinctIntegers_whenMaxHeapFindTopK_thenReturnKLargest() { | ||
assertThat(maxHeapFinder.findTopK(distinctIntegers, k)).containsOnlyElementsOf(distinctIntegersTopK); | ||
} | ||
|
||
@Test | ||
public void givenArrayDistinctIntegers_whenTreeSetFindTopK_thenReturnKLargest() { | ||
assertThat(treeSetFinder.findTopK(distinctIntegers, k)).containsOnlyElementsOf(distinctIntegersTopK); | ||
} | ||
|
||
@Test | ||
public void givenArrayNonDistinctIntegers_whenBruteForceFindTopK_thenReturnKLargest() { | ||
assertThat(bruteForceFinder.findTopK(nonDistinctIntegers, k)).containsOnlyElementsOf(nonDistinctIntegersTopK); | ||
} | ||
|
||
@Test | ||
public void givenArrayNonDistinctIntegers_whenMaxHeapFindTopK_thenReturnKLargest() { | ||
assertThat(maxHeapFinder.findTopK(nonDistinctIntegers, k)).containsOnlyElementsOf(nonDistinctIntegersTopK); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 96 additions & 0 deletions
96
apache-shiro/src/main/java/com/baeldung/comparison/shiro/CustomRealm.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package com.baeldung.comparison.shiro; | ||
|
||
import java.sql.Connection; | ||
import java.sql.SQLException; | ||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.Map; | ||
import java.util.Set; | ||
|
||
import org.apache.shiro.authc.AuthenticationException; | ||
import org.apache.shiro.authc.AuthenticationInfo; | ||
import org.apache.shiro.authc.AuthenticationToken; | ||
import org.apache.shiro.authc.SimpleAuthenticationInfo; | ||
import org.apache.shiro.authc.UnknownAccountException; | ||
import org.apache.shiro.authc.UsernamePasswordToken; | ||
import org.apache.shiro.authz.AuthorizationInfo; | ||
import org.apache.shiro.authz.SimpleAuthorizationInfo; | ||
import org.apache.shiro.realm.jdbc.JdbcRealm; | ||
import org.apache.shiro.subject.PrincipalCollection; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public class CustomRealm extends JdbcRealm { | ||
|
||
private Logger logger = LoggerFactory.getLogger(CustomRealm.class); | ||
|
||
private Map<String, String> credentials = new HashMap<>(); | ||
private Map<String, Set<String>> roles = new HashMap<>(); | ||
private Map<String, Set<String>> permissions = new HashMap<>(); | ||
|
||
{ | ||
credentials.put("Tom", "password"); | ||
credentials.put("Jerry", "password"); | ||
|
||
roles.put("Jerry", new HashSet<>(Arrays.asList("ADMIN"))); | ||
roles.put("Tom", new HashSet<>(Arrays.asList("USER"))); | ||
|
||
permissions.put("ADMIN", new HashSet<>(Arrays.asList("READ", "WRITE"))); | ||
permissions.put("USER", new HashSet<>(Arrays.asList("READ"))); | ||
} | ||
|
||
@Override | ||
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { | ||
|
||
UsernamePasswordToken userToken = (UsernamePasswordToken) token; | ||
|
||
if (userToken.getUsername() == null || userToken.getUsername() | ||
.isEmpty() || !credentials.containsKey(userToken.getUsername())) { | ||
throw new UnknownAccountException("User doesn't exist"); | ||
} | ||
|
||
return new SimpleAuthenticationInfo(userToken.getUsername(), credentials.get(userToken.getUsername()), getName()); | ||
} | ||
|
||
@Override | ||
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { | ||
Set<String> roles = new HashSet<>(); | ||
Set<String> permissions = new HashSet<>(); | ||
|
||
for (Object user : principals) { | ||
try { | ||
roles.addAll(getRoleNamesForUser(null, (String) user)); | ||
permissions.addAll(getPermissions(null, null, roles)); | ||
} catch (SQLException e) { | ||
logger.error(e.getMessage()); | ||
} | ||
} | ||
SimpleAuthorizationInfo authInfo = new SimpleAuthorizationInfo(roles); | ||
authInfo.setStringPermissions(permissions); | ||
return authInfo; | ||
} | ||
|
||
@Override | ||
protected Set<String> getRoleNamesForUser(Connection conn, String username) throws SQLException { | ||
if (!roles.containsKey(username)) { | ||
throw new SQLException("User doesn't exist"); | ||
} | ||
return roles.get(username); | ||
} | ||
|
||
@Override | ||
protected Set<String> getPermissions(Connection conn, String username, Collection<String> roles) throws SQLException { | ||
Set<String> userPermissions = new HashSet<>(); | ||
|
||
for (String role : roles) { | ||
if (!permissions.containsKey(role)) { | ||
throw new SQLException("Role doesn't exist"); | ||
} | ||
userPermissions.addAll(permissions.get(role)); | ||
} | ||
return userPermissions; | ||
} | ||
|
||
} |
33 changes: 33 additions & 0 deletions
33
apache-shiro/src/main/java/com/baeldung/comparison/shiro/ShiroApplication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.baeldung.comparison.shiro; | ||
|
||
import org.apache.shiro.realm.Realm; | ||
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition; | ||
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition; | ||
import org.springframework.boot.SpringApplication; | ||
import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; | ||
import org.springframework.context.annotation.Bean; | ||
|
||
@SpringBootApplication(exclude = SecurityAutoConfiguration.class) | ||
public class ShiroApplication { | ||
|
||
public static void main(String... args) { | ||
SpringApplication.run(ShiroApplication.class, args); | ||
} | ||
|
||
@Bean | ||
public Realm customRealm() { | ||
return new CustomRealm(); | ||
} | ||
|
||
@Bean | ||
public ShiroFilterChainDefinition shiroFilterChainDefinition() { | ||
DefaultShiroFilterChainDefinition filter = new DefaultShiroFilterChainDefinition(); | ||
|
||
filter.addPathDefinition("/home", "authc"); | ||
filter.addPathDefinition("/**", "anon"); | ||
|
||
return filter; | ||
} | ||
|
||
} |
99 changes: 99 additions & 0 deletions
99
apache-shiro/src/main/java/com/baeldung/comparison/shiro/controllers/ShiroController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package com.baeldung.comparison.shiro.controllers; | ||
|
||
import javax.servlet.http.HttpServletRequest; | ||
|
||
import org.apache.shiro.SecurityUtils; | ||
import org.apache.shiro.authc.AuthenticationException; | ||
import org.apache.shiro.authc.UsernamePasswordToken; | ||
import org.apache.shiro.subject.Subject; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.stereotype.Controller; | ||
import org.springframework.ui.Model; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.servlet.mvc.support.RedirectAttributes; | ||
|
||
import com.baeldung.comparison.shiro.models.UserCredentials; | ||
|
||
@Controller | ||
public class ShiroController { | ||
|
||
private Logger logger = LoggerFactory.getLogger(ShiroController.class); | ||
|
||
@GetMapping("/") | ||
public String getIndex() { | ||
return "comparison/index"; | ||
} | ||
|
||
@GetMapping("/login") | ||
public String showLoginPage() { | ||
return "comparison/login"; | ||
} | ||
|
||
@PostMapping("/login") | ||
public String doLogin(HttpServletRequest req, UserCredentials credentials, RedirectAttributes attr) { | ||
|
||
Subject subject = SecurityUtils.getSubject(); | ||
|
||
if (!subject.isAuthenticated()) { | ||
UsernamePasswordToken token = new UsernamePasswordToken(credentials.getUsername(), credentials.getPassword()); | ||
try { | ||
subject.login(token); | ||
} catch (AuthenticationException ae) { | ||
logger.error(ae.getMessage()); | ||
attr.addFlashAttribute("error", "Invalid Credentials"); | ||
return "redirect:/login"; | ||
} | ||
} | ||
return "redirect:/home"; | ||
} | ||
|
||
@GetMapping("/home") | ||
public String getMeHome(Model model) { | ||
|
||
addUserAttributes(model); | ||
|
||
return "comparison/home"; | ||
} | ||
|
||
@GetMapping("/admin") | ||
public String adminOnly(Model model) { | ||
addUserAttributes(model); | ||
|
||
Subject currentUser = SecurityUtils.getSubject(); | ||
if (currentUser.hasRole("ADMIN")) { | ||
model.addAttribute("adminContent", "only admin can view this"); | ||
} | ||
return "comparison/home"; | ||
} | ||
|
||
@PostMapping("/logout") | ||
public String logout() { | ||
Subject subject = SecurityUtils.getSubject(); | ||
subject.logout(); | ||
return "redirect:/"; | ||
} | ||
|
||
private void addUserAttributes(Model model) { | ||
Subject currentUser = SecurityUtils.getSubject(); | ||
String permission = ""; | ||
|
||
if (currentUser.hasRole("ADMIN")) { | ||
model.addAttribute("role", "ADMIN"); | ||
} else if (currentUser.hasRole("USER")) { | ||
model.addAttribute("role", "USER"); | ||
} | ||
|
||
if (currentUser.isPermitted("READ")) { | ||
permission = permission + " READ"; | ||
} | ||
|
||
if (currentUser.isPermitted("WRITE")) { | ||
permission = permission + " WRITE"; | ||
} | ||
model.addAttribute("username", currentUser.getPrincipal()); | ||
model.addAttribute("permission", permission); | ||
} | ||
|
||
} |
Oops, something went wrong.