![JAR search and dependency download from the Maven repository](/logo.png)
net.officefloor.web.state.HttpRequestStateManagedObjectSource Maven / Gradle / Ivy
/*
* OfficeFloor - http://www.officefloor.net
* Copyright (C) 2005-2018 Daniel Sagenschneider
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package net.officefloor.web.state;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.officefloor.frame.api.build.None;
import net.officefloor.frame.api.managedobject.CoordinatingManagedObject;
import net.officefloor.frame.api.managedobject.ManagedObject;
import net.officefloor.frame.api.managedobject.ObjectRegistry;
import net.officefloor.frame.api.managedobject.ProcessAwareContext;
import net.officefloor.frame.api.managedobject.ProcessAwareManagedObject;
import net.officefloor.frame.api.managedobject.source.ManagedObjectSource;
import net.officefloor.frame.api.managedobject.source.impl.AbstractManagedObjectSource;
import net.officefloor.frame.api.source.PrivateSource;
import net.officefloor.server.http.HttpException;
import net.officefloor.server.http.HttpRequest;
import net.officefloor.server.http.HttpRequestCookie;
import net.officefloor.server.http.ServerHttpConnection;
import net.officefloor.web.build.HttpArgumentParser;
import net.officefloor.web.build.HttpValueLocation;
import net.officefloor.web.tokenise.HttpRequestTokeniser;
import net.officefloor.web.value.load.ValueLoader;
/**
* {@link ManagedObjectSource} for the {@link HttpRequestState}.
*
* @author Daniel Sagenschneider
*/
@PrivateSource
public class HttpRequestStateManagedObjectSource
extends AbstractManagedObjectSource {
/**
* Dependency keys.
*/
public static enum HttpRequestStateDependencies {
SERVER_HTTP_CONNECTION
}
/**
* Initialises the {@link HttpRequestState}.
*
* @param pathArguments Head path {@link HttpArgument} of the linked list of
* {@link HttpArgument} instances.
* @param requestState {@link HttpRequestState}.
*/
public static void initialiseHttpRequestState(HttpArgument pathArguments, HttpRequestState requestState) {
HttpRequestStateManagedObject mo = (HttpRequestStateManagedObject) requestState;
mo.initialise(pathArguments);
}
/**
* Imports the state from the momento.
*
* @param momento Momento containing the state for the
* {@link HttpRequestState}.
* @param requestState {@link HttpRequestState}
* @throws IllegalArgumentException If invalid momento.
*/
public static void importHttpRequestState(Serializable momento, HttpRequestState requestState)
throws IllegalArgumentException {
// Ensure valid state momento
if (!(momento instanceof StateMomento)) {
throw new IllegalArgumentException("Invalid momento for " + HttpRequestState.class.getSimpleName());
}
StateMomento state = (StateMomento) momento;
HttpRequestStateManagedObject mo = (HttpRequestStateManagedObject) requestState;
mo.context.run(() -> {
// Load the arguments
mo.arguments = state.headArgument;
mo.isTokenisedRequest = true;
// Load the state
mo.attributes = new HashMap(state.attributes);
// Void return
return null;
});
}
/**
* Exports a momento for the current state of this {@link HttpRequestState}.
*
* @param requestState {@link HttpRequestState}.
* @return Momento for the current state of this {@link HttpRequestState}.
*/
public static Serializable exportHttpRequestState(HttpRequestState requestState) {
HttpRequestStateManagedObject mo = (HttpRequestStateManagedObject) requestState;
return mo.context.run(() -> {
// Obtain the arguments
mo.ensureTokenised();
HttpArgument headArgument = mo.arguments;
// Create the momento state
Map momentoAttributes = new HashMap(mo.attributes);
// Create and return the momento
return new StateMomento(headArgument, momentoAttributes);
});
}
/**
* {@link HttpArgumentParser} instances.
*/
private final HttpArgumentParser[] argumentParsers;
/**
* Instantiate.
*
* @param argumentParsers {@link HttpArgumentParser} instances.
*/
public HttpRequestStateManagedObjectSource(HttpArgumentParser[] argumentParsers) {
this.argumentParsers = argumentParsers;
}
/*
* =================== ManagedObjectSource ==========================
*/
@Override
protected void loadSpecification(SpecificationContext context) {
// No properties required
}
@Override
protected void loadMetaData(MetaDataContext context) throws Exception {
context.setObjectClass(HttpRequestState.class);
context.setManagedObjectClass(HttpRequestStateManagedObject.class);
context.addDependency(HttpRequestStateDependencies.SERVER_HTTP_CONNECTION, ServerHttpConnection.class);
}
@Override
protected ManagedObject getManagedObject() throws Throwable {
return new HttpRequestStateManagedObject();
}
/**
* {@link ManagedObject} for the {@link HttpRequestState}.
*/
private class HttpRequestStateManagedObject implements ProcessAwareManagedObject,
CoordinatingManagedObject, HttpRequestState, ValueLoader {
/**
* {@link ProcessAwareContext}.
*/
private ProcessAwareContext context;
/**
* {@link ServerHttpConnection}.
*/
private ServerHttpConnection connection;
/**
* Head {@link HttpArgument} of the linked list of {@link HttpArgument}
* instances.
*/
private HttpArgument arguments = null;
/**
* Indicates if tokenised the {@link HttpRequest}.
*/
private boolean isTokenisedRequest = false;
/**
* Attributes.
*/
private Map attributes = new HashMap();
/**
* Initialises this {@link HttpRequestState}.
*
* @param pathArguments Head path {@link HttpArgument} of the linked list of
* {@link HttpArgument} instances.
*/
private void initialise(HttpArgument pathArguments) {
this.context.run(() -> {
this.arguments = pathArguments;
return null;
});
}
/**
* Ensures the {@link HttpRequest} has been tokenized.
*
* @return {@link HttpRequest}.
*/
private HttpRequest ensureTokenised() {
HttpRequest request = this.connection.getRequest();
if (!this.isTokenisedRequest) {
// Tokenise out the arguments
HttpRequestTokeniser.tokeniseHttpRequest(request,
HttpRequestStateManagedObjectSource.this.argumentParsers, this);
// Request now tokenised
this.isTokenisedRequest = true;
}
return request;
}
/*
* ====================== ManagedObject ===========================
*/
@Override
public void setProcessAwareContext(ProcessAwareContext context) {
this.context = context;
}
@Override
public void loadObjects(ObjectRegistry registry) throws Throwable {
this.connection = (ServerHttpConnection) registry
.getObject(HttpRequestStateDependencies.SERVER_HTTP_CONNECTION);
}
@Override
public Object getObject() throws Throwable {
return this;
}
/*
* ===================== ValueLoader =========================
*/
@Override
public void loadValue(String name, String value, HttpValueLocation location) throws HttpException {
HttpArgument oldHead = this.arguments;
this.arguments = new HttpArgument(name, value, location);
this.arguments.next = oldHead;
}
/*
* ==================== HttpRequestState ==========================
*/
@Override
public void loadValues(ValueLoader valueLoader) throws HttpException {
this.context.run(() -> {
// Tokenise the HTTP request
HttpRequest request = this.ensureTokenised();
// Load the arguments
HttpArgument argument = this.arguments;
while (argument != null) {
valueLoader.loadValue(argument.name, argument.value, argument.location);
argument = argument.next;
}
// Always load cookies from request
for (HttpRequestCookie cookie : request.getCookies()) {
valueLoader.loadValue(cookie.getName(), cookie.getValue(), HttpValueLocation.COOKIE);
}
// Void return
return null;
});
}
@Override
public Serializable getAttribute(String name) {
return this.context.run(() -> this.attributes.get(name));
}
@Override
public Iterator getAttributeNames() {
return this.context.run(() -> {
// Create copy of names (stops concurrency issues)
List names = new ArrayList(this.attributes.keySet());
return names.iterator();
});
}
@Override
public void setAttribute(String name, Serializable object) {
this.context.run(() -> this.attributes.put(name, object));
}
@Override
public void removeAttribute(String name) {
this.context.run(() -> this.attributes.remove(name));
}
}
/**
* State momento.
*/
private static class StateMomento implements Serializable {
/**
* {@link Serializable} version.
*/
private static final long serialVersionUID = 1L;
/**
* Head {@link HttpArgument}.
*/
private final HttpArgument headArgument;
/**
* Attributes.
*/
private final Map attributes;
/**
* Initiate.
*
* @param headArgument Head {@link HttpArgument}.
* @param attributes Attributes.
*/
public StateMomento(HttpArgument headArgument, Map attributes) {
this.headArgument = headArgument;
this.attributes = attributes;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy