This commit is contained in:
DOHA
2017-08-28 13:15:36 +02:00
45 changed files with 1234 additions and 76 deletions
+16 -3
View File
@@ -9,9 +9,9 @@
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<properties>
@@ -21,6 +21,19 @@
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>${apache-shiro-core-version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
@@ -0,0 +1,45 @@
package com.baeldung;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
/**
* Created by smatt on 21/08/2017.
*/
@SpringBootApplication
public class ShiroSpringApplication {
private static final transient Logger log = LoggerFactory.getLogger(ShiroSpringApplication.class);
public static void main(String... args) {
SpringApplication.run(ShiroSpringApplication.class, args);
}
@Bean
public Realm realm() {
return new MyCustomRealm();
}
@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
DefaultShiroFilterChainDefinition filter
= new DefaultShiroFilterChainDefinition();
filter.addPathDefinition("/secure", "authc");
filter.addPathDefinition("/**", "anon");
return filter;
}
}
@@ -0,0 +1,105 @@
package com.baeldung.controllers;
import com.baeldung.models.UserCredentials;
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.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.servlet.http.HttpServletRequest;
@Controller
public class ShiroSpringController {
@GetMapping("/")
public String index() {
return "index";
}
@RequestMapping( value = "/login", method = {RequestMethod.GET, RequestMethod.POST})
public String login(HttpServletRequest req, UserCredentials cred, RedirectAttributes attr) {
if(req.getMethod().equals(RequestMethod.GET.toString())) {
return "login";
}
else {
Subject subject = SecurityUtils.getSubject();
if(!subject.isAuthenticated()) {
UsernamePasswordToken token = new UsernamePasswordToken(
cred.getUsername(), cred.getPassword(), cred.isRememberMe());
try {
subject.login(token);
} catch (AuthenticationException ae) {
ae.printStackTrace();
attr.addFlashAttribute("error", "Invalid Credentials");
return "redirect:/login";
}
}
return "redirect:/secure";
}
}
@GetMapping("/secure")
public String secure(ModelMap modelMap) {
Subject currentUser = SecurityUtils.getSubject();
String role = "", permission = "";
if(currentUser.hasRole("admin")) {
role = role + "You are an Admin";
}
else if(currentUser.hasRole("editor")) {
role = role + "You are an Editor";
}
else if(currentUser.hasRole("author")) {
role = role + "You are an Author";
}
if(currentUser.isPermitted("articles:compose")) {
permission = permission + "You can compose an article, ";
} else {
permission = permission + "You are not permitted to compose an article!, ";
}
if(currentUser.isPermitted("articles:save")) {
permission = permission + "You can save articles, ";
} else {
permission = permission + "\nYou can not save articles, ";
}
if(currentUser.isPermitted("articles:publish")) {
permission = permission + "\nYou can publish articles";
} else {
permission = permission + "\nYou can not publish articles";
}
modelMap.addAttribute("username", currentUser.getPrincipal());
modelMap.addAttribute("permission", permission);
modelMap.addAttribute("role", role);
return "secure";
}
@PostMapping("/logout")
public String logout() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "redirect:/";
}
}
@@ -0,0 +1,40 @@
package com.baeldung.models;
public class UserCredentials {
private String username;
private String password;
private boolean rememberMe = false;
public UserCredentials() {}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isRememberMe() {
return rememberMe;
}
public void setRememberMe(boolean rememberMe) {
this.rememberMe = rememberMe;
}
@Override
public String toString() {
return "username = " + getUsername()
+ "\nrememberMe = " + isRememberMe();
}
}
@@ -0,0 +1,11 @@
server.port=9000
server.servlet-path=/
server.context-path=/
#shiro-spring-boot-config
shiro.loginUrl = /login
shiro.successUrl = /secure
shiro.unauthorizedUrl = /login
#freemarker
spring.freemarker.suffix=.ftl
@@ -0,0 +1,10 @@
<html>
<head>
<title>Index</title>
</head>
<body>
<h1>Welcome Guest!</h1>
<br>
<a href="/login">Login</a>
</body>
</html>
@@ -0,0 +1,27 @@
<html>
<head>
<title>Login</title>
</head>
<body style="margin-left: 30px;">
<h3>Login</h3>
<br>
<form action="/login" method="post">
<#if (error?length > 0)??>
<p style="color:darkred;">${error}</p>
<#else>
</#if>
<label for="username">Username</label>
<br>
<input type="text" name="username">
<br><br>
<label for="password">Password</label>
<br>
<input type="password" name="password">
<br><br>
<input type="checkbox" name="rememberMe"> Remember Me
<br><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
@@ -0,0 +1,15 @@
<html>
<head>
<title>Secure</title>
</head>
<body style="margin-left: 30px;">
<h1>Welcome ${username}!</h1>
<p><strong>Role</strong>: ${role}</p>
<p><strong>Permissions</strong></p>
<p>${permission}</p>
<br>
<form role="form" action="/logout" method="POST">
<input type="Submit" value="Logout" />
</form>
</body>
</html>
@@ -3,11 +3,11 @@ package com.baeldung.concurrent.atomic;
public class SafeCounterWithLock {
private volatile int counter;
public int getValue() {
int getValue() {
return counter;
}
public synchronized void increment() {
synchronized void increment() {
counter++;
}
}
@@ -5,11 +5,11 @@ import java.util.concurrent.atomic.AtomicInteger;
public class SafeCounterWithoutLock {
private final AtomicInteger counter = new AtomicInteger(0);
public int getValue() {
int getValue() {
return counter.get();
}
public void increment() {
void increment() {
while(true) {
int existingValue = getValue();
int newValue = existingValue + 1;
@@ -1,13 +1,13 @@
package com.baeldung.concurrent.atomic;
public class UnsafeCounter {
int counter;
private int counter;
public int getValue() {
int getValue() {
return counter;
}
public void increment() {
void increment() {
counter++;
}
}
@@ -4,14 +4,14 @@ package com.baeldung.threadlocal;
public class Context {
private final String userName;
public Context(String userName) {
Context(String userName) {
this.userName = userName;
}
@Override
public String toString() {
return "Context{" +
"userNameSecret='" + userName + '\'' +
'}';
"userNameSecret='" + userName + '\'' +
'}';
}
}
@@ -5,11 +5,11 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class SharedMapWithUserContext implements Runnable {
public final static Map<Integer, Context> userContextPerUserId = new ConcurrentHashMap<>();
final static Map<Integer, Context> userContextPerUserId = new ConcurrentHashMap<>();
private final Integer userId;
private UserRepository userRepository = new UserRepository();
public SharedMapWithUserContext(Integer userId) {
SharedMapWithUserContext(Integer userId) {
this.userId = userId;
}
@@ -10,7 +10,7 @@ public class ThreadLocalWithUserContext implements Runnable {
private final Integer userId;
private UserRepository userRepository = new UserRepository();
public ThreadLocalWithUserContext(Integer userId) {
ThreadLocalWithUserContext(Integer userId) {
this.userId = userId;
}
@@ -4,7 +4,7 @@ import java.util.UUID;
public class UserRepository {
public String getUserNameForUserId(Integer userId) {
String getUserNameForUserId(Integer userId) {
return UUID.randomUUID().toString();
}
}
@@ -2,19 +2,21 @@ package com.baeldung.threadpool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.stream.Collectors;
public class CountingTask extends RecursiveTask<Integer> {
private final TreeNode node;
public CountingTask(TreeNode node) {
CountingTask(TreeNode node) {
this.node = node;
}
@Override
protected Integer compute() {
return node.value + node.children.stream().map(childNode -> new CountingTask(childNode).fork()).collect(Collectors.summingInt(ForkJoinTask::join));
return node.getValue() + node.getChildren().stream()
.map(childNode -> new CountingTask(childNode).fork())
.mapToInt(ForkJoinTask::join)
.sum();
}
}
@@ -11,10 +11,10 @@ public class Consumer implements Runnable {
private final TransferQueue<String> transferQueue;
private final String name;
private final int numberOfMessagesToConsume;
public final AtomicInteger numberOfConsumedMessages = new AtomicInteger();
final int numberOfMessagesToConsume;
final AtomicInteger numberOfConsumedMessages = new AtomicInteger();
public Consumer(TransferQueue<String> transferQueue, String name, int numberOfMessagesToConsume) {
Consumer(TransferQueue<String> transferQueue, String name, int numberOfMessagesToConsume) {
this.transferQueue = transferQueue;
this.name = name;
this.numberOfMessagesToConsume = numberOfMessagesToConsume;
@@ -12,10 +12,10 @@ public class Producer implements Runnable {
private final TransferQueue<String> transferQueue;
private final String name;
private final Integer numberOfMessagesToProduce;
public final AtomicInteger numberOfProducedMessages = new AtomicInteger();
final Integer numberOfMessagesToProduce;
final AtomicInteger numberOfProducedMessages = new AtomicInteger();
public Producer(TransferQueue<String> transferQueue, String name, Integer numberOfMessagesToProduce) {
Producer(TransferQueue<String> transferQueue, String name, Integer numberOfMessagesToProduce) {
this.transferQueue = transferQueue;
this.name = name;
this.numberOfMessagesToProduce = numberOfMessagesToProduce;
@@ -4,7 +4,11 @@ import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.*;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -18,7 +18,9 @@ public class CountdownLatchExampleIntegrationTest {
// Given
List<String> outputScraper = Collections.synchronizedList(new ArrayList<>());
CountDownLatch countDownLatch = new CountDownLatch(5);
List<Thread> workers = Stream.generate(() -> new Thread(new Worker(outputScraper, countDownLatch))).limit(5).collect(toList());
List<Thread> workers = Stream.generate(() -> new Thread(new Worker(outputScraper, countDownLatch)))
.limit(5)
.collect(toList());
// When
workers.forEach(Thread::start);
@@ -26,7 +28,6 @@ public class CountdownLatchExampleIntegrationTest {
outputScraper.add("Latch released");
// Then
outputScraper.forEach(Object::toString);
assertThat(outputScraper).containsExactly("Counted down", "Counted down", "Counted down", "Counted down", "Counted down", "Latch released");
}
@@ -35,7 +36,9 @@ public class CountdownLatchExampleIntegrationTest {
// Given
List<String> outputScraper = Collections.synchronizedList(new ArrayList<>());
CountDownLatch countDownLatch = new CountDownLatch(5);
List<Thread> workers = Stream.generate(() -> new Thread(new BrokenWorker(outputScraper, countDownLatch))).limit(5).collect(toList());
List<Thread> workers = Stream.generate(() -> new Thread(new BrokenWorker(outputScraper, countDownLatch)))
.limit(5)
.collect(toList());
// When
workers.forEach(Thread::start);
@@ -63,7 +66,6 @@ public class CountdownLatchExampleIntegrationTest {
outputScraper.add("Workers complete");
// Then
outputScraper.forEach(Object::toString);
assertThat(outputScraper).containsExactly("Workers ready", "Counted down", "Counted down", "Counted down", "Counted down", "Counted down", "Workers complete");
}
@@ -22,7 +22,6 @@ public class SquareCalculatorIntegrationTest {
private static final Logger LOG = LoggerFactory.getLogger(SquareCalculatorIntegrationTest.class);
@Rule
public TestName name = new TestName();
@@ -49,9 +49,7 @@ public class SynchronizedHashMapWithRWLockManualTest {
private void executeReaderThreads(SynchronizedHashMapWithRWLock object, int threadCount, ExecutorService service) {
for (int i = 0; i < threadCount; i++)
service.execute(() -> {
object.get("key" + threadCount);
});
service.execute(() -> object.get("key" + threadCount));
}
}
@@ -12,7 +12,7 @@ import static org.junit.Assert.assertNull;
public class ConcurrentMapNullKeyValueManualTest {
ConcurrentMap<String, Object> concurrentMap;
private ConcurrentMap<String, Object> concurrentMap;
@Before
public void setup() {
@@ -18,7 +18,7 @@ public class ConcurrentNavigableMapManualTest {
public void givenSkipListMap_whenAccessInMultiThreads_thenOrderingStable() throws InterruptedException {
NavigableMap<Integer, String> skipListMap = new ConcurrentSkipListMap<>();
updateMapConcurrently(skipListMap, 4);
updateMapConcurrently(skipListMap);
Iterator<Integer> skipListIter = skipListMap.keySet().iterator();
int previous = skipListIter.next();
@@ -28,9 +28,9 @@ public class ConcurrentNavigableMapManualTest {
}
}
private void updateMapConcurrently(NavigableMap<Integer, String> navigableMap, int concurrencyLevel) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(concurrencyLevel);
for (int i = 0; i < concurrencyLevel; i++) {
private void updateMapConcurrently(NavigableMap<Integer, String> navigableMap) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(4);
for (int i = 0; i < 4; i++) {
executorService.execute(() -> {
ThreadLocalRandom random = ThreadLocalRandom.current();
for (int j = 0; j < 10000; j++) {
@@ -45,26 +45,26 @@ public class ConcurrentNavigableMapManualTest {
@Test
public void givenSkipListMap_whenNavConcurrently_thenCountCorrect() throws InterruptedException {
NavigableMap<Integer, Integer> skipListMap = new ConcurrentSkipListMap<>();
int count = countMapElementByPollingFirstEntry(skipListMap, 10000, 4);
int count = countMapElementByPollingFirstEntry(skipListMap);
assertEquals(10000 * 4, count);
}
@Test
public void givenTreeMap_whenNavConcurrently_thenCountError() throws InterruptedException {
NavigableMap<Integer, Integer> treeMap = new TreeMap<>();
int count = countMapElementByPollingFirstEntry(treeMap, 10000, 4);
int count = countMapElementByPollingFirstEntry(treeMap);
assertNotEquals(10000 * 4, count);
}
private int countMapElementByPollingFirstEntry(NavigableMap<Integer, Integer> navigableMap, int elementCount, int concurrencyLevel) throws InterruptedException {
for (int i = 0; i < elementCount * concurrencyLevel; i++) {
private int countMapElementByPollingFirstEntry(NavigableMap<Integer, Integer> navigableMap) throws InterruptedException {
for (int i = 0; i < 10000 * 4; i++) {
navigableMap.put(i, i);
}
AtomicInteger counter = new AtomicInteger(0);
ExecutorService executorService = Executors.newFixedThreadPool(concurrencyLevel);
for (int j = 0; j < concurrencyLevel; j++) {
ExecutorService executorService = Executors.newFixedThreadPool(4);
for (int j = 0; j < 4; j++) {
executorService.execute(() -> {
for (int i = 0; i < elementCount; i++) {
for (int i = 0; i < 10000; i++) {
if (navigableMap.pollFirstEntry() != null) {
counter.incrementAndGet();
}
@@ -2,7 +2,6 @@ package com.baeldung.java.concurrentmodification;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
@@ -28,9 +27,9 @@ public class ConcurrentModificationUnitTest {
List<Integer> integers = newArrayList(1, 2, 3);
for (Iterator<Integer> iterator = integers.iterator(); iterator.hasNext();) {
for (Iterator<Integer> iterator = integers.iterator(); iterator.hasNext(); ) {
Integer integer = iterator.next();
if(integer == 2) {
if (integer == 2) {
iterator.remove();
}
}
@@ -45,7 +44,7 @@ public class ConcurrentModificationUnitTest {
List<Integer> toRemove = newArrayList();
for (Integer integer : integers) {
if(integer == 2) {
if (integer == 2) {
toRemove.add(integer);
}
}
@@ -69,10 +68,10 @@ public class ConcurrentModificationUnitTest {
Collection<Integer> integers = newArrayList(1, 2, 3);
List<String> collected = integers
.stream()
.filter(i -> i != 2)
.map(Object::toString)
.collect(toList());
.stream()
.filter(i -> i != 2)
.map(Object::toString)
.collect(toList());
assertThat(collected).containsExactly("1", "3");
}
@@ -72,7 +72,7 @@ public class Java8ExecutorServiceIntegrationTest {
assertTrue(threadPoolExecutor.isShutdown());
assertFalse(notExecutedTasks.isEmpty());
assertTrue(notExecutedTasks.size() > 0 && notExecutedTasks.size() < 98);
assertTrue(notExecutedTasks.size() < 98);
}
private List<Runnable> smartShutdown(ExecutorService executorService) {
@@ -23,7 +23,10 @@ public class ThreadPoolInParallelStreamIntegrationTest {
List<Long> aList = LongStream.rangeClosed(firstNum, lastNum).boxed().collect(Collectors.toList());
ForkJoinPool customThreadPool = new ForkJoinPool(4);
long actualTotal = customThreadPool.submit(() -> aList.parallelStream().reduce(0L, Long::sum)).get();
long actualTotal = customThreadPool
.submit(() -> aList.parallelStream()
.reduce(0L, Long::sum))
.get();
assertEquals((lastNum + firstNum) * lastNum / 2, actualTotal);
}
+3
View File
@@ -119,3 +119,6 @@
- [Guide to UUID in Java](http://www.baeldung.com/java-uuid)
- [How to Get the Last Element of a Stream in Java?](http://www.baeldung.com/java-stream-last-element)
- [Guide to Escaping Characters in Java RegExps](http://www.baeldung.com/java-regexp-escape-char)
- [Period and Duration in Java](http://www.baeldung.com/java-period-duration)
- [Introduction to the Java 8 Date/Time API](http://www.baeldung.com/java-8-date-time-intro)
- [Migrating to the New Java 8 Date Time API](http://www.baeldung.com/migrating-to-java-8-date-time-api)
+13 -1
View File
@@ -186,6 +186,16 @@
<artifactId>fscontext</artifactId>
<version>${fscontext.version}</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${joda-time.version}</version>
</dependency>
<dependency>
<groupId>com.darwinsys</groupId>
<artifactId>hirondelle-date4j</artifactId>
<version>${hirondelle-date4j.version}</version>
</dependency>
</dependencies>
<build>
@@ -408,6 +418,8 @@
<grep4j.version>1.8.7</grep4j.version>
<lombok.version>1.16.12</lombok.version>
<fscontext.version>4.6-b01</fscontext.version>
<joda-time.version>2.9.9</joda-time.version>
<hirondelle-date4j.version>1.5.1</hirondelle-date4j.version>
<!-- testing -->
<org.hamcrest.version>1.3</org.hamcrest.version>
@@ -416,9 +428,9 @@
<assertj.version>3.6.1</assertj.version>
<avaitility.version>1.7.0</avaitility.version>
<!-- maven plugins -->
<maven-compiler-plugin.version>3.6.0</maven-compiler-plugin.version>
<maven-surefire-plugin.version>2.19.1</maven-surefire-plugin.version>
</properties>
</project>
@@ -0,0 +1,131 @@
package com.baeldung.numberofdigits;
import static com.baeldung.designpatterns.util.LogerUtil.LOG;;
public class Benchmarking {;
private static final int LOWER_BOUND = 1;
private static final int UPPER_BOUND = 999999999;
public static void main(String[] args) {
LOG.info("Testing all methods...");
long length = test_stringBasedSolution();
LOG.info("String Based Solution : " + length);
length = test_logarithmicApproach();
LOG.info("Logarithmic Approach : " + length);
length = test_repeatedMultiplication();
LOG.info("Repeated Multiplication : " + length);
length = test_shiftOperators();
LOG.info("Shift Operators : " + length);
length = test_dividingWithPowersOf2();
LOG.info("Dividing with Powers of 2 : " + length);
length = test_divideAndConquer();
LOG.info("Divide And Conquer : " + length);
}
private static long test_stringBasedSolution() {
long startTime, stopTime, elapsedTime;
startTime = System.currentTimeMillis();
int total = 0;
for (int i = LOWER_BOUND; i <= UPPER_BOUND; i++) {
total += NumberOfDigits.stringBasedSolution(i);
}
stopTime = System.currentTimeMillis();
elapsedTime = stopTime - startTime;
return elapsedTime;
}
private static long test_logarithmicApproach() {
long startTime, stopTime, elapsedTime;
startTime = System.currentTimeMillis();
int total = 0;
for (int i = LOWER_BOUND; i <= UPPER_BOUND; i++) {
total += NumberOfDigits.logarithmicApproach(i);
}
stopTime = System.currentTimeMillis();
elapsedTime = stopTime - startTime;
return elapsedTime;
}
private static long test_repeatedMultiplication() {
long startTime, stopTime, elapsedTime;
startTime = System.currentTimeMillis();
int total = 0;
for (int i = LOWER_BOUND; i <= UPPER_BOUND; i++) {
total += NumberOfDigits.repeatedMultiplication(i);
}
stopTime = System.currentTimeMillis();
elapsedTime = stopTime - startTime;
return elapsedTime;
}
private static long test_shiftOperators() {
long startTime, stopTime, elapsedTime;
startTime = System.currentTimeMillis();
int total = 0;
for (int i = LOWER_BOUND; i <= UPPER_BOUND; i++) {
total += NumberOfDigits.shiftOperators(i);
}
stopTime = System.currentTimeMillis();
elapsedTime = stopTime - startTime;
return elapsedTime;
}
private static long test_dividingWithPowersOf2() {
long startTime, stopTime, elapsedTime;
startTime = System.currentTimeMillis();
int total = 0;
for (int i = LOWER_BOUND; i <= UPPER_BOUND; i++) {
total += NumberOfDigits.dividingWithPowersOf2(i);
}
stopTime = System.currentTimeMillis();
elapsedTime = stopTime - startTime;
return elapsedTime;
}
private static long test_divideAndConquer() {
long startTime, stopTime, elapsedTime;
startTime = System.currentTimeMillis();
int total = 0;
for (int i = LOWER_BOUND; i <= UPPER_BOUND; i++) {
total += NumberOfDigits.divideAndConquer(i);
}
stopTime = System.currentTimeMillis();
elapsedTime = stopTime - startTime;
return elapsedTime;
}
}

Some files were not shown because too many files have changed in this diff Show More