/***************************************************************************
   Copyright 2012 Emily Estes

   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.metanotion.web.examples;


import net.metanotion.io.JavaFileSystem;

import net.metanotion.simpletemplate.ResourceFactory;
import net.metanotion.simpletemplate.StaticResources;

import net.metanotion.util.Unknown;
import net.metanotion.web.Default;
import net.metanotion.web.RequestObject;
import net.metanotion.web.SessionFactory;
import net.metanotion.web.concrete.BasicRequestObject;
import net.metanotion.web.concrete.DefaultDispatcher;
import net.metanotion.web.servlets.ServerUtil;

/** <p>This example doesn't add any new functionality over the {@link net.metanotion.web.examples.FileServerApp}
example, however instead of implementing {@link net.metanotion.web.SessionHandler}, this app implements
{@link net.metanotion.web.SessionFactory}. A SessionFactory instance is asked for on every HTTP Request that doesn't
have a cached session. Session instances are cached by whatever mechanism/strategy the
{@link net.metanotion.web.SessionStore} implementation uses. The default implementation uses Session cookies (provided
by the Servlet API) to cache it's session object instances.</p>

<p>Of course, sessions can differentiate between users, so we could add authentication to this example and have a file
server that requires users to log in and only serve up files that specific user has access to. Or whatever else we
might do with sessions. Also, note that since you control the session object, you control what instance variables are
associated with the session, and so on.</p>
*/
public final class FileServerSessionsApp implements SessionFactory<RequestObject> {
	/** This is the main method to start this application server instance.
		@param args The command line arguments, however, this application only takes one: The path to read files from
			to respond to HTTP requests.
	*/
	public static void main(final String[] args) {
		try {
			/** We need to represent our folder as a file system for the static file server component. */
			final JavaFileSystem files = new JavaFileSystem(args[0]);
			/** The "default server" is an implementation of the "Default" component that uses a ResourceFactory. */
			final ResourceFactory resources = new StaticResources(files);
			ServerUtil.launchJettyServer(8080, new DefaultDispatcher(), new FileServerSessionsApp(resources));
		} catch (final Exception e) {
			e.printStackTrace();
		}
	}

	/** The application wide resource factory. */
	private final ResourceFactory resources;
	/** Create the SessionFactory instance for our application to respond to HTTP requests.
		@param resources The resource factory to load the files this server is hosting.
	*/
	public FileServerSessionsApp(final ResourceFactory resources) { this.resources = resources; }

	@Override public Unknown newSession(final RequestObject ro) {
		return new Session(resources);
	}

	/** This is the session object that represents all session state. One instance is create per session. */
	private static final class Session implements Unknown, Default {
		private final ResourceFactory resources;
		public Session(final ResourceFactory resources) { this.resources = resources; }
		@Override public Object lookupInterface(Class theInterface) { return this; }
		@Override public Object get(String url) {
			return this.resources.get(url).skin(null, new BasicRequestObject());
		}
	}
}
