Cleaning up server side exception handling.

This commit is contained in:
marcins78
2013-01-04 10:49:58 +00:00
parent edfc33800f
commit 49c275564b
19 changed files with 125 additions and 75 deletions

View File

@@ -0,0 +1,4 @@
package com.gempukku.lotro;
public class PrivateInformationException extends Exception {
}

View File

@@ -0,0 +1,4 @@
package com.gempukku.lotro;
public class SubscriptionConflictException extends Exception {
}

View File

@@ -0,0 +1,4 @@
package com.gempukku.lotro;
public class SubscriptionExpiredException extends Exception {
}

View File

@@ -1,9 +1,9 @@
package com.gempukku.lotro.chat;
import com.gempukku.lotro.PrivateInformationException;
import com.gempukku.lotro.SubscriptionExpiredException;
import com.gempukku.lotro.game.GatheringChatRoomListener;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -39,12 +39,12 @@ public class ChatRoomMediator {
}
}
public List<ChatMessage> getPendingMessages(String playerId) throws UserUnsubscribedException {
public List<ChatMessage> getPendingMessages(String playerId) throws SubscriptionExpiredException {
_lock.readLock().lock();
try {
GatheringChatRoomListener gatheringChatRoomListener = _listeners.get(playerId);
if (gatheringChatRoomListener == null)
throw new UserUnsubscribedException();
throw new SubscriptionExpiredException();
return gatheringChatRoomListener.consumeMessages();
} finally {
_lock.readLock().unlock();
@@ -61,11 +61,11 @@ public class ChatRoomMediator {
}
}
public void sendMessage(String playerId, String message, boolean admin) {
public void sendMessage(String playerId, String message, boolean admin) throws PrivateInformationException {
_lock.writeLock().lock();
try {
if (!admin && _allowedPlayers != null && !_allowedPlayers.contains(playerId))
throw new WebApplicationException(Response.Status.FORBIDDEN);
throw new PrivateInformationException();
_chatRoom.postMessage(playerId, message);
} finally {

View File

@@ -1,6 +1,7 @@
package com.gempukku.lotro.chat;
import com.gempukku.lotro.AbstractServer;
import com.gempukku.lotro.PrivateInformationException;
import java.util.Map;
import java.util.Set;
@@ -11,21 +12,33 @@ public class ChatServer extends AbstractServer {
public ChatRoomMediator createChatRoom(String name, int secondsTimeoutPeriod) {
ChatRoomMediator chatRoom = new ChatRoomMediator(secondsTimeoutPeriod);
chatRoom.sendMessage("System", "Welcome to room: " + name, true);
try {
chatRoom.sendMessage("System", "Welcome to room: " + name, true);
} catch (PrivateInformationException exp) {
// Ignore, sent as admin
}
_chatRooms.put(name, chatRoom);
return chatRoom;
}
public ChatRoomMediator createVoicedChatRoom(String name, Set<String> allowedUsers, int secondsTimeoutPeriod) {
ChatRoomMediator chatRoom = new ChatRoomMediator(secondsTimeoutPeriod, allowedUsers);
chatRoom.sendMessage("System", "Welcome to private room: " + name, true);
try {
chatRoom.sendMessage("System", "Welcome to private room: " + name, true);
} catch (PrivateInformationException exp) {
// Ignore, sent as admin
}
_chatRooms.put(name, chatRoom);
return chatRoom;
}
public void sendSystemMessageToAllChatRooms(String message) {
for (ChatRoomMediator chatRoomMediator : _chatRooms.values())
chatRoomMediator.sendMessage("System", message, true);
try {
for (ChatRoomMediator chatRoomMediator : _chatRooms.values())
chatRoomMediator.sendMessage("System", message, true);
} catch (PrivateInformationException exp) {
// Ignore, sent as admin
}
}
public ChatRoomMediator getChatRoom(String name) {

View File

@@ -1,4 +0,0 @@
package com.gempukku.lotro.chat;
public class UserUnsubscribedException extends Exception {
}

View File

@@ -1,5 +1,8 @@
package com.gempukku.lotro.game;
import com.gempukku.lotro.PrivateInformationException;
import com.gempukku.lotro.SubscriptionConflictException;
import com.gempukku.lotro.SubscriptionExpiredException;
import com.gempukku.lotro.common.*;
import com.gempukku.lotro.communication.GameStateListener;
import com.gempukku.lotro.filters.Filters;
@@ -14,8 +17,6 @@ import com.gempukku.lotro.logic.timing.GameResultListener;
import com.gempukku.lotro.logic.vo.LotroDeck;
import org.apache.log4j.Logger;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import java.util.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -291,7 +292,7 @@ public class LotroGameMediator {
}
}
public void playerAnswered(Player player, int channelNumber, int decisionId, String answer) {
public void playerAnswered(Player player, int channelNumber, int decisionId, String answer) throws SubscriptionConflictException, SubscriptionExpiredException {
String playerName = player.getName();
_writeLock.lock();
try {
@@ -322,20 +323,20 @@ public class LotroGameMediator {
}
}
} else {
throw new WebApplicationException(Response.Status.CONFLICT);
throw new SubscriptionConflictException();
}
} else {
throw new WebApplicationException(Response.Status.GONE);
throw new SubscriptionExpiredException();
}
} finally {
_writeLock.unlock();
}
}
public void processCommunicationChannel(Player player, int channelNumber, ParticipantCommunicationVisitor visitor) {
public void processCommunicationChannel(Player player, int channelNumber, ParticipantCommunicationVisitor visitor) throws PrivateInformationException, SubscriptionConflictException, SubscriptionExpiredException {
String playerName = player.getName();
if (!player.getType().contains("a") && !_allowSpectators && !_playersPlaying.contains(playerName))
throw new WebApplicationException(Response.Status.FORBIDDEN);
throw new PrivateInformationException();
_readLock.lock();
try {
@@ -357,20 +358,20 @@ public class LotroGameMediator {
}
visitor.visitClock(secondsLeft);
} else {
visitor.visitGameEvent(new GameEvent(GameEvent.Type.W).message("You have joined this game in another window, please refresh your browser window (press F5) if you wish to continue playing in this window"));
throw new SubscriptionConflictException();
}
} else {
visitor.visitGameEvent(new GameEvent(GameEvent.Type.W).message("Your browser was inactive for too long, please refresh your browser window to continue playing"));
throw new SubscriptionExpiredException();
}
} finally {
_readLock.unlock();
}
}
public void singupUserForGame(Player player, ParticipantCommunicationVisitor visitor) {
public void singupUserForGame(Player player, ParticipantCommunicationVisitor visitor) throws PrivateInformationException {
String playerName = player.getName();
if (!player.getType().contains("a") && !_allowSpectators && !_playersPlaying.contains(playerName))
throw new WebApplicationException(Response.Status.FORBIDDEN);
throw new PrivateInformationException();
_readLock.lock();
try {

View File

@@ -1,6 +1,7 @@
package com.gempukku.lotro.game;
import com.gempukku.lotro.AbstractServer;
import com.gempukku.lotro.PrivateInformationException;
import com.gempukku.lotro.chat.ChatServer;
import com.gempukku.lotro.db.DeckDAO;
import com.gempukku.lotro.logic.timing.GameResultListener;
@@ -50,7 +51,11 @@ public class LotroServer extends AbstractServer {
String gameId = finishedGame.getKey();
if (currentTime > finishedGame.getValue().getTime() + _timeToGameDeathWarning
&& !_gameDeathWarningsSent.contains(gameId)) {
_chatServer.getChatRoom(getChatRoomName(gameId)).sendMessage("System", "This game is already finished and will be shortly removed, please move to the Game Hall", true);
try {
_chatServer.getChatRoom(getChatRoomName(gameId)).sendMessage("System", "This game is already finished and will be shortly removed, please move to the Game Hall", true);
} catch (PrivateInformationException exp) {
// Ignore, sent as admin
}
_gameDeathWarningsSent.add(gameId);
}
if (currentTime > finishedGame.getValue().getTime() + _timeToGameDeath) {

View File

@@ -1,7 +1,6 @@
package com.gempukku.lotro.hall;
import com.gempukku.lotro.AbstractServer;
import com.gempukku.lotro.DateUtils;
import com.gempukku.lotro.*;
import com.gempukku.lotro.chat.ChatRoomMediator;
import com.gempukku.lotro.chat.ChatServer;
import com.gempukku.lotro.collection.CollectionsManager;
@@ -16,8 +15,6 @@ import com.gempukku.lotro.logic.timing.GameResultListener;
import com.gempukku.lotro.logic.vo.LotroDeck;
import com.gempukku.lotro.tournament.*;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -289,7 +286,7 @@ public class HallServer extends AbstractServer {
}
}
public void processHall(Player player, int channelNumber, HallChannelVisitor hallChannelVisitor) {
public void processHall(Player player, int channelNumber, HallChannelVisitor hallChannelVisitor) throws SubscriptionExpiredException, SubscriptionConflictException {
_hallDataAccessLock.readLock().lock();
try {
HallCommunicationChannel communicationChannel = _playerChannelCommunication.get(player);
@@ -297,10 +294,10 @@ public class HallServer extends AbstractServer {
if (communicationChannel.getChannelNumber() == channelNumber) {
communicationChannel.processCommunicationChannel(this, player, hallChannelVisitor);
} else {
throw new WebApplicationException(Response.Status.CONFLICT);
throw new SubscriptionConflictException();
}
} else {
throw new WebApplicationException(Response.Status.GONE);
throw new SubscriptionExpiredException();
}
} finally {
_hallDataAccessLock.readLock().unlock();
@@ -641,7 +638,11 @@ public class HallServer extends AbstractServer {
@Override
public void broadcastMessage(String message) {
try {
_hallChat.sendMessage("TournamentSystem", message, true);
} catch (PrivateInformationException exp) {
// Ignore, sent as admin
}
}
}
}

View File

@@ -78,7 +78,4 @@ public abstract class AbstractResource {
return resourceOwner;
}
protected final void sendError(Response.Status status) throws WebApplicationException {
throw new WebApplicationException(status);
}
}

View File

@@ -336,14 +336,14 @@ public class AdminResource extends AbstractResource {
Player player = getResourceOwnerSafely(request, null);
if (!player.getType().contains("a"))
sendError(Response.Status.FORBIDDEN);
throw new WebApplicationException(Response.Status.FORBIDDEN);
}
private void validateLeagueAdmin(HttpServletRequest request) {
Player player = getResourceOwnerSafely(request, null);
if (!player.getType().contains("l"))
sendError(Response.Status.FORBIDDEN);
throw new WebApplicationException(Response.Status.FORBIDDEN);
}
private CollectionType createCollectionType(String collectionType) {

View File

@@ -1,9 +1,10 @@
package com.gempukku.lotro.server;
import com.gempukku.lotro.PrivateInformationException;
import com.gempukku.lotro.SubscriptionExpiredException;
import com.gempukku.lotro.chat.ChatMessage;
import com.gempukku.lotro.chat.ChatRoomMediator;
import com.gempukku.lotro.chat.ChatServer;
import com.gempukku.lotro.chat.UserUnsubscribedException;
import com.gempukku.lotro.game.Player;
import com.sun.jersey.spi.resource.Singleton;
import org.apache.commons.lang.StringEscapeUtils;
@@ -38,7 +39,7 @@ public class ChatResource extends AbstractResource {
ChatRoomMediator chatRoom = _chatServer.getChatRoom(room);
if (chatRoom == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
List<ChatMessage> chatMessages = chatRoom.joinUser(resourceOwner.getName());
Collection<String> usersInRoom = chatRoom.getUsersInRoom();
@@ -65,12 +66,16 @@ public class ChatResource extends AbstractResource {
ChatRoomMediator chatRoom = _chatServer.getChatRoom(room);
if (chatRoom == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
if (messages != null) {
for (String message : messages) {
if (message != null && message.trim().length() > 0)
chatRoom.sendMessage(resourceOwner.getName(), StringEscapeUtils.escapeHtml(message), resourceOwner.getType().contains("a"));
try {
for (String message : messages) {
if (message != null && message.trim().length() > 0)
chatRoom.sendMessage(resourceOwner.getName(), StringEscapeUtils.escapeHtml(message), resourceOwner.getType().contains("a"));
}
} catch (PrivateInformationException exp) {
throw new WebApplicationException(Response.Status.FORBIDDEN);
}
}
@@ -87,9 +92,8 @@ public class ChatResource extends AbstractResource {
serializeChatRoomData(room, chatMessages, usersInRoom, doc);
return doc;
} catch (UserUnsubscribedException exp) {
sendError(Response.Status.GONE);
return null;
} catch (SubscriptionExpiredException exp) {
throw new WebApplicationException(Response.Status.GONE);
}
}

View File

@@ -94,7 +94,7 @@ public class CollectionResource extends AbstractResource {
CardCollection collection = getCollection(resourceOwner, collectionType);
if (collection == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
Collection<CardCollection.Item> items = collection.getAll().values();
List<CardCollection.Item> filteredResult = _sortAndFilterCards.process(filter, items, _library, _formatLibrary, _rarities);
@@ -215,7 +215,7 @@ public class CollectionResource extends AbstractResource {
CardCollection packContents = _collectionsManager.openPackInPlayerCollection(resourceOwner, collectionTypeObj, selection, _packStorage, packId);
if (packContents == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

View File

@@ -101,7 +101,7 @@ public class DeckResource extends AbstractResource {
LotroDeck deck = _deckDao.getDeckForPlayer(resourceOwner, deckName);
if (deck == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
StringBuilder result = new StringBuilder();
result.append("<html><body>");
@@ -152,7 +152,7 @@ public class DeckResource extends AbstractResource {
LotroDeck lotroDeck = _lotroServer.createDeckWithValidate(deckName, contents);
if (lotroDeck == null)
sendError(Response.Status.BAD_REQUEST);
throw new WebApplicationException(Response.Status.BAD_REQUEST);
_deckDao.saveDeckForPlayer(resourceOwner, deckName, lotroDeck);
@@ -178,7 +178,7 @@ public class DeckResource extends AbstractResource {
LotroDeck deck = _deckDao.renameDeck(resourceOwner, oldDeckName, deckName);
if (deck == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
return serializeDeck(deck);
}
@@ -205,7 +205,7 @@ public class DeckResource extends AbstractResource {
LotroDeck deck = _lotroServer.createDeckWithValidate("tempDeck", contents);
if (deck == null)
sendError(Response.Status.BAD_REQUEST);
throw new WebApplicationException(Response.Status.BAD_REQUEST);
int fpCount = 0;
int shadowCount = 0;

View File

@@ -1,5 +1,8 @@
package com.gempukku.lotro.server;
import com.gempukku.lotro.PrivateInformationException;
import com.gempukku.lotro.SubscriptionConflictException;
import com.gempukku.lotro.SubscriptionExpiredException;
import com.gempukku.lotro.common.Phase;
import com.gempukku.lotro.game.LotroGameMediator;
import com.gempukku.lotro.game.LotroServer;
@@ -56,7 +59,7 @@ public class GameResource extends AbstractResource {
LotroGameMediator gameMediator = _lotroServer.getGameById(gameId);
if (gameMediator == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
gameMediator.setPlayerAutoPassSettings(resourceOwner.getName(), getAutoPassPhases(request));
@@ -65,7 +68,11 @@ public class GameResource extends AbstractResource {
Document doc = documentBuilder.newDocument();
Element gameState = doc.createElement("gameState");
gameMediator.singupUserForGame(resourceOwner, new SerializationVisitor(doc, gameState));
try {
gameMediator.singupUserForGame(resourceOwner, new SerializationVisitor(doc, gameState));
} catch (PrivateInformationException e) {
throw new WebApplicationException(Response.Status.FORBIDDEN);
}
doc.appendChild(gameState);
return doc;
@@ -100,7 +107,7 @@ public class GameResource extends AbstractResource {
LotroGameMediator gameMediator = _lotroServer.getGameById(gameId);
if (gameMediator == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
return gameMediator.produceCardInfo(resourceOwner, cardId);
}
@@ -115,7 +122,7 @@ public class GameResource extends AbstractResource {
LotroGameMediator gameMediator = _lotroServer.getGameById(gameId);
if (gameMediator == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
gameMediator.concede(resourceOwner);
}
@@ -130,7 +137,7 @@ public class GameResource extends AbstractResource {
LotroGameMediator gameMediator = _lotroServer.getGameById(gameId);
if (gameMediator == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
gameMediator.cancel(resourceOwner);
}
@@ -152,7 +159,7 @@ public class GameResource extends AbstractResource {
try {
LotroGameMediator gameMediator = _lotroServer.getGameById(gameId);
if (gameMediator == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
gameMediator.setPlayerAutoPassSettings(resourceOwner.getName(), getAutoPassPhases(request));
@@ -172,6 +179,12 @@ public class GameResource extends AbstractResource {
processDeliveryServiceNotification(request, response);
return doc;
} catch (SubscriptionConflictException exp) {
throw new WebApplicationException(Response.Status.CONFLICT);
} catch (PrivateInformationException e) {
throw new WebApplicationException(Response.Status.FORBIDDEN);
} catch (SubscriptionExpiredException e) {
throw new WebApplicationException(Response.Status.GONE);
} finally {
LoggingThreadLocal.stop(decisionId != null);
}

View File

@@ -1,5 +1,7 @@
package com.gempukku.lotro.server;
import com.gempukku.lotro.SubscriptionConflictException;
import com.gempukku.lotro.SubscriptionExpiredException;
import com.gempukku.lotro.db.vo.League;
import com.gempukku.lotro.game.LotroCardBlueprintLibrary;
import com.gempukku.lotro.game.LotroFormat;
@@ -20,6 +22,7 @@ import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -129,7 +132,7 @@ public class HallResource extends AbstractResource {
@FormParam("participantId") String participantId,
@FormParam("channelNumber") int channelNumber,
@Context HttpServletRequest request,
@Context HttpServletResponse response) throws ParserConfigurationException, Exception {
@Context HttpServletResponse response) throws ParserConfigurationException {
Player resourceOwner = getResourceOwnerSafely(request, participantId);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
@@ -140,7 +143,13 @@ public class HallResource extends AbstractResource {
Element hall = doc.createElement("hall");
hall.setAttribute("currency", String.valueOf(_collectionManager.getPlayerCollection(resourceOwner, "permanent").getCurrency()));
_hallServer.processHall(resourceOwner, channelNumber, new SerializeHallInfoVisitor(doc, hall));
try {
_hallServer.processHall(resourceOwner, channelNumber, new SerializeHallInfoVisitor(doc, hall));
} catch (SubscriptionExpiredException exp) {
throw new WebApplicationException(Response.Status.GONE);
} catch (SubscriptionConflictException exp) {
throw new WebApplicationException(Response.Status.CONFLICT);
}
doc.appendChild(hall);

View File

@@ -44,10 +44,10 @@ public class LeagueResource extends AbstractResource {
League league = _leagueService.getLeagueByType(leagueType);
if (league == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
if (!_leagueService.playerJoinsLeague(league, resourceOwner, request.getRemoteAddr()))
sendError(Response.Status.CONFLICT);
throw new WebApplicationException(Response.Status.CONFLICT);
}
@GET
@@ -100,7 +100,7 @@ public class LeagueResource extends AbstractResource {
League league = getLeagueByType(leagueType);
if (league == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
final LeagueData leagueData = league.getLeagueData();
final List<LeagueSerieData> series = leagueData.getSeries();

View File

@@ -109,13 +109,13 @@ public class ServerResource extends AbstractResource {
public StreamingOutput getReplay(
@PathParam("replayId") String replayId) throws ParserConfigurationException {
if (!replayId.contains("$"))
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
if (replayId.contains("."))
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
final String[] split = replayId.split("\\$");
if (split.length != 2)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
return new StreamingOutput() {
@Override
@@ -144,7 +144,7 @@ public class ServerResource extends AbstractResource {
@QueryParam("participantId") String participantId,
@Context HttpServletRequest request) throws ParserConfigurationException {
if (start < 0 || count < 1 || count > 100)
sendError(Response.Status.BAD_REQUEST);
throw new WebApplicationException(Response.Status.BAD_REQUEST);
Player resourceOwner = getResourceOwnerSafely(request, participantId);
@@ -234,7 +234,7 @@ public class ServerResource extends AbstractResource {
else if (length.equals("day"))
to.setDate(to.getDate() + 1);
else
sendError(Response.Status.BAD_REQUEST);
throw new WebApplicationException(Response.Status.BAD_REQUEST);
long duration = to.getTime() - from;
int activePlayers = _gameHistoryService.getActivePlayersCount(from, duration);
@@ -263,8 +263,7 @@ public class ServerResource extends AbstractResource {
doc.appendChild(stats);
return doc;
} catch (ParseException exp) {
sendError(Response.Status.BAD_REQUEST);
return null;
throw new WebApplicationException(Response.Status.BAD_REQUEST);
}
}

View File

@@ -113,7 +113,7 @@ public class TournamentResource extends AbstractResource {
Tournament tournament = _tournamentService.getTournamentById(tournamentId);
if (tournament == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
Element tournamentElem = doc.createElement("tournament");
@@ -148,14 +148,14 @@ public class TournamentResource extends AbstractResource {
Tournament tournament = _tournamentService.getTournamentById(tournamentId);
if (tournament == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
if (tournament.getTournamentStage() != Tournament.Stage.FINISHED)
sendError(Response.Status.FORBIDDEN);
throw new WebApplicationException(Response.Status.FORBIDDEN);
LotroDeck deck = _tournamentService.getPlayerDeck(tournamentId, playerName);
if (deck == null)
sendError(Response.Status.NOT_FOUND);
throw new WebApplicationException(Response.Status.NOT_FOUND);
StringBuilder result = new StringBuilder();
result.append("<html><body>");