/**
* Copyright 2010 Marko Lavikainen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.contextfw.web.application.internal.service;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.contextfw.web.application.ResourceCleaner;
import net.contextfw.web.application.WebApplicationException;
import net.contextfw.web.application.component.Component;
import net.contextfw.web.application.configuration.Configuration;
import net.contextfw.web.application.internal.component.MetaComponentException;
import net.contextfw.web.application.internal.development.InternalDevelopmentTools;
import net.contextfw.web.application.internal.page.PageScope;
import net.contextfw.web.application.internal.page.WebApplicationPage;
import net.contextfw.web.application.internal.servlet.UriMapping;
import net.contextfw.web.application.lifecycle.LifecycleListener;
import net.contextfw.web.application.remote.ErrorResolution;
import net.contextfw.web.application.scope.ScopedWebApplicationExecution;
import net.contextfw.web.application.scope.WebApplicationStorage;
import org.apache.commons.lang.mutable.MutableBoolean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.google.inject.Provider;
public class InitHandler {
private Logger logger = LoggerFactory.getLogger(InitHandler.class);
private static final long HOUR = 1000 * 60 * 3600;
@Inject
private Provider<WebApplication> webApplicationProvider;
@Inject
private LifecycleListener listeners;
private PageScope pageScope;
@Inject
private WebApplicationStorage storage;
private final long initialMaxInactivity;
private DirectoryWatcher watcher;
private ResourceCleaner cleaner;
private final boolean developmentMode;
private final InternalDevelopmentTools internalDevelopmentTools;
public InitHandler(Configuration properties,
PageScope pageScope,
InternalDevelopmentTools internalDevelopmentTools) {
initialMaxInactivity = properties.get(Configuration.INITIAL_MAX_INACTIVITY);
developmentMode = properties.get(Configuration.DEVELOPMENT_MODE);
this.pageScope = pageScope;
this.internalDevelopmentTools = internalDevelopmentTools;
}
public final void handleRequest(
final UriMapping mapping,
final List<Class<? extends Component>> chain,
final HttpServlet servlet,
final HttpServletRequest request,
final HttpServletResponse response)
throws ServletException, IOException {
if (watcher != null && watcher.hasChanged()) {
logger.debug("Reloading resources");
cleaner.clean();
internalDevelopmentTools.reloadResources();
}
response.addHeader("Expires", "Sun, 19 Nov 1978 05:00:00 GMT");
response.addHeader("Last-Modified", new Date().toString());
response.addHeader("Cache-Control", "no-store, no-cache, must-revalidate");
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
response.addHeader("Pragma", "no-cache");
if (chain == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
} else {
WebApplicationPage page = pageScope.createPage(servlet, request, response);
final MutableBoolean expired = new MutableBoolean(false);
storage.initialize(
page,
request,
System.currentTimeMillis() + HOUR,
new ScopedWebApplicationExecution() {
@Override
public void execute(net.contextfw.web.application.WebApplication application) {
try {
WebApplicationPage page = (WebApplicationPage) application;
WebApplication app = webApplicationProvider.get();
app.setInitializerChain(chain);
page.setWebApplication(app);
listeners.beforeInitialize();
page.getWebApplication().initState(mapping);
listeners.afterInitialize();
listeners.beforeRender();
expired.setValue(page.getWebApplication().sendResponse());
listeners.afterRender();
} catch (Exception e) {
// TODO Fix this construct with test
if (e instanceof MetaComponentException) {
ErrorResolution resolution =
((MetaComponentException) e).getResolution();
try {
if (resolution == ErrorResolution.SEND_NOT_FOUND_ERROR) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
} else if (resolution == ErrorResolution.SEND_BAD_REQUEST_ERROR) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
}
} catch (IOException e1) {
throw new WebApplicationException(e1);
}
}
listeners.onException(e);
} finally {
pageScope.deactivateCurrentPage();
}
}
});
// Setting expiration here so that long page
// processing is
// not
// penalizing client
if (expired.booleanValue()) {
storage.remove(page.getHandle(), request);
} else {
storage.refresh(
page.getHandle(),
request,
System.currentTimeMillis() + initialMaxInactivity);
}
}
}
@Inject
public void setWatcher(DirectoryWatcher watcher) {
if (developmentMode) {
this.watcher = watcher;
}
}
@Inject
public void setCleaner(ResourceCleaner cleaner) {
if (developmentMode) {
this.cleaner = cleaner;
}
}
public void setPageScope(PageScope pageScope) {
this.pageScope = pageScope;
}
}