/*
* Copyright 2013 Simon Taddiken
*
* This file is part of Polly HTTP API.
*
* Polly HTTP API is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Polly HTTP API is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with Polly HTTP API. If not, see http://www.gnu.org/licenses/.
*/
package de.skuzzle.polly.http.internal;
import java.net.InetSocketAddress;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang.StringEscapeUtils;
import de.skuzzle.polly.http.api.HttpEvent;
import de.skuzzle.polly.http.api.HttpServer;
import de.skuzzle.polly.http.api.HttpSession;
class HttpEventImpl implements HttpEvent {
private final transient HttpServer source;
private final URI requestUri;
private final String plainUri;
private final String requestBody;
private final InetSocketAddress clientIp;
private final HttpSession session;
private final Map<String, String> cookies;
private final Map<String, String> get;
private final Map<String, String> post;
private final RequestMode mode;
private Map<String, String> combinedParameters;
private Map<String, String> postGet;
private final Date creationTime;
private final List<Listener> closeListener;
private boolean discarded;
public HttpEventImpl(HttpServer source, RequestMode mode, URI requestURI,
InetSocketAddress remoteAddress,
String plainUri, HttpSession session, Map<String, String> cookies,
Map<String, String> get, Map<String, String> post, String requestBody) {
this.source = source;
this.mode = mode;
this.requestUri = requestURI;
this.plainUri = plainUri;
this.clientIp = remoteAddress;
this.session = session;
this.requestBody = requestBody;
this.cookies = Collections.unmodifiableMap(cookies);
this.get = Collections.unmodifiableMap(get);
this.post = Collections.unmodifiableMap(post);
this.closeListener = new ArrayList<>();
this.creationTime = new Date();
}
public HttpEventImpl copy() {
return new HttpEventImpl(this.source, this.mode, this.requestUri, this.clientIp,
this.plainUri, null, this.cookies, this.get, this.post, this.requestBody);
}
public String getRequestBody() {
return this.requestBody;
}
@Override
public Date getEventTime() {
return this.creationTime;
}
@Override
public HttpServer getSource() {
return this.source;
}
@Override
public RequestMode getMode() {
return this.mode;
}
@Override
public URI getRequestURI() {
return this.requestUri;
}
@Override
public String getPlainUri() {
return this.plainUri;
}
@Override
public InetSocketAddress getClientIP() {
return this.clientIp;
}
@Override
public String get(String key) {
return this.get.get(key);
}
@Override
public String getEscaped(String key) {
return StringEscapeUtils.escapeHtml(this.get.get(key));
}
@Override
public String post(String key) {
return this.post.get(key);
}
@Override
public String postEscaped(String key) {
return StringEscapeUtils.escapeHtml(this.post.get(key));
}
@Override
public Map<String, String> parameterMap() {
synchronized (this) {
if (this.combinedParameters == null) {
this.combinedParameters = new HashMap<>(this.get.size() + this.post.size() +
this.cookies.size());
this.combinedParameters.putAll(this.cookies);
join(this.combinedParameters, this.get);
join(this.combinedParameters, this.post);
this.combinedParameters = Collections.unmodifiableMap(
this.combinedParameters);
}
return this.combinedParameters;
}
}
@Override
public Map<String, String> parameterMap(RequestMode mode) {
switch (mode) {
case GET: return this.getMap();
case POST: return this.postMap();
default:
throw new IllegalStateException("unknown mode");
}
}
@Override
public Map<String, String> postGetMap() {
synchronized (this) {
if (this.postGet == null) {
this.postGet = new HashMap<>(this.get.size() + this.post.size());
this.postGet.putAll(this.get);
join(this.postGet, this.post);
this.postGet = Collections.unmodifiableMap(
this.postGet);
}
return this.postGet;
}
}
private final static void join(Map<String, String> target,
Map<String, String> source) {
for (final Entry<String, String> se : source.entrySet()) {
String targetValue = target.get(se.getKey());
if (targetValue != null && !targetValue.contains(se.getValue())) {
targetValue = targetValue + ";" + se.getValue();
} else {
targetValue = se.getValue();
}
target.put(se.getKey(), targetValue);
}
}
@Override
public Map<String, String> postMap() {
return this.post;
}
@Override
public Map<String, String> getMap() {
return this.get;
}
@Override
public HttpSession getSession() {
return this.session;
}
@Override
public void onClose(Listener listener) {
this.closeListener.add(listener);
}
public void discard() {
// note: this method is implemented anonymously in BasicEventHandler
this.discarded = true;
}
@Override
public boolean isDiscarded() {
return this.discarded;
}
void fireOnClose() {
for (final Listener listener : this.closeListener) {
listener.action(this);
}
}
}