Commit 92bb24e3 authored by Andy Wilkinson's avatar Andy Wilkinson

Avoid synchronizing on this and use an internal monitor instead

Where possible, code that previously synchronized on this (or on the
class in the case of static methods) has been updated to use an
internal monitor object instead. This allows the locking model that's
employed to be an implementation detail rather than part of the
class's API.

Classes that override a synchronized method continue to declare
the overriding method as synchronized. This ensures that locking
is consistent across the superclass and its subclass.

Closes gh-6262
parent f9c7db11
...@@ -33,6 +33,8 @@ public class InMemoryAuditEventRepository implements AuditEventRepository { ...@@ -33,6 +33,8 @@ public class InMemoryAuditEventRepository implements AuditEventRepository {
private static final int DEFAULT_CAPACITY = 4000; private static final int DEFAULT_CAPACITY = 4000;
private final Object monitor = new Object();
/** /**
* Circular buffer of the event with tail pointing to the last element. * Circular buffer of the event with tail pointing to the last element.
*/ */
...@@ -52,36 +54,42 @@ public class InMemoryAuditEventRepository implements AuditEventRepository { ...@@ -52,36 +54,42 @@ public class InMemoryAuditEventRepository implements AuditEventRepository {
* Set the capacity of this event repository. * Set the capacity of this event repository.
* @param capacity the capacity * @param capacity the capacity
*/ */
public synchronized void setCapacity(int capacity) { public void setCapacity(int capacity) {
synchronized (this.monitor) {
this.events = new AuditEvent[capacity]; this.events = new AuditEvent[capacity];
} }
}
@Override @Override
public synchronized void add(AuditEvent event) { public void add(AuditEvent event) {
Assert.notNull(event, "AuditEvent must not be null"); Assert.notNull(event, "AuditEvent must not be null");
synchronized (this.monitor) {
this.tail = (this.tail + 1) % this.events.length; this.tail = (this.tail + 1) % this.events.length;
this.events[this.tail] = event; this.events[this.tail] = event;
} }
}
@Override @Override
public synchronized List<AuditEvent> find(Date after) { public List<AuditEvent> find(Date after) {
return find(null, after, null); return find(null, after, null);
} }
@Override @Override
public synchronized List<AuditEvent> find(String principal, Date after) { public List<AuditEvent> find(String principal, Date after) {
return find(principal, after, null); return find(principal, after, null);
} }
@Override @Override
public synchronized List<AuditEvent> find(String principal, Date after, String type) { public List<AuditEvent> find(String principal, Date after, String type) {
LinkedList<AuditEvent> events = new LinkedList<AuditEvent>(); LinkedList<AuditEvent> events = new LinkedList<AuditEvent>();
synchronized (this.events) {
for (int i = 0; i < this.events.length; i++) { for (int i = 0; i < this.events.length; i++) {
AuditEvent event = resolveTailEvent(i); AuditEvent event = resolveTailEvent(i);
if (event != null && isMatch(principal, after, type, event)) { if (event != null && isMatch(principal, after, type, event)) {
events.addFirst(event); events.addFirst(event);
} }
} }
}
return events; return events;
} }
......
...@@ -88,8 +88,8 @@ public class MailHealthIndicatorTests { ...@@ -88,8 +88,8 @@ public class MailHealthIndicatorTests {
} }
@Override @Override
public synchronized void connect(String host, int port, String user, public void connect(String host, int port, String user, String password)
String password) throws MessagingException { throws MessagingException {
} }
@Override @Override
......
...@@ -61,6 +61,8 @@ public class RunCommand extends OptionParsingCommand { ...@@ -61,6 +61,8 @@ public class RunCommand extends OptionParsingCommand {
private static class RunOptionHandler extends CompilerOptionHandler { private static class RunOptionHandler extends CompilerOptionHandler {
private final Object monitor = new Object();
private OptionSpec<Void> watchOption; private OptionSpec<Void> watchOption;
private OptionSpec<Void> verboseOption; private OptionSpec<Void> verboseOption;
...@@ -77,16 +79,18 @@ public class RunCommand extends OptionParsingCommand { ...@@ -77,16 +79,18 @@ public class RunCommand extends OptionParsingCommand {
this.quietOption = option(Arrays.asList("quiet", "q"), "Quiet logging"); this.quietOption = option(Arrays.asList("quiet", "q"), "Quiet logging");
} }
public synchronized void stop() { public void stop() {
synchronized (this.monitor) {
if (this.runner != null) { if (this.runner != null) {
this.runner.stop(); this.runner.stop();
} }
this.runner = null; this.runner = null;
} }
}
@Override @Override
protected synchronized ExitStatus run(OptionSet options) throws Exception { protected synchronized ExitStatus run(OptionSet options) throws Exception {
synchronized (this.monitor) {
if (this.runner != null) { if (this.runner != null) {
throw new RuntimeException( throw new RuntimeException(
"Already running. Please stop the current application before running another (use the 'stop' command)."); "Already running. Please stop the current application before running another (use the 'stop' command).");
...@@ -108,6 +112,7 @@ public class RunCommand extends OptionParsingCommand { ...@@ -108,6 +112,7 @@ public class RunCommand extends OptionParsingCommand {
return ExitStatus.OK; return ExitStatus.OK;
} }
}
/** /**
* Simple adapter class to present the {@link OptionSet} as a * Simple adapter class to present the {@link OptionSet} as a
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -45,6 +45,8 @@ public class SpringApplicationRunner { ...@@ -45,6 +45,8 @@ public class SpringApplicationRunner {
private static int runnerCounter = 0; private static int runnerCounter = 0;
private final Object monitor = new Object();
private final SpringApplicationRunnerConfiguration configuration; private final SpringApplicationRunnerConfiguration configuration;
private final String[] sources; private final String[] sources;
...@@ -84,11 +86,12 @@ public class SpringApplicationRunner { ...@@ -84,11 +86,12 @@ public class SpringApplicationRunner {
} }
/** /**
* Compile and run the application. This method is synchronized as it can be called by * Compile and run the application.
* file monitoring threads. *
* @throws Exception on error * @throws Exception on error
*/ */
public synchronized void compileAndRun() throws Exception { public void compileAndRun() throws Exception {
synchronized (this.monitor) {
try { try {
stop(); stop();
Object[] compiledSources = compile(); Object[] compiledSources = compile();
...@@ -107,13 +110,16 @@ public class SpringApplicationRunner { ...@@ -107,13 +110,16 @@ public class SpringApplicationRunner {
} }
} }
} }
}
public void stop() { public void stop() {
synchronized (this.monitor) {
if (this.runThread != null) { if (this.runThread != null) {
this.runThread.shutdown(); this.runThread.shutdown();
this.runThread = null; this.runThread = null;
} }
} }
}
private Object[] compile() throws IOException { private Object[] compile() throws IOException {
Object[] compiledSources = this.compiler.compile(this.sources); Object[] compiledSources = this.compiler.compile(this.sources);
...@@ -136,6 +142,8 @@ public class SpringApplicationRunner { ...@@ -136,6 +142,8 @@ public class SpringApplicationRunner {
*/ */
private class RunThread extends Thread { private class RunThread extends Thread {
private final Object monitor = new Object();
private final Object[] compiledSources; private final Object[] compiledSources;
private Object applicationContext; private Object applicationContext;
...@@ -155,6 +163,7 @@ public class SpringApplicationRunner { ...@@ -155,6 +163,7 @@ public class SpringApplicationRunner {
@Override @Override
public void run() { public void run() {
synchronized (this.monitor) {
try { try {
this.applicationContext = new SpringApplicationLauncher( this.applicationContext = new SpringApplicationLauncher(
getContextClassLoader()).launch(this.compiledSources, getContextClassLoader()).launch(this.compiledSources,
...@@ -164,14 +173,17 @@ public class SpringApplicationRunner { ...@@ -164,14 +173,17 @@ public class SpringApplicationRunner {
ex.printStackTrace(); ex.printStackTrace();
} }
} }
}
/** /**
* Shutdown the thread, closing any previously opened application context. * Shutdown the thread, closing any previously opened application context.
*/ */
public synchronized void shutdown() { public void shutdown() {
synchronized (this.monitor) {
if (this.applicationContext != null) { if (this.applicationContext != null) {
try { try {
Method method = this.applicationContext.getClass().getMethod("close"); Method method = this.applicationContext.getClass()
.getMethod("close");
method.invoke(this.applicationContext); method.invoke(this.applicationContext);
} }
catch (NoSuchMethodException ex) { catch (NoSuchMethodException ex) {
...@@ -186,6 +198,7 @@ public class SpringApplicationRunner { ...@@ -186,6 +198,7 @@ public class SpringApplicationRunner {
} }
} }
} }
}
/** /**
* Thread to watch for file changes and trigger recompile/reload. * Thread to watch for file changes and trigger recompile/reload.
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -139,7 +139,7 @@ class Connection { ...@@ -139,7 +139,7 @@ class Connection {
} }
} }
private synchronized void writeWebSocketFrame(Frame frame) throws IOException { private void writeWebSocketFrame(Frame frame) throws IOException {
frame.write(this.outputStream); frame.write(this.outputStream);
} }
......
...@@ -53,6 +53,13 @@ public class LiveReloadServer { ...@@ -53,6 +53,13 @@ public class LiveReloadServer {
private static final int READ_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(4); private static final int READ_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(4);
private final ExecutorService executor = Executors
.newCachedThreadPool(new WorkerThreadFactory());
private final List<Connection> connections = new ArrayList<Connection>();
private final Object monitor = new Object();
private final int port; private final int port;
private final ThreadFactory threadFactory; private final ThreadFactory threadFactory;
...@@ -61,11 +68,6 @@ public class LiveReloadServer { ...@@ -61,11 +68,6 @@ public class LiveReloadServer {
private Thread listenThread; private Thread listenThread;
private ExecutorService executor = Executors
.newCachedThreadPool(new WorkerThreadFactory());
private List<Connection> connections = new ArrayList<Connection>();
/** /**
* Create a new {@link LiveReloadServer} listening on the default port. * Create a new {@link LiveReloadServer} listening on the default port.
*/ */
...@@ -112,7 +114,8 @@ public class LiveReloadServer { ...@@ -112,7 +114,8 @@ public class LiveReloadServer {
* Start the livereload server and accept incoming connections. * Start the livereload server and accept incoming connections.
* @throws IOException in case of I/O errors * @throws IOException in case of I/O errors
*/ */
public synchronized void start() throws IOException { public void start() throws IOException {
synchronized (this.monitor) {
Assert.state(!isStarted(), "Server already started"); Assert.state(!isStarted(), "Server already started");
logger.debug("Starting live reload server on port " + this.port); logger.debug("Starting live reload server on port " + this.port);
this.serverSocket = new ServerSocket(this.port); this.serverSocket = new ServerSocket(this.port);
...@@ -128,14 +131,17 @@ public class LiveReloadServer { ...@@ -128,14 +131,17 @@ public class LiveReloadServer {
this.listenThread.setName("Live Reload Server"); this.listenThread.setName("Live Reload Server");
this.listenThread.start(); this.listenThread.start();
} }
}
/** /**
* Return if the server has been started. * Return if the server has been started.
* @return {@code true} if the server is running * @return {@code true} if the server is running
*/ */
public synchronized boolean isStarted() { public boolean isStarted() {
synchronized (this.monitor) {
return this.listenThread != null; return this.listenThread != null;
} }
}
/** /**
* Return the port that the server is listening on. * Return the port that the server is listening on.
...@@ -168,7 +174,8 @@ public class LiveReloadServer { ...@@ -168,7 +174,8 @@ public class LiveReloadServer {
* Gracefully stop the livereload server. * Gracefully stop the livereload server.
* @throws IOException in case of I/O errors * @throws IOException in case of I/O errors
*/ */
public synchronized void stop() throws IOException { public void stop() throws IOException {
synchronized (this.monitor) {
if (this.listenThread != null) { if (this.listenThread != null) {
closeAllConnections(); closeAllConnections();
try { try {
...@@ -189,9 +196,10 @@ public class LiveReloadServer { ...@@ -189,9 +196,10 @@ public class LiveReloadServer {
this.serverSocket = null; this.serverSocket = null;
} }
} }
}
private void closeAllConnections() throws IOException { private void closeAllConnections() throws IOException {
synchronized (this.connections) { synchronized (this.monitor) {
for (Connection connection : this.connections) { for (Connection connection : this.connections) {
connection.close(); connection.close();
} }
...@@ -202,7 +210,7 @@ public class LiveReloadServer { ...@@ -202,7 +210,7 @@ public class LiveReloadServer {
* Trigger livereload of all connected clients. * Trigger livereload of all connected clients.
*/ */
public void triggerReload() { public void triggerReload() {
synchronized (this.connections) { synchronized (this.monitor) {
for (Connection connection : this.connections) { for (Connection connection : this.connections) {
try { try {
connection.triggerReload(); connection.triggerReload();
...@@ -215,13 +223,13 @@ public class LiveReloadServer { ...@@ -215,13 +223,13 @@ public class LiveReloadServer {
} }
private void addConnection(Connection connection) { private void addConnection(Connection connection) {
synchronized (this.connections) { synchronized (this.monitor) {
this.connections.add(connection); this.connections.add(connection);
} }
} }
private void removeConnection(Connection connection) { private void removeConnection(Connection connection) {
synchronized (this.connections) { synchronized (this.monitor) {
this.connections.remove(connection); this.connections.remove(connection);
} }
} }
......
...@@ -80,10 +80,24 @@ import org.springframework.util.ReflectionUtils; ...@@ -80,10 +80,24 @@ import org.springframework.util.ReflectionUtils;
*/ */
public class Restarter { public class Restarter {
private static final Object INSTANCE_MONITOR = new Object();
private static final String[] NO_ARGS = {}; private static final String[] NO_ARGS = {};
private static Restarter instance; private static Restarter instance;
private final Set<URL> urls = new LinkedHashSet<URL>();
private final ClassLoaderFiles classLoaderFiles = new ClassLoaderFiles();
private final Map<String, Object> attributes = new HashMap<String, Object>();
private final BlockingDeque<LeakSafeThread> leakSafeThreads = new LinkedBlockingDeque<LeakSafeThread>();
private final Lock stopLock = new ReentrantLock();
private final Object monitor = new Object();
private Log logger = new DeferredLog(); private Log logger = new DeferredLog();
private final boolean forceReferenceCleanup; private final boolean forceReferenceCleanup;
...@@ -100,18 +114,8 @@ public class Restarter { ...@@ -100,18 +114,8 @@ public class Restarter {
private final UncaughtExceptionHandler exceptionHandler; private final UncaughtExceptionHandler exceptionHandler;
private final Set<URL> urls = new LinkedHashSet<URL>();
private final ClassLoaderFiles classLoaderFiles = new ClassLoaderFiles();
private final Map<String, Object> attributes = new HashMap<String, Object>();
private final BlockingDeque<LeakSafeThread> leakSafeThreads = new LinkedBlockingDeque<LeakSafeThread>();
private boolean finished = false; private boolean finished = false;
private final Lock stopLock = new ReentrantLock();
private volatile ConfigurableApplicationContext rootContext; private volatile ConfigurableApplicationContext rootContext;
/** /**
...@@ -394,16 +398,21 @@ public class Restarter { ...@@ -394,16 +398,21 @@ public class Restarter {
* Called to finish {@link Restarter} initialization when application logging is * Called to finish {@link Restarter} initialization when application logging is
* available. * available.
*/ */
synchronized void finish() { void finish() {
synchronized (this.monitor) {
if (!isFinished()) { if (!isFinished()) {
this.logger = DeferredLog.replay(this.logger, LogFactory.getLog(getClass())); this.logger = DeferredLog.replay(this.logger,
LogFactory.getLog(getClass()));
this.finished = true; this.finished = true;
} }
} }
}
synchronized boolean isFinished() { boolean isFinished() {
synchronized (this.monitor) {
return this.finished; return this.finished;
} }
}
void prepare(ConfigurableApplicationContext applicationContext) { void prepare(ConfigurableApplicationContext applicationContext) {
if (applicationContext != null && applicationContext.getParent() != null) { if (applicationContext != null && applicationContext.getParent() != null) {
...@@ -514,7 +523,7 @@ public class Restarter { ...@@ -514,7 +523,7 @@ public class Restarter {
public static void initialize(String[] args, boolean forceReferenceCleanup, public static void initialize(String[] args, boolean forceReferenceCleanup,
RestartInitializer initializer, boolean restartOnInitialize) { RestartInitializer initializer, boolean restartOnInitialize) {
Restarter localInstance = null; Restarter localInstance = null;
synchronized (Restarter.class) { synchronized (INSTANCE_MONITOR) {
if (instance == null) { if (instance == null) {
localInstance = new Restarter(Thread.currentThread(), args, localInstance = new Restarter(Thread.currentThread(), args,
forceReferenceCleanup, initializer); forceReferenceCleanup, initializer);
...@@ -531,26 +540,32 @@ public class Restarter { ...@@ -531,26 +540,32 @@ public class Restarter {
* {@link #initialize(String[]) initialization}. * {@link #initialize(String[]) initialization}.
* @return the restarter * @return the restarter
*/ */
public synchronized static Restarter getInstance() { public static Restarter getInstance() {
synchronized (INSTANCE_MONITOR) {
Assert.state(instance != null, "Restarter has not been initialized"); Assert.state(instance != null, "Restarter has not been initialized");
return instance; return instance;
} }
}
/** /**
* Set the restarter instance (useful for testing). * Set the restarter instance (useful for testing).
* @param instance the instance to set * @param instance the instance to set
*/ */
final static void setInstance(Restarter instance) { final static void setInstance(Restarter instance) {
synchronized (INSTANCE_MONITOR) {
Restarter.instance = instance; Restarter.instance = instance;
} }
}
/** /**
* Clear the instance. Primarily provided for tests and not usually used in * Clear the instance. Primarily provided for tests and not usually used in
* application code. * application code.
*/ */
public static void clearInstance() { public static void clearInstance() {
synchronized (INSTANCE_MONITOR) {
instance = null; instance = null;
} }
}
/** /**
* Thread that is created early so not to retain the {@link RestartClassLoader}. * Thread that is created early so not to retain the {@link RestartClassLoader}.
......
...@@ -150,7 +150,7 @@ public class HttpTunnelConnection implements TunnelConnection { ...@@ -150,7 +150,7 @@ public class HttpTunnelConnection implements TunnelConnection {
return size; return size;
} }
private synchronized void openNewConnection(final HttpTunnelPayload payload) { private void openNewConnection(final HttpTunnelPayload payload) {
HttpTunnelConnection.this.executor.execute(new Runnable() { HttpTunnelConnection.this.executor.execute(new Runnable() {
@Override @Override
......
...@@ -46,12 +46,14 @@ public class TunnelClient implements SmartInitializingSingleton { ...@@ -46,12 +46,14 @@ public class TunnelClient implements SmartInitializingSingleton {
private static final Log logger = LogFactory.getLog(TunnelClient.class); private static final Log logger = LogFactory.getLog(TunnelClient.class);
private final TunnelClientListeners listeners = new TunnelClientListeners();
private final Object monitor = new Object();
private final int listenPort; private final int listenPort;
private final TunnelConnection tunnelConnection; private final TunnelConnection tunnelConnection;
private TunnelClientListeners listeners = new TunnelClientListeners();
private ServerThread serverThread; private ServerThread serverThread;
public TunnelClient(int listenPort, TunnelConnection tunnelConnection) { public TunnelClient(int listenPort, TunnelConnection tunnelConnection) {
...@@ -63,6 +65,7 @@ public class TunnelClient implements SmartInitializingSingleton { ...@@ -63,6 +65,7 @@ public class TunnelClient implements SmartInitializingSingleton {
@Override @Override
public void afterSingletonsInstantiated() { public void afterSingletonsInstantiated() {
synchronized (this.monitor) {
if (this.serverThread == null) { if (this.serverThread == null) {
try { try {
start(); start();
...@@ -72,25 +75,30 @@ public class TunnelClient implements SmartInitializingSingleton { ...@@ -72,25 +75,30 @@ public class TunnelClient implements SmartInitializingSingleton {
} }
} }
} }
}
/** /**
* Start the client and accept incoming connections on the port. * Start the client and accept incoming connections on the port.
* @throws IOException in case of I/O errors * @throws IOException in case of I/O errors
*/ */
public synchronized void start() throws IOException { public void start() throws IOException {
synchronized (this.monitor) {
Assert.state(this.serverThread == null, "Server already started"); Assert.state(this.serverThread == null, "Server already started");
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(this.listenPort)); serverSocketChannel.socket().bind(new InetSocketAddress(this.listenPort));
logger.trace("Listening for TCP traffic to tunnel on port " + this.listenPort); logger.trace(
"Listening for TCP traffic to tunnel on port " + this.listenPort);
this.serverThread = new ServerThread(serverSocketChannel); this.serverThread = new ServerThread(serverSocketChannel);
this.serverThread.start(); this.serverThread.start();
} }
}
/** /**
* Stop the client, disconnecting any servers. * Stop the client, disconnecting any servers.
* @throws IOException in case of I/O errors * @throws IOException in case of I/O errors
*/ */
public synchronized void stop() throws IOException { public void stop() throws IOException {
synchronized (this.monitor) {
if (this.serverThread != null) { if (this.serverThread != null) {
logger.trace("Closing tunnel client on port " + this.listenPort); logger.trace("Closing tunnel client on port " + this.listenPort);
this.serverThread.close(); this.serverThread.close();
...@@ -103,10 +111,13 @@ public class TunnelClient implements SmartInitializingSingleton { ...@@ -103,10 +111,13 @@ public class TunnelClient implements SmartInitializingSingleton {
this.serverThread = null; this.serverThread = null;
} }
} }
}
protected final ServerThread getServerThread() { protected final ServerThread getServerThread() {
synchronized (this.monitor) {
return this.serverThread; return this.serverThread;
} }
}
public void addListener(TunnelClientListener listener) { public void addListener(TunnelClientListener listener) {
this.listeners.addListener(listener); this.listeners.addListener(listener);
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -17,8 +17,8 @@ ...@@ -17,8 +17,8 @@
package org.springframework.boot.devtools.tunnel.client; package org.springframework.boot.devtools.tunnel.client;
import java.nio.channels.SocketChannel; import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.springframework.util.Assert; import org.springframework.util.Assert;
...@@ -29,7 +29,7 @@ import org.springframework.util.Assert; ...@@ -29,7 +29,7 @@ import org.springframework.util.Assert;
*/ */
class TunnelClientListeners { class TunnelClientListeners {
private final List<TunnelClientListener> listeners = new ArrayList<TunnelClientListener>(); private final List<TunnelClientListener> listeners = new CopyOnWriteArrayList<TunnelClientListener>();
public void addListener(TunnelClientListener listener) { public void addListener(TunnelClientListener listener) {
Assert.notNull(listener, "Listener must not be null"); Assert.notNull(listener, "Listener must not be null");
......
...@@ -34,12 +34,14 @@ public class HttpTunnelPayloadForwarder { ...@@ -34,12 +34,14 @@ public class HttpTunnelPayloadForwarder {
private static final int MAXIMUM_QUEUE_SIZE = 100; private static final int MAXIMUM_QUEUE_SIZE = 100;
private final Map<Long, HttpTunnelPayload> queue = new HashMap<Long, HttpTunnelPayload>();
private final Object monitor = new Object();
private final WritableByteChannel targetChannel; private final WritableByteChannel targetChannel;
private long lastRequestSeq = 0; private long lastRequestSeq = 0;
private final Map<Long, HttpTunnelPayload> queue = new HashMap<Long, HttpTunnelPayload>();
/** /**
* Create a new {@link HttpTunnelPayloadForwarder} instance. * Create a new {@link HttpTunnelPayloadForwarder} instance.
* @param targetChannel the target channel * @param targetChannel the target channel
...@@ -49,7 +51,8 @@ public class HttpTunnelPayloadForwarder { ...@@ -49,7 +51,8 @@ public class HttpTunnelPayloadForwarder {
this.targetChannel = targetChannel; this.targetChannel = targetChannel;
} }
public synchronized void forward(HttpTunnelPayload payload) throws IOException { public void forward(HttpTunnelPayload payload) throws IOException {
synchronized (this.monitor) {
long seq = payload.getSequence(); long seq = payload.getSequence();
if (this.lastRequestSeq != seq - 1) { if (this.lastRequestSeq != seq - 1) {
Assert.state(this.queue.size() < MAXIMUM_QUEUE_SIZE, Assert.state(this.queue.size() < MAXIMUM_QUEUE_SIZE,
...@@ -65,5 +68,6 @@ public class HttpTunnelPayloadForwarder { ...@@ -65,5 +68,6 @@ public class HttpTunnelPayloadForwarder {
forward(queuedItem); forward(queuedItem);
} }
} }
}
} }
...@@ -28,14 +28,21 @@ public class Snake { ...@@ -28,14 +28,21 @@ public class Snake {
private static final int DEFAULT_LENGTH = 5; private static final int DEFAULT_LENGTH = 5;
private final Deque<Location> tail = new ArrayDeque<Location>();
private final Object monitor = new Object();
private final int id; private final int id;
private final WebSocketSession session; private final WebSocketSession session;
private final String hexColor;
private Direction direction; private Direction direction;
private int length = DEFAULT_LENGTH; private int length = DEFAULT_LENGTH;
private Location head; private Location head;
private final Deque<Location> tail = new ArrayDeque<Location>();
private final String hexColor;
public Snake(int id, WebSocketSession session) { public Snake(int id, WebSocketSession session) {
this.id = id; this.id = id;
...@@ -51,21 +58,26 @@ public class Snake { ...@@ -51,21 +58,26 @@ public class Snake {
this.length = DEFAULT_LENGTH; this.length = DEFAULT_LENGTH;
} }
private synchronized void kill() throws Exception { private void kill() throws Exception {
synchronized (this.monitor) {
resetState(); resetState();
sendMessage("{'type': 'dead'}"); sendMessage("{'type': 'dead'}");
} }
}
private synchronized void reward() throws Exception { private void reward() throws Exception {
synchronized (this.monitor) {
this.length++; this.length++;
sendMessage("{'type': 'kill'}"); sendMessage("{'type': 'kill'}");
} }
}
protected void sendMessage(String msg) throws Exception { protected void sendMessage(String msg) throws Exception {
this.session.sendMessage(new TextMessage(msg)); this.session.sendMessage(new TextMessage(msg));
} }
public synchronized void update(Collection<Snake> snakes) throws Exception { public void update(Collection<Snake> snakes) throws Exception {
synchronized (this.monitor) {
Location nextLocation = this.head.getAdjacentLocation(this.direction); Location nextLocation = this.head.getAdjacentLocation(this.direction);
if (nextLocation.x >= SnakeUtils.PLAYFIELD_WIDTH) { if (nextLocation.x >= SnakeUtils.PLAYFIELD_WIDTH) {
nextLocation.x = 0; nextLocation.x = 0;
...@@ -89,6 +101,7 @@ public class Snake { ...@@ -89,6 +101,7 @@ public class Snake {
handleCollisions(snakes); handleCollisions(snakes);
} }
}
private void handleCollisions(Collection<Snake> snakes) throws Exception { private void handleCollisions(Collection<Snake> snakes) throws Exception {
for (Snake snake : snakes) { for (Snake snake : snakes) {
...@@ -104,19 +117,26 @@ public class Snake { ...@@ -104,19 +117,26 @@ public class Snake {
} }
} }
public synchronized Location getHead() { public Location getHead() {
synchronized (this.monitor) {
return this.head; return this.head;
} }
}
public synchronized Collection<Location> getTail() { public Collection<Location> getTail() {
synchronized (this.monitor) {
return this.tail; return this.tail;
} }
}
public synchronized void setDirection(Direction direction) { public void setDirection(Direction direction) {
synchronized (this.monitor) {
this.direction = direction; this.direction = direction;
} }
}
public synchronized String getLocationsJson() { public String getLocationsJson() {
synchronized (this.monitor) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(String.format("{x: %d, y: %d}", Integer.valueOf(this.head.x), sb.append(String.format("{x: %d, y: %d}", Integer.valueOf(this.head.x),
Integer.valueOf(this.head.y))); Integer.valueOf(this.head.y)));
...@@ -128,6 +148,7 @@ public class Snake { ...@@ -128,6 +148,7 @@ public class Snake {
return String.format("{'id':%d,'body':[%s]}", Integer.valueOf(this.id), return String.format("{'id':%d,'body':[%s]}", Integer.valueOf(this.id),
sb.toString()); sb.toString());
} }
}
public int getId() { public int getId() {
return this.id; return this.id;
......
...@@ -33,31 +33,37 @@ import org.slf4j.LoggerFactory; ...@@ -33,31 +33,37 @@ import org.slf4j.LoggerFactory;
*/ */
public class SnakeTimer { public class SnakeTimer {
private static final Logger log = LoggerFactory.getLogger(SnakeTimer.class); private static final long TICK_DELAY = 100;
private static Timer gameTimer = null; private static final Object MONITOR = new Object();
private static final long TICK_DELAY = 100; private static final Logger log = LoggerFactory.getLogger(SnakeTimer.class);
private static final ConcurrentHashMap<Integer, Snake> snakes = new ConcurrentHashMap<Integer, Snake>(); private static final ConcurrentHashMap<Integer, Snake> snakes = new ConcurrentHashMap<Integer, Snake>();
public static synchronized void addSnake(Snake snake) { private static Timer gameTimer = null;
public static void addSnake(Snake snake) {
synchronized (MONITOR) {
if (snakes.isEmpty()) { if (snakes.isEmpty()) {
startTimer(); startTimer();
} }
snakes.put(Integer.valueOf(snake.getId()), snake); snakes.put(Integer.valueOf(snake.getId()), snake);
} }
}
public static Collection<Snake> getSnakes() { public static Collection<Snake> getSnakes() {
return Collections.unmodifiableCollection(snakes.values()); return Collections.unmodifiableCollection(snakes.values());
} }
public static synchronized void removeSnake(Snake snake) { public static void removeSnake(Snake snake) {
synchronized (MONITOR) {
snakes.remove(Integer.valueOf(snake.getId())); snakes.remove(Integer.valueOf(snake.getId()));
if (snakes.isEmpty()) { if (snakes.isEmpty()) {
stopTimer(); stopTimer();
} }
} }
}
public static void tick() throws Exception { public static void tick() throws Exception {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
......
...@@ -28,14 +28,21 @@ public class Snake { ...@@ -28,14 +28,21 @@ public class Snake {
private static final int DEFAULT_LENGTH = 5; private static final int DEFAULT_LENGTH = 5;
private final Deque<Location> tail = new ArrayDeque<Location>();
private final Object monitor = new Object();
private final int id; private final int id;
private final WebSocketSession session; private final WebSocketSession session;
private final String hexColor;
private Direction direction; private Direction direction;
private int length = DEFAULT_LENGTH; private int length = DEFAULT_LENGTH;
private Location head; private Location head;
private final Deque<Location> tail = new ArrayDeque<Location>();
private final String hexColor;
public Snake(int id, WebSocketSession session) { public Snake(int id, WebSocketSession session) {
this.id = id; this.id = id;
...@@ -51,21 +58,26 @@ public class Snake { ...@@ -51,21 +58,26 @@ public class Snake {
this.length = DEFAULT_LENGTH; this.length = DEFAULT_LENGTH;
} }
private synchronized void kill() throws Exception { private void kill() throws Exception {
synchronized (this.monitor) {
resetState(); resetState();
sendMessage("{'type': 'dead'}"); sendMessage("{'type': 'dead'}");
} }
}
private synchronized void reward() throws Exception { private void reward() throws Exception {
synchronized (this.monitor) {
this.length++; this.length++;
sendMessage("{'type': 'kill'}"); sendMessage("{'type': 'kill'}");
} }
}
protected void sendMessage(String msg) throws Exception { protected void sendMessage(String msg) throws Exception {
this.session.sendMessage(new TextMessage(msg)); this.session.sendMessage(new TextMessage(msg));
} }
public synchronized void update(Collection<Snake> snakes) throws Exception { public void update(Collection<Snake> snakes) throws Exception {
synchronized (this.monitor) {
Location nextLocation = this.head.getAdjacentLocation(this.direction); Location nextLocation = this.head.getAdjacentLocation(this.direction);
if (nextLocation.x >= SnakeUtils.PLAYFIELD_WIDTH) { if (nextLocation.x >= SnakeUtils.PLAYFIELD_WIDTH) {
nextLocation.x = 0; nextLocation.x = 0;
...@@ -89,6 +101,7 @@ public class Snake { ...@@ -89,6 +101,7 @@ public class Snake {
handleCollisions(snakes); handleCollisions(snakes);
} }
}
private void handleCollisions(Collection<Snake> snakes) throws Exception { private void handleCollisions(Collection<Snake> snakes) throws Exception {
for (Snake snake : snakes) { for (Snake snake : snakes) {
...@@ -104,19 +117,26 @@ public class Snake { ...@@ -104,19 +117,26 @@ public class Snake {
} }
} }
public synchronized Location getHead() { public Location getHead() {
synchronized (this.monitor) {
return this.head; return this.head;
} }
}
public synchronized Collection<Location> getTail() { public Collection<Location> getTail() {
synchronized (this.monitor) {
return this.tail; return this.tail;
} }
}
public synchronized void setDirection(Direction direction) { public void setDirection(Direction direction) {
synchronized (this.monitor) {
this.direction = direction; this.direction = direction;
} }
}
public synchronized String getLocationsJson() { public String getLocationsJson() {
synchronized (this.monitor) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(String.format("{x: %d, y: %d}", Integer.valueOf(this.head.x), sb.append(String.format("{x: %d, y: %d}", Integer.valueOf(this.head.x),
Integer.valueOf(this.head.y))); Integer.valueOf(this.head.y)));
...@@ -128,6 +148,7 @@ public class Snake { ...@@ -128,6 +148,7 @@ public class Snake {
return String.format("{'id':%d,'body':[%s]}", Integer.valueOf(this.id), return String.format("{'id':%d,'body':[%s]}", Integer.valueOf(this.id),
sb.toString()); sb.toString());
} }
}
public int getId() { public int getId() {
return this.id; return this.id;
......
...@@ -33,31 +33,37 @@ import org.apache.juli.logging.LogFactory; ...@@ -33,31 +33,37 @@ import org.apache.juli.logging.LogFactory;
*/ */
public class SnakeTimer { public class SnakeTimer {
private static final Log log = LogFactory.getLog(SnakeTimer.class); private static final long TICK_DELAY = 100;
private static Timer gameTimer = null; private static final Object MONITOR = new Object();
private static final long TICK_DELAY = 100; private static final Log log = LogFactory.getLog(SnakeTimer.class);
private static final ConcurrentHashMap<Integer, Snake> snakes = new ConcurrentHashMap<Integer, Snake>(); private static final ConcurrentHashMap<Integer, Snake> snakes = new ConcurrentHashMap<Integer, Snake>();
public static synchronized void addSnake(Snake snake) { private static Timer gameTimer = null;
public static void addSnake(Snake snake) {
synchronized (MONITOR) {
if (snakes.isEmpty()) { if (snakes.isEmpty()) {
startTimer(); startTimer();
} }
snakes.put(Integer.valueOf(snake.getId()), snake); snakes.put(Integer.valueOf(snake.getId()), snake);
} }
}
public static Collection<Snake> getSnakes() { public static Collection<Snake> getSnakes() {
return Collections.unmodifiableCollection(snakes.values()); return Collections.unmodifiableCollection(snakes.values());
} }
public static synchronized void removeSnake(Snake snake) { public static void removeSnake(Snake snake) {
synchronized (MONITOR) {
snakes.remove(Integer.valueOf(snake.getId())); snakes.remove(Integer.valueOf(snake.getId()));
if (snakes.isEmpty()) { if (snakes.isEmpty()) {
stopTimer(); stopTimer();
} }
} }
}
public static void tick() throws Exception { public static void tick() throws Exception {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
......
...@@ -28,14 +28,21 @@ public class Snake { ...@@ -28,14 +28,21 @@ public class Snake {
private static final int DEFAULT_LENGTH = 5; private static final int DEFAULT_LENGTH = 5;
private final Deque<Location> tail = new ArrayDeque<Location>();
private final Object monitor = new Object();
private final int id; private final int id;
private final WebSocketSession session; private final WebSocketSession session;
private final String hexColor;
private Direction direction; private Direction direction;
private int length = DEFAULT_LENGTH; private int length = DEFAULT_LENGTH;
private Location head; private Location head;
private final Deque<Location> tail = new ArrayDeque<Location>();
private final String hexColor;
public Snake(int id, WebSocketSession session) { public Snake(int id, WebSocketSession session) {
this.id = id; this.id = id;
...@@ -51,21 +58,26 @@ public class Snake { ...@@ -51,21 +58,26 @@ public class Snake {
this.length = DEFAULT_LENGTH; this.length = DEFAULT_LENGTH;
} }
private synchronized void kill() throws Exception { private void kill() throws Exception {
synchronized (this.monitor) {
resetState(); resetState();
sendMessage("{'type': 'dead'}"); sendMessage("{'type': 'dead'}");
} }
}
private synchronized void reward() throws Exception { private void reward() throws Exception {
synchronized (this.monitor) {
this.length++; this.length++;
sendMessage("{'type': 'kill'}"); sendMessage("{'type': 'kill'}");
} }
}
protected void sendMessage(String msg) throws Exception { protected void sendMessage(String msg) throws Exception {
this.session.sendMessage(new TextMessage(msg)); this.session.sendMessage(new TextMessage(msg));
} }
public synchronized void update(Collection<Snake> snakes) throws Exception { public void update(Collection<Snake> snakes) throws Exception {
synchronized (this.monitor) {
Location nextLocation = this.head.getAdjacentLocation(this.direction); Location nextLocation = this.head.getAdjacentLocation(this.direction);
if (nextLocation.x >= SnakeUtils.PLAYFIELD_WIDTH) { if (nextLocation.x >= SnakeUtils.PLAYFIELD_WIDTH) {
nextLocation.x = 0; nextLocation.x = 0;
...@@ -89,6 +101,7 @@ public class Snake { ...@@ -89,6 +101,7 @@ public class Snake {
handleCollisions(snakes); handleCollisions(snakes);
} }
}
private void handleCollisions(Collection<Snake> snakes) throws Exception { private void handleCollisions(Collection<Snake> snakes) throws Exception {
for (Snake snake : snakes) { for (Snake snake : snakes) {
...@@ -104,19 +117,26 @@ public class Snake { ...@@ -104,19 +117,26 @@ public class Snake {
} }
} }
public synchronized Location getHead() { public Location getHead() {
synchronized (this.monitor) {
return this.head; return this.head;
} }
}
public synchronized Collection<Location> getTail() { public Collection<Location> getTail() {
synchronized (this.monitor) {
return this.tail; return this.tail;
} }
}
public synchronized void setDirection(Direction direction) { public void setDirection(Direction direction) {
synchronized (this.monitor) {
this.direction = direction; this.direction = direction;
} }
}
public synchronized String getLocationsJson() { public String getLocationsJson() {
synchronized (this.monitor) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(String.format("{x: %d, y: %d}", Integer.valueOf(this.head.x), sb.append(String.format("{x: %d, y: %d}", Integer.valueOf(this.head.x),
Integer.valueOf(this.head.y))); Integer.valueOf(this.head.y)));
...@@ -128,6 +148,7 @@ public class Snake { ...@@ -128,6 +148,7 @@ public class Snake {
return String.format("{'id':%d,'body':[%s]}", Integer.valueOf(this.id), return String.format("{'id':%d,'body':[%s]}", Integer.valueOf(this.id),
sb.toString()); sb.toString());
} }
}
public int getId() { public int getId() {
return this.id; return this.id;
......
...@@ -33,31 +33,37 @@ import org.slf4j.LoggerFactory; ...@@ -33,31 +33,37 @@ import org.slf4j.LoggerFactory;
*/ */
public class SnakeTimer { public class SnakeTimer {
private static final Logger log = LoggerFactory.getLogger(SnakeTimer.class); private static final long TICK_DELAY = 100;
private static Timer gameTimer = null; private static final Object MONITOR = new Object();
private static final long TICK_DELAY = 100; private static final Logger log = LoggerFactory.getLogger(SnakeTimer.class);
private static final ConcurrentHashMap<Integer, Snake> snakes = new ConcurrentHashMap<Integer, Snake>(); private static final ConcurrentHashMap<Integer, Snake> snakes = new ConcurrentHashMap<Integer, Snake>();
public static synchronized void addSnake(Snake snake) { private static Timer gameTimer = null;
public static void addSnake(Snake snake) {
synchronized (MONITOR) {
if (snakes.isEmpty()) { if (snakes.isEmpty()) {
startTimer(); startTimer();
} }
snakes.put(Integer.valueOf(snake.getId()), snake); snakes.put(Integer.valueOf(snake.getId()), snake);
} }
}
public static Collection<Snake> getSnakes() { public static Collection<Snake> getSnakes() {
return Collections.unmodifiableCollection(snakes.values()); return Collections.unmodifiableCollection(snakes.values());
} }
public static synchronized void removeSnake(Snake snake) { public static void removeSnake(Snake snake) {
synchronized (MONITOR) {
snakes.remove(Integer.valueOf(snake.getId())); snakes.remove(Integer.valueOf(snake.getId()));
if (snakes.isEmpty()) { if (snakes.isEmpty()) {
stopTimer(); stopTimer();
} }
} }
}
public static void tick() throws Exception { public static void tick() throws Exception {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
......
...@@ -89,6 +89,8 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor { ...@@ -89,6 +89,8 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor {
private static class Verification { private static class Verification {
private final Object monitor = new Object();
private final MockingProgress progress; private final MockingProgress progress;
Verification(Object target) { Verification(Object target) {
...@@ -101,7 +103,8 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor { ...@@ -101,7 +103,8 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor {
this.progress = (MockingProgress) ReflectionUtils.getField(field, container); this.progress = (MockingProgress) ReflectionUtils.getField(field, container);
} }
public synchronized boolean isVerifying() { public boolean isVerifying() {
synchronized (this.monitor) {
VerificationMode mode = this.progress.pullVerificationMode(); VerificationMode mode = this.progress.pullVerificationMode();
if (mode != null) { if (mode != null) {
this.progress.verificationStarted(mode); this.progress.verificationStarted(mode);
...@@ -109,8 +112,10 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor { ...@@ -109,8 +112,10 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor {
} }
return false; return false;
} }
}
public synchronized void replaceVerifyMock(Object source, Object target) { public void replaceVerifyMock(Object source, Object target) {
synchronized (this.monitor) {
VerificationMode mode = this.progress.pullVerificationMode(); VerificationMode mode = this.progress.pullVerificationMode();
if (mode != null) { if (mode != null) {
if (mode instanceof MockAwareVerificationMode) { if (mode instanceof MockAwareVerificationMode) {
...@@ -122,6 +127,7 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor { ...@@ -122,6 +127,7 @@ class MockitoAopProxyTargetInterceptor implements MethodInterceptor {
this.progress.verificationStarted(mode); this.progress.verificationStarted(mode);
} }
} }
}
} }
......
...@@ -426,6 +426,8 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { ...@@ -426,6 +426,8 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
*/ */
class IsolatedThreadGroup extends ThreadGroup { class IsolatedThreadGroup extends ThreadGroup {
private final Object monitor = new Object();
private Throwable exception; private Throwable exception;
IsolatedThreadGroup(String name) { IsolatedThreadGroup(String name) {
...@@ -435,18 +437,21 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { ...@@ -435,18 +437,21 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
@Override @Override
public void uncaughtException(Thread thread, Throwable ex) { public void uncaughtException(Thread thread, Throwable ex) {
if (!(ex instanceof ThreadDeath)) { if (!(ex instanceof ThreadDeath)) {
synchronized (this) { synchronized (this.monitor) {
this.exception = (this.exception == null ? ex : this.exception); this.exception = (this.exception == null ? ex : this.exception);
} }
getLog().warn(ex); getLog().warn(ex);
} }
} }
public synchronized void rethrowUncaughtException() public void rethrowUncaughtException() throws MojoExecutionException {
throws MojoExecutionException { synchronized (this.monitor) {
if (this.exception != null) { if (this.exception != null) {
throw new MojoExecutionException("An exception occurred while running. " throw new MojoExecutionException(
+ this.exception.getMessage(), this.exception); "An exception occurred while running. "
+ this.exception.getMessage(),
this.exception);
}
} }
} }
......
...@@ -51,6 +51,8 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer { ...@@ -51,6 +51,8 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer {
private static final Log logger = LogFactory private static final Log logger = LogFactory
.getLog(JettyEmbeddedServletContainer.class); .getLog(JettyEmbeddedServletContainer.class);
private final Object monitor = new Object();
private final Server server; private final Server server;
private final boolean autoStart; private final boolean autoStart;
...@@ -77,7 +79,8 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer { ...@@ -77,7 +79,8 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer {
initialize(); initialize();
} }
private synchronized void initialize() { private void initialize() {
synchronized (this.monitor) {
try { try {
// Cache and clear the connectors to prevent requests being handled before // Cache and clear the connectors to prevent requests being handled before
// the application context is ready // the application context is ready
...@@ -95,6 +98,7 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer { ...@@ -95,6 +98,7 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer {
"Unable to start embedded Jetty servlet container", ex); "Unable to start embedded Jetty servlet container", ex);
} }
} }
}
private void stopSilently() { private void stopSilently() {
try { try {
...@@ -191,7 +195,8 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer { ...@@ -191,7 +195,8 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer {
} }
@Override @Override
public synchronized void stop() { public void stop() {
synchronized (this.monitor) {
try { try {
this.server.stop(); this.server.stop();
} }
...@@ -203,6 +208,7 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer { ...@@ -203,6 +208,7 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer {
"Unable to stop embedded Jetty servlet container", ex); "Unable to stop embedded Jetty servlet container", ex);
} }
} }
}
@Override @Override
public int getPort() { public int getPort() {
......
...@@ -53,12 +53,14 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer ...@@ -53,12 +53,14 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
private static final Log logger = LogFactory private static final Log logger = LogFactory
.getLog(TomcatEmbeddedServletContainer.class); .getLog(TomcatEmbeddedServletContainer.class);
private static AtomicInteger containerCounter = new AtomicInteger(-1); private static final AtomicInteger containerCounter = new AtomicInteger(-1);
private final Tomcat tomcat; private final Object monitor = new Object();
private final Map<Service, Connector[]> serviceConnectors = new HashMap<Service, Connector[]>(); private final Map<Service, Connector[]> serviceConnectors = new HashMap<Service, Connector[]>();
private final Tomcat tomcat;
private final boolean autoStart; private final boolean autoStart;
/** /**
...@@ -81,9 +83,10 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer ...@@ -81,9 +83,10 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
initialize(); initialize();
} }
private synchronized void initialize() throws EmbeddedServletContainerException { private void initialize() throws EmbeddedServletContainerException {
TomcatEmbeddedServletContainer.logger TomcatEmbeddedServletContainer.logger
.info("Tomcat initialized with port(s): " + getPortsDescription(false)); .info("Tomcat initialized with port(s): " + getPortsDescription(false));
synchronized (this.monitor) {
try { try {
addInstanceIdToEngineName(); addInstanceIdToEngineName();
...@@ -110,8 +113,9 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer ...@@ -110,8 +113,9 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
startDaemonAwaitThread(); startDaemonAwaitThread();
} }
catch (Exception ex) { catch (Exception ex) {
throw new EmbeddedServletContainerException("Unable to start embedded Tomcat", throw new EmbeddedServletContainerException(
ex); "Unable to start embedded Tomcat", ex);
}
} }
} }
...@@ -266,7 +270,8 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer ...@@ -266,7 +270,8 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
} }
@Override @Override
public synchronized void stop() throws EmbeddedServletContainerException { public void stop() throws EmbeddedServletContainerException {
synchronized (this.monitor) {
try { try {
try { try {
stopTomcat(); stopTomcat();
...@@ -277,13 +282,14 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer ...@@ -277,13 +282,14 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
} }
} }
catch (Exception ex) { catch (Exception ex) {
throw new EmbeddedServletContainerException("Unable to stop embedded Tomcat", throw new EmbeddedServletContainerException(
ex); "Unable to stop embedded Tomcat", ex);
} }
finally { finally {
containerCounter.decrementAndGet(); containerCounter.decrementAndGet();
} }
} }
}
private String getPortsDescription(boolean localPort) { private String getPortsDescription(boolean localPort) {
StringBuilder ports = new StringBuilder(); StringBuilder ports = new StringBuilder();
......
...@@ -70,6 +70,8 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine ...@@ -70,6 +70,8 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine
private static final Log logger = LogFactory private static final Log logger = LogFactory
.getLog(UndertowEmbeddedServletContainer.class); .getLog(UndertowEmbeddedServletContainer.class);
private final Object monitor = new Object();
private final Builder builder; private final Builder builder;
private final DeploymentManager manager; private final DeploymentManager manager;
...@@ -197,7 +199,8 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine ...@@ -197,7 +199,8 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine
} }
@Override @Override
public synchronized void start() throws EmbeddedServletContainerException { public void start() throws EmbeddedServletContainerException {
synchronized (this.monitor) {
try { try {
if (!this.autoStart) { if (!this.autoStart) {
return; return;
...@@ -224,6 +227,7 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine ...@@ -224,6 +227,7 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine
"Unable to start embedded Undertow", ex); "Unable to start embedded Undertow", ex);
} }
} }
}
private BindException findBindException(Exception ex) { private BindException findBindException(Exception ex) {
Throwable candidate = ex; Throwable candidate = ex;
...@@ -356,7 +360,8 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine ...@@ -356,7 +360,8 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine
} }
@Override @Override
public synchronized void stop() throws EmbeddedServletContainerException { public void stop() throws EmbeddedServletContainerException {
synchronized (this.monitor) {
if (this.started) { if (this.started) {
try { try {
this.started = false; this.started = false;
...@@ -369,6 +374,7 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine ...@@ -369,6 +374,7 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine
} }
} }
} }
}
@Override @Override
public int getPort() { public int getPort() {
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -46,7 +46,7 @@ import org.springframework.util.StringUtils; ...@@ -46,7 +46,7 @@ import org.springframework.util.StringUtils;
public class PoolingConnectionFactoryBean extends PoolingConnectionFactory public class PoolingConnectionFactoryBean extends PoolingConnectionFactory
implements BeanNameAware, InitializingBean, DisposableBean { implements BeanNameAware, InitializingBean, DisposableBean {
private static ThreadLocal<PoolingConnectionFactoryBean> source = new ThreadLocal<PoolingConnectionFactoryBean>(); private static final ThreadLocal<PoolingConnectionFactoryBean> source = new ThreadLocal<PoolingConnectionFactoryBean>();
private String beanName; private String beanName;
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -50,7 +50,7 @@ import org.springframework.util.StringUtils; ...@@ -50,7 +50,7 @@ import org.springframework.util.StringUtils;
public class PoolingDataSourceBean extends PoolingDataSource public class PoolingDataSourceBean extends PoolingDataSource
implements BeanNameAware, InitializingBean { implements BeanNameAware, InitializingBean {
private static ThreadLocal<PoolingDataSourceBean> source = new ThreadLocal<PoolingDataSourceBean>(); private static final ThreadLocal<PoolingDataSourceBean> source = new ThreadLocal<PoolingDataSourceBean>();
private XADataSource dataSource; private XADataSource dataSource;
......
...@@ -51,7 +51,7 @@ public class AtomikosDataSourceBeanTests { ...@@ -51,7 +51,7 @@ public class AtomikosDataSourceBeanTests {
} }
@Override @Override
public synchronized void close() { public void close() {
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment