/*
* $Id: Zone.java,v 1.55 2002/09/16 08:05:06 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.server;
import java.io.File;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.HashMap;
import java.net.URL;
import java.net.MalformedURLException;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.security.Permission;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.PatternMatcherInput;
import org.apache.oro.text.regex.Perl5Pattern;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import org.apache.oro.text.regex.MalformedPatternException;
import anvil.Log;
import anvil.ForgingException;
import anvil.core.Modules;
import anvil.core.ObjectPool;
import anvil.core.reflect.Reflection;
import anvil.database.NoConnectionPoolException;
import anvil.database.CannotReturnPooledConnectionException;
import anvil.database.ConnectionManager;
import anvil.database.PooledConnection;
import anvil.database.ConnectionPool;
import anvil.session.Session;
import anvil.session.SessionContainer;
import anvil.server.listener.Listener;
import anvil.script.ModuleEnvelope;
import anvil.script.ScriptException;
import anvil.script.statements.Statement;
import anvil.java.util.Hashlist;
import anvil.java.security.PermissionCollectionCombiner;
/**
* class Zone
*
* @author: Jani Lehtim�ki
*/
public class Zone implements Configurable
{
public static final String[] PREFERENCES = {
"path", "string",
"pattern", "string",
"container", "string",
"dispatcher", "string",
"index", "string",
"namespace", "string",
"content", "preserve;compress;pack;silent",
"repositories", "string",
"hidden", "boolean",
"invalidate", "boolean",
"pretty", "boolean",
"assert", "boolean",
"debug", "boolean",
};
protected boolean _started = false;
protected Zone _parent = null;
protected Zone[] _childs = new Zone[0];
protected String _container = null;
protected String _dispatcher = null;
protected String _pathinfo = null;
protected Pattern _pattern = null;
protected String _index = null;
protected String _namespace = null;
protected int _content = -1;
protected String _repositories = null;
protected Boolean _hidden = null;
protected Boolean _invalidate = null;
protected Boolean _pretty = null;
protected Boolean _assert = null;
protected Boolean _debug = null;
protected LoggingPreferences _loggingprefs = null;
protected ListenerPreferences _listenerprefs = null;
protected AccessPreferences _accessprefs = null;
protected SessionPreferences _sessionprefs = null;
protected SessionContainerPreferences _sessioncontainerprefs = null;
protected LocalizationPreferences _localizationprefs = null;
protected CompilerPreferences _compilerprefs = null;
protected ModulePreferences _moduleprefs = null;
protected BindPreferences _bindprefs = null;
protected HandlerPreferences _handlerprefs = null;
protected ApplicationPreferences _applicationprefs = null;
protected PolicyPreferences _policyprefs = null;
protected ArrayList _namespacesprefs = new ArrayList();
protected ArrayList _realmprefs = new ArrayList();
protected ArrayList _pools = new ArrayList();
protected Address _address = null;
protected Container _thecontainer = null;
protected Log _log = null;
protected Listener _listener = null;
protected ConnectionManager _manager = null;
protected SessionContainer _sessioncontainer = null;
protected Modules _modules = null;
protected Authorization _auth = null;
protected HashMap _namespaces = new HashMap();
protected HashMap _realms = new HashMap();
protected ZoneClassLoader _classloader = null;
protected PermissionCollection _combinedpermissions = null;
protected boolean _combinedpermissionscreated = false;
public Zone(Zone parent)
{
_parent = parent;
_pathinfo = "";
}
public String toString()
{
return getPath();
}
public Address getAddress()
{
if (_address == null) {
_address = new Address(this, getDomain().getHostname(), getPathinfo());
}
return _address;
}
public Server getServer()
{
return _parent.getServer();
}
public RequestAdapterFactory getAdapterFactory()
{
return _parent.getAdapterFactory();
}
public ConnectionManager getManager()
{
return _manager;
}
public PooledConnection acquireConnection(String name)
throws NoConnectionPoolException, CannotReturnPooledConnectionException
{
if (_manager != null) {
if (_manager.hasPool(name)) {
return _manager.acquire(name);
}
}
if (_parent != null) {
return _parent.acquireConnection(name);
}
throw new anvil.database.CannotReturnPooledConnectionException("There are no pools with name '"+name+"'");
}
public ConnectionManager getManagerFor(String name) throws NoConnectionPoolException
{
if (_manager != null) {
if (_manager.hasPool(name)) {
return _manager;
}
}
if (_parent != null) {
return _parent.getManagerFor(name);
}
throw new anvil.database.NoConnectionPoolException();
}
public SessionContainer getSessionContainer()
{
if (_sessioncontainer != null) {
return _sessioncontainer;
} else {
if (_parent != null) {
return _parent.getSessionContainer();
}
}
return null;
}
public Realm getRealm(String name)
{
Realm realm = (Realm)_realms.get(name);
if (realm != null) {
return realm;
}
if (_parent != null) {
return _parent.getRealm(name);
}
return null;
}
public Authorization getAuthorization()
{
if (_auth != null) {
return _auth;
} else {
if (_parent != null) {
return _parent.getAuthorization();
}
}
return NoAuthorization.INSTANCE;
}
public PersistentNamespace getNamespace(String name)
{
PersistentNamespace ns = (PersistentNamespace)_namespaces.get(name);
if (ns != null) {
return ns;
} else {
if (_parent != null) {
return _parent.getNamespace(name);
}
}
return null;
}
public Reflection findJava(String classname)
{
if (classname.startsWith("anvil.") ||
classname.startsWith(anvil.Version.getBuild())) {
return null;
}
ClassLoader loader = getClassLoader();
try {
Class cls = loader.loadClass(classname);
if (cls != null) {
return ObjectPool.createReflection(cls);
}
} catch (LinkageError e) {
log().error("While trying to reflect: "+classname, e);
} catch (Throwable t) {
}
return null;
}
public ZoneClassLoader getClassLoader()
{
if (_classloader != null) {
return _classloader;
} else {
if (_parent != null) {
return _parent.getClassLoader();
}
}
return null;
}
protected PermissionCollection getLocalPermissions()
{
if (_policyprefs != null) {
return _policyprefs.getLocalPermissions();
}
return null;
}
protected PermissionCollection getPermissions()
{
if (_policyprefs != null) {
return _policyprefs.getPermissions();
}
return null;
}
protected PermissionCollection getCombinedPermissions()
{
if (_combinedpermissionscreated) {
return _combinedpermissions;
}
synchronized(this) {
PermissionCollectionCombiner combiner = new PermissionCollectionCombiner();
Zone zone = this;
combiner.combine(zone.getLocalPermissions());
while(zone != null) {
combiner.combine(zone.getPermissions());
zone = zone._parent;
}
_combinedpermissionscreated = true;
return _combinedpermissions = combiner.getResult();
}
}
public final boolean checkPermission(Permission perm)
{
PermissionCollection perms = getCombinedPermissions();
if (perms != null) {
if (perms.implies(perm)) {
return true;
}
}
return false;
}
public Zone getParent()
{
return _parent;
}
public void setParent(Zone parent)
{
_parent = parent;
}
public Domain getDomain()
{
return _parent.getDomain();
}
public String getHostname()
{
Domain domain = getDomain();
if (domain != null) {
return domain.getHostname();
} else {
return "";
}
}
public Pattern getPattern()
{
return _pattern;
}
public Zone[] getChilds()
{
return _childs;
}
public Log log()
{
if (_log != null) {
return _log;
} else {
if (_parent != null) {
return _parent.log();
} else {
return Log.log();
}
}
}
public void setContainer(String container)
{
if (container == null || container.length() == 1) {
_container = null;
_thecontainer = null;
} else {
if (!container.endsWith("/")) {
container = container + '/';
}
_container = container;
_thecontainer = createContainer(container);
}
}
protected Container createContainer(String container)
{
URL url;
try {
url = new URL(container);
} catch (MalformedURLException e) {
return new DirContainer(new File(container));
}
if (url.getProtocol().equals("file")) {
return new DirContainer(new File(url.getFile()));
}
return new URLContainer(url);
}
public Container getContainer()
{
if (_thecontainer != null) {
return _thecontainer;
} else {
return _parent.getContainer();
}
}
public String getDispatcher()
{
if (_dispatcher != null) {
if (_dispatcher.length() == 0) {
return null;
} else {
return _dispatcher;
}
} else {
return _parent.getDispatcher();
}
}
public Zone getDispatcherZone()
{
if (_dispatcher == null) {
return _parent.getDispatcherZone();
}
return this;
}
public void setDispatcher(String dispatcher)
{
_dispatcher = dispatcher;
}
public void setPathinfo(String pathinfo)
{
if (pathinfo == null) {
_pathinfo = null;
} else {
if (pathinfo.equals("/")) {
_pathinfo = "";
} else {
if (pathinfo.startsWith("/")) {
pathinfo = pathinfo.substring(1);
}
if (!pathinfo.endsWith("/")) {
pathinfo = pathinfo + "/";
}
_pathinfo = pathinfo;
}
}
}
public void setPattern(String pattern)
{
if (pattern != null) {
try {
Perl5Compiler compiler = new Perl5Compiler();
_pattern = compiler.compile(pattern);
} catch (MalformedPatternException mpe) {
throw new ConfigurationError(mpe.toString());
}
} else {
_pattern = null;
}
}
public String mergePaths(String p, String q)
{
int qlen = q.length();
StringBuffer b = new StringBuffer(p.length() + qlen + 1);
b.append(p);
if (p.endsWith("/")) {
if (q.startsWith("/")) {
if (qlen>1) {
b.append(q.substring(1));
}
} else {
b.append(q);
}
}
return b.toString();
}
public String mergePath(String q)
{
return mergePaths(getPath(), q);
}
public String getPathinfo()
{
return _pathinfo;
}
public String getPath()
{
if (_parent != null) {
return mergePaths(_parent.getPath(), _pathinfo);
} else {
return _pathinfo;
}
}
public String getParentPath()
{
return _parent.getPath();
}
public String getBasePath()
{
if (_container != null && _parent != null) {
return mergePaths(_parent.getBasePath(), _pathinfo);
} else {
return _parent.getBasePath();
}
}
public void setDirectoryIndex(String index)
{
_index = index;
}
public String getDirectoryIndex()
{
if (_index != null) {
if (_index.length() == 0) {
return null;
}
return _index;
} else {
return _parent.getDirectoryIndex();
}
}
public void setNamespace(String namespace)
{
_namespace = namespace;
}
public String getNamespace()
{
if (_namespace != null) {
if (_namespace.length() == 0) {
return null;
}
return _namespace;
} else {
return _parent.getNamespace();
}
}
public int getContentProcessing()
{
if (_content == -1) {
return _parent.getContentProcessing();
} else {
return _content;
}
}
public void setContentProcessing(int state)
{
_content = state;
}
public void setRepositories(String repositories)
{
_repositories = repositories;
}
public String getRepositories()
{
if (_repositories != null) {
return _repositories;
}
if (_parent != null) {
return _parent.getRepositories();
}
return null;
}
public void setHidden(boolean hidden)
{
_hidden = hidden ? Boolean.TRUE : Boolean.FALSE;
}
public boolean isHidden()
{
if (_hidden != null) {
return _hidden.booleanValue();
} else {
return _parent.isHidden();
}
}
public void setShouldInvalidate(boolean invalidate)
{
_invalidate = invalidate ? Boolean.TRUE : Boolean.FALSE;
}
public boolean shouldInvalidate()
{
if (_invalidate != null) {
return _invalidate.booleanValue();
} else {
return _parent.shouldInvalidate();
}
}
public void setPrintPretty(boolean pretty)
{
_pretty = pretty ? Boolean.TRUE : Boolean.FALSE;
}
public boolean printPretty()
{
if (_pretty != null) {
return _pretty.booleanValue();
} else {
return _parent.printPretty();
}
}
public void setAssert(boolean enabled)
{
_assert = enabled ? Boolean.TRUE : Boolean.FALSE;
}
public boolean getAssert()
{
if (_assert != null) {
return _assert.booleanValue();
} else {
return _parent.getAssert();
}
}
public void setDebug(boolean enabled)
{
_debug = enabled ? Boolean.TRUE : Boolean.FALSE;
}
public boolean getDebug()
{
if (_debug != null) {
return _debug.booleanValue();
} else {
return _parent.getDebug();
}
}
public LoggingPreferences getLoggingPreferences()
{
if (_loggingprefs == null) {
return _parent.getLoggingPreferences();
} else {
return _loggingprefs;
}
}
public AccessPreferences getAccessPreferences()
{
if (_accessprefs == null) {
return _parent.getAccessPreferences();
} else {
return _accessprefs;
}
}
public RealmPreferences getRealmPreferences(String name)
{
int n = _realmprefs.size();
for(int i=0; i<n; i++) {
RealmPreferences prefs = (RealmPreferences)_realmprefs.get(i);
if (prefs.getName().equals(name)) {
return prefs;
}
}
if (_parent != null) {
return _parent.getRealmPreferences(name);
}
return null;
}
public SessionPreferences getSessionPreferences()
{
if (_sessionprefs == null) {
return _parent.getSessionPreferences();
} else {
return _sessionprefs;
}
}
public SessionContainerPreferences getSessionContainerPreferences()
{
if (_sessioncontainerprefs == null) {
return _parent.getSessionContainerPreferences();
} else {
return _sessioncontainerprefs;
}
}
public LocalizationPreferences getLocalizationPreferences()
{
if (_localizationprefs == null) {
return _parent.getLocalizationPreferences();
} else {
return _localizationprefs;
}
}
public CompilerPreferences getCompilerPreferences()
{
if (_compilerprefs == null) {
return _parent.getCompilerPreferences();
} else {
return _compilerprefs;
}
}
public BindPreferences getBindPreferences()
{
if (_bindprefs == null) {
return _parent.getBindPreferences();
} else {
return _bindprefs;
}
}
public ModulePreferences getModulePreferences()
{
return _moduleprefs;
}
public ApplicationPreferences getApplicationPreferences()
{
if (_applicationprefs == null) {
return _parent.getApplicationPreferences();
} else {
return _applicationprefs;
}
}
public Modules getModules()
{
if (_modules == null) {
synchronized(this) {
Modules modules = null;
Zone zone = this;
while(zone != null) {
ModulePreferences prefs = zone.getModulePreferences();
if (prefs != null && !prefs.isEmpty()) {
if (modules == null) {
modules = new Modules();
}
prefs.registerModules(modules);
}
zone = zone._parent;
}
if (modules == null) {
modules = Modules.getInstance();
}
_modules = modules;
}
}
return _modules;
}
public int getType()
{
return ZONE;
}
public String[] getPreferences()
{
return PREFERENCES;
}
public String[] getAdditionalPreferenceNames()
{
return null;
}
public Object getPreference(String name)
{
if (name.equalsIgnoreCase("path")) {
return _pathinfo;
}
if (name.equalsIgnoreCase("pattern")) {
return (_pattern != null) ? _pattern.getPattern() : null;
}
if (name.equalsIgnoreCase("container")) {
return _container;
}
if (name.equalsIgnoreCase("dispatcher")) {
return _dispatcher;
}
if (name.equalsIgnoreCase("hidden")) {
return _hidden;
}
if (name.equalsIgnoreCase("invalidate")) {
return _invalidate;
}
if (name.equalsIgnoreCase("pretty")) {
return _pretty;
}
if (name.equalsIgnoreCase("assert")) {
return _assert;
}
if (name.equalsIgnoreCase("debug")) {
return _debug;
}
if (name.equalsIgnoreCase("index")) {
return _index;
}
if (name.equalsIgnoreCase("namespace")) {
return _namespace;
}
if (name.equalsIgnoreCase("content")) {
int c = _content;
String[] s = Statement.CONTENT_PROCESSING;
if (c>=0 && c<s.length) {
return s[c];
}
return null;
}
if (name.equalsIgnoreCase("repositories")) {
return _repositories;
}
return null;
}
public boolean setPreference(String name, String value)
{
if (name.equalsIgnoreCase("path")) {
setPathinfo(value);
} else if (name.equalsIgnoreCase("pattern")) {
setPattern(value);
} else if (name.equalsIgnoreCase("container")) {
setContainer(value);
} else if (name.equalsIgnoreCase("dispatcher")) {
setDispatcher(value);
} else if (name.equalsIgnoreCase("hidden")) {
setHidden(ConfigReader.toBoolean(value));
} else if (name.equalsIgnoreCase("invalidate")) {
setShouldInvalidate(ConfigReader.toBoolean(value));
} else if (name.equalsIgnoreCase("pretty")) {
setPrintPretty(ConfigReader.toBoolean(value));
} else if (name.equalsIgnoreCase("assert")) {
setAssert(ConfigReader.toBoolean(value));
} else if (name.equalsIgnoreCase("debug")) {
setDebug(ConfigReader.toBoolean(value));
} else if (name.equalsIgnoreCase("index")) {
setDirectoryIndex(value);
} else if (name.equalsIgnoreCase("namespace")) {
setNamespace(value);
} else if (name.equalsIgnoreCase("content")) {
String[] s = Statement.CONTENT_PROCESSING;
for(int i=s.length-1; i>=0; i--) {
if (s[i].equalsIgnoreCase(value)) {
setContentProcessing(i);
return true;
}
}
setContentProcessing(-1);
} else if (name.equalsIgnoreCase("repositories")) {
setRepositories(value);
} else {
return false;
}
return true;
}
public void deleteConfiguration(Configurable configurable)
{
switch(configurable.getType()) {
case SERVER:
case DOMAIN:
return;
case ZONE:
Zone zone = (Zone)configurable;
zone.setParent(null);
int length = _childs.length;
for(int i=0; i<length; i++) {
if (_childs[i] == zone) {
Zone[] childs = new Zone[length-1];
if (i>0) {
System.arraycopy(_childs, 0, childs, 0, i);
}
if (i<length-1) {
System.arraycopy(_childs, i+1, childs, i, length-i-1);
}
_childs = childs;
break;
}
}
break;
case LOGGING:
if (configurable == _loggingprefs) {
_loggingprefs = null;
}
break;
case LISTENER:
if (configurable == _listenerprefs) {
_listenerprefs = null;
}
break;
case ACCESS:
if (configurable == _accessprefs) {
_accessprefs = null;
}
break;
case SESSION:
if (configurable == _sessionprefs) {
_sessionprefs = null;
}
break;
case SESSION_CONTAINER:
if (configurable == _sessioncontainerprefs) {
_sessioncontainerprefs = null;
}
break;
case LOCALIZATION:
if (configurable == _localizationprefs) {
_localizationprefs = null;
}
break;
case COMPILER:
if (configurable == _compilerprefs) {
_compilerprefs = null;
}
break;
case MODULES:
if (configurable == _moduleprefs) {
_moduleprefs = null;
_modules = null;
}
break;
case APPLICATION:
if (configurable == _applicationprefs) {
_applicationprefs = null;
}
break;
case BIND:
if (configurable == _bindprefs) {
_bindprefs = null;
}
break;
case HANDLERS:
if (configurable == _handlerprefs) {
_handlerprefs = null;
}
break;
case POLICY:
if (configurable == _policyprefs) {
_policyprefs = null;
}
break;
case NAMESPACE:
_namespacesprefs.remove(configurable);
break;
case POOL:
_pools.remove(configurable);
break;
case REALM:
_realmprefs.remove(configurable);
break;
default:
}
}
protected void getConfigurations(ArrayList v)
{
int length = _childs.length;
for(int i=0; i<length; i++) {
v.add(_childs[i]);
}
if (_loggingprefs != null) v.add(_loggingprefs);
if (_listenerprefs != null) v.add(_listenerprefs);
if (_compilerprefs != null) v.add(_compilerprefs);
if (_bindprefs != null) v.add(_bindprefs);
if (_handlerprefs != null) v.add(_handlerprefs);
if (_sessioncontainerprefs != null) v.add(_sessioncontainerprefs);
if (_sessionprefs != null) v.add(_sessionprefs);
length = _realmprefs.size();
for(int i=0; i<length; i++) {
v.add(_realmprefs.get(i));
}
if (_accessprefs != null) v.add(_accessprefs);
if (_localizationprefs != null) v.add(_localizationprefs);
if (_moduleprefs != null) v.add(_moduleprefs);
if (_applicationprefs != null) v.add(_applicationprefs);
length = _namespacesprefs.size();
for(int i=0; i<length; i++) {
v.add(_namespacesprefs.get(i));
}
length = _pools.size();
for(int i=0; i<length; i++) {
v.add(_pools.get(i));
}
}
public Configurable[] getConfigurations()
{
ArrayList v = new ArrayList();
getConfigurations(v);
return (Configurable[])v.toArray(new Configurable[v.size()]);
}
public boolean configure(Configurable configurable)
{
switch(configurable.getType()) {
case SERVER:
case DOMAIN:
return false;
case ZONE:
Zone zone = (Zone)configurable;
zone.setParent(this);
if (_childs == null) {
_childs = new Zone[] { (Zone)configurable };
} else {
int length = _childs.length;
Zone[] childs = new Zone[length+1];
System.arraycopy(_childs, 0, childs, 0, length);
childs[length] = (Zone)configurable;
_childs = childs;
}
break;
case LOGGING:
if (_loggingprefs != null) {
return false;
}
_loggingprefs = (LoggingPreferences)configurable;
break;
case LISTENER:
if (_listenerprefs != null) {
return false;
}
_listenerprefs = (ListenerPreferences)configurable;
break;
case ACCESS:
if (_accessprefs != null) {
return false;
}
_accessprefs = (AccessPreferences)configurable;
break;
case SESSION:
if (_sessionprefs != null) {
return false;
}
_sessionprefs = (SessionPreferences)configurable;
break;
case SESSION_CONTAINER:
if (_sessioncontainerprefs != null) {
return false;
}
_sessioncontainerprefs = (SessionContainerPreferences)configurable;
break;
case REALM:
_realmprefs.add(configurable);
break;
case LOCALIZATION:
if (_localizationprefs != null) {
return false;
}
_localizationprefs = (LocalizationPreferences)configurable;
break;
case COMPILER:
if (_compilerprefs != null) {
return false;
}
_compilerprefs = (CompilerPreferences)configurable;
break;
case BIND:
if (_bindprefs != null) {
return false;
}
_bindprefs = (BindPreferences)configurable;
break;
case HANDLERS:
if (_handlerprefs != null) {
return false;
}
_handlerprefs = (HandlerPreferences)configurable;
break;
case MODULES:
if (_moduleprefs != null) {
return false;
}
_moduleprefs = (ModulePreferences)configurable;
break;
case APPLICATION:
if (_applicationprefs != null) {
return false;
}
_applicationprefs = (ApplicationPreferences)configurable;
break;
case POLICY:
if (_policyprefs != null) {
return false;
}
_policyprefs = (PolicyPreferences)configurable;
break;
case POOL:
_pools.add(configurable);
break;
case NAMESPACE:
_namespacesprefs.add(configurable);
break;
default:
return false;
}
return true;
}
public ModuleEnvelope[] getCacheContents()
{
return getServer().getCache().getContents(getDomain().getHostname(), _pathinfo);
}
public void purgeCache()
{
getServer().getCache().purge(getDomain().getHostname(), _pathinfo);
}
public synchronized boolean isStarted()
{
return _started;
}
public synchronized void start()
{
int n;
if (_loggingprefs != null) {
String name = getDomain().getHostname();
if (name.length()>0) {
name += ':' + _pathinfo;
} else {
name = _pathinfo;
}
_log = _loggingprefs.createLog(name);
_log.info("Created: " + _log.toString());
}
n = _pools.size();
if (n>0) {
_manager = new ConnectionManager();
for(int i=0; i<n; i++) {
PoolPreferences prefs = (PoolPreferences)_pools.get(i);
if (prefs.isEnabled()) {
_manager.addPool(new ConnectionPool(this, prefs));
}
}
}
if (_sessioncontainerprefs != null) {
_sessioncontainer = _sessioncontainerprefs.createContainer();
}
n = _realmprefs.size();
for(int i=0; i<n; i++) {
RealmPreferences prefs = (RealmPreferences)_realmprefs.get(i);
_realms.put(prefs.getName(), prefs.createRealm());
}
if (_accessprefs != null) {
_auth = _accessprefs.createAuthorization();
}
n = _namespacesprefs.size();
for(int i=0; i<n; i++) {
NamespacePreferences ns = (NamespacePreferences)_namespacesprefs.get(i);
_namespaces.put(ns.getName(), ns.createNamespace());
}
if ((_compilerprefs != null) || (_repositories != null)) {
_classloader = new ZoneClassLoader(this, _compilerprefs);
}
n = _childs.length;
for(int i=0; i<n; i++) {
_childs[i].start();
}
if (_listenerprefs != null) {
_listener = _listenerprefs.createListener();
}
log().info("Zone "+getPath()+" started.");
_started = true;
}
public synchronized void stop()
{
try {
if (_listener != null) {
_listener.stop();
_listener = null;
}
int n = _childs.length;
for(int i=0; i<n; i++) {
_childs[i].stop();
}
if (_sessioncontainer != null) {
_sessioncontainer.stop();
}
if (_auth != null) {
_auth.stop();
}
Iterator iter = _realms.values().iterator();
while(iter.hasNext()) {
Realm realm = (Realm)iter.next();
realm.stop();
}
iter = _namespaces.values().iterator();
while(iter.hasNext()) {
PersistentNamespace ns = (PersistentNamespace)iter.next();
ns.stop();
}
if (_manager != null) {
_manager.stop();
}
if (_classloader != null) {
_classloader.stop();
}
log().info("Zone "+getPath()+" stopped.");
if (_log != null) {
_log.stop();
}
} finally {
_started = false;
_modules = null;
_sessioncontainer = null;
_auth = null;
_realms.clear();
_namespaces.clear();
_manager = null;
_classloader = null;
_address = null;
_log = null;
}
}
public String getContentType(String extension)
{
if (_bindprefs != null) {
String type = _bindprefs.lookup(extension);
if (type != null) {
return type;
}
}
if (_parent != null) {
return _parent.getContentType(extension);
}
return null;
}
public ContentHandler getContentHandler(String type)
{
if (type != null) {
if (_handlerprefs != null) {
ContentHandler handler = _handlerprefs.lookup(type);
if (handler != null) {
return handler;
}
}
if (_parent != null) {
return _parent.getContentHandler(type);
}
}
return DefaultContentHandler.INSTANCE;
}
public Zone resolveDomain(String hostname)
{
return this;
}
protected Zone accept(String pathinfo, int start)
{
if (_pattern != null) {
PatternMatcherInput input = new PatternMatcherInput(pathinfo, start, pathinfo.length()-start);
Perl5Matcher matcher = new Perl5Matcher();
if (matcher.contains(input, _pattern)) {
return resolveZone(pathinfo, start);
}
} else {
String pi = _pathinfo;
int pi_length = pi.length();
if (pathinfo.regionMatches(start, pi, 0, pi_length-1)) {
int next = start + pi_length;
if (next <= pathinfo.length() && pathinfo.charAt(next-1) != '/') {
return null;
}
Zone zone = resolveZone(pathinfo, next);
if (zone != null) {
return zone;
}
return this;
}
}
return null;
}
protected Zone resolveZone(String pathinfo, int start)
{
if (!_started) {
return null;
}
Zone[] zones = _childs;
final int n = zones.length;
for(int i=0; i<n; i++) {
Zone zone = zones[i];
zone = zone.accept(pathinfo, start);
if (zone != null) {
return zone;
}
}
return this;
}
public Zone resolveZone(String pathinfo)
{
if (pathinfo == null) {
pathinfo = "/";
}
Zone zone = resolveZone(pathinfo, getPath().length());
if (zone == null) {
zone = this;
}
return zone;
}
public Context resolve(String path, boolean dispatch)
throws RedirectException, ZoneInactiveException
{
if (!_started) {
throw new ZoneInactiveException("Zone '"+getPath()+"' is not started");
}
Zone zone = this;
Domain domain = zone.getDomain();
String hostname = domain.getHostname();
String dispatcher = zone.getDispatcher();
String resource;
if (dispatch && dispatcher != null) {
zone = zone.getDispatcherZone();
String dispatcherpath = zone.getPath();
resource = path.substring(dispatcherpath.length()-1);
if (resource.length()==0 && !path.endsWith("/")) {
throw new RedirectException(path+'/');
}
path = dispatcherpath + dispatcher;
} else {
resource = "";
}
return new Context(new Address(zone, hostname, path), resource);
}
public Address resolve(String path) throws ZoneInactiveException
{
if (!_started) {
throw new ZoneInactiveException("Zone '"+getPath()+"' is not started");
}
Zone zone = this;
Domain domain = zone.getDomain();
String hostname = domain.getHostname();
String dispatcher = zone.getDispatcher();
return new Address(zone, hostname, path);
}
protected String[] analyzePathinfo(String pathinfo)
{
if (pathinfo == null) {
pathinfo = "/";
} else {
pathinfo = anvil.util.PathUtils.normalizePath(pathinfo);
}
if (pathinfo.startsWith("/$")) {
int end = pathinfo.indexOf('/', 2);
if (end > 0) {
String session = pathinfo.substring(2, end);
pathinfo = pathinfo.substring(end);
return new String[] { session, pathinfo };
}
}
return new String[] { null, pathinfo };
}
protected Context resolve(RequestAdapter adapter, HttpServletRequest request, HttpServletResponse response)
throws ZoneInactiveException, RedirectException
{
String pathinfo = mergePaths(getPath(), adapter.getPathinfo());
String hostname = request.getHeader("Host");
Zone domain = resolveDomain(hostname);
Zone zone = domain.resolveZone(pathinfo);
Context context = zone.resolve(pathinfo, true);
context.init(adapter, request, response);
return context;
}
public void sendRedirect(RequestAdapter adapter, HttpServletRequest request, HttpServletResponse response, RedirectException exception) throws IOException
{
StringBuffer redirect = new StringBuffer();
String sp = adapter.getServletPath();
if (sp == null) {
redirect.append('/');
} else {
redirect.append(sp);
if (!(sp.endsWith("/"))) {
redirect.append('/');
}
}
String session = null;
if (exception.hadSession()) {
session = exception.getSession();
} else {
session = adapter.getSession();
}
if (session != null) {
redirect.append('$');
redirect.append(session);
redirect.append('/');
}
String pathinfo = exception.getPathinfo();
if (pathinfo.startsWith("/")) {
redirect.append(pathinfo.substring(1));
} else {
redirect.append(pathinfo);
}
String querystring = request.getQueryString();
if (querystring != null) {
redirect.append('?');
redirect.append(querystring);
}
response.sendRedirect(redirect.toString());
}
public void service(HttpServletRequest request, HttpServletResponse response)
{
Server server = getServer();
server.serveRequest();
String name = "Request-"+server.getRequestsServed();
Thread.currentThread().setName(name);
try {
String contentType = MimeTypes.guessContentType(request);
response.setContentType(contentType);
RequestAdapter adapter = getAdapterFactory().createAdapter(request);
Context context = null;
try {
try {
context = resolve(adapter, request, response);
try {
context.getAddress().getZone().service(context);
} catch (ScriptException exception) {
context.log().error("Runtime errors\n" + exception.getData().toString());
Templates.exception(context, exception, contentType);
} catch (ForgingException exception) {
context.log().error("Parsing errors\n" + exception.toString());
Templates.exception(context, exception, contentType);
} catch (RedirectException redirect) {
sendRedirect(adapter, request, response, redirect);
} catch (ContainerException exception) {
log().info("Resource not found: "+request.getHeader("Host") + ", " + request.getPathInfo());
Templates.message(request, response, contentType, 404);
} catch (FileNotFoundException exception) {
log().info("Resource not found: "+request.getHeader("Host") + ", " + request.getPathInfo());
Templates.message(request, response, contentType, 404);
} catch (IOException exception) {
context.log().error("IO-Error", exception);
Templates.exception(context, exception, contentType);
} catch (Exception exception) {
context.log().error("Exception", exception);
Templates.exception(context, exception, contentType);
}
} catch (ZoneInactiveException exception) {
log().error(exception.getMessage());
Templates.message(request, response, contentType, 503, "Zone temporarily inactive");
} catch (RedirectException redirect) {
sendRedirect(adapter, request, response, redirect);
}
} finally {
if (context != null) {
context.destroy();
context = null;
}
}
} catch (Throwable t) {
log().error("Exception while handling request", t);
}
}
public void service(Context context) throws Exception
{
if (isHidden()) {
Templates.message(context, MimeTypes.TEXT_HTML, 403);
return;
}
Address address = context.getAddress();
Resource resource = address.openResource(context);
ContentHandler handler = getContentHandler(resource.getContentType());
Authorization auth = getAuthorization();
boolean needSession = handler.isSessionRequired() || auth.isSessionRequired();
if (needSession) {
if (!getSessionPreferences().service(context)) {
return;
}
if (!auth.authorize(context)) {
return;
}
}
handler.service(context, resource);
Citizen citizen = context.getCitizen();
if (citizen != null) {
citizen.commit();
}
}
}