Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoakim Erdfelt2013-09-16 16:11:43 +0000
committerJoakim Erdfelt2013-09-16 16:11:43 +0000
commita71dce39ca8fd184bb9de9c60af687d34a88f75d (patch)
tree11a2e090c97d7b0741cc91cde50b53c42de44477 /jetty-plus/src/main/java/org/eclipse/jetty
parentea22c2128106dd1590210ef44064a2bfa1514848 (diff)
downloadorg.eclipse.jetty.project-a71dce39ca8fd184bb9de9c60af687d34a88f75d.tar.gz
org.eclipse.jetty.project-a71dce39ca8fd184bb9de9c60af687d34a88f75d.tar.xz
org.eclipse.jetty.project-a71dce39ca8fd184bb9de9c60af687d34a88f75d.zip
Diffstat (limited to 'jetty-plus/src/main/java/org/eclipse/jetty')
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java113
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/Injection.java34
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/LifeCycleCallback.java39
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/RunAsCollection.java20
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASGroup.java152
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASLoginService.java336
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASPrincipal.java89
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASRole.java (renamed from jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/package-info.java)27
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASUserPrincipal.java79
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/RoleCheckPolicy.java (renamed from jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/package-info.java)21
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/StrictRoleCheckPolicy.java63
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/callback/AbstractCallbackHandler.java60
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/callback/DefaultCallbackHandler.java97
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/callback/ObjectCallback.java (renamed from jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/package-info.java)50
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/callback/RequestParameterCallback.java61
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/AbstractDatabaseLoginModule.java144
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/AbstractLoginModule.java289
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/DataSourceLoginModule.java89
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/JDBCLoginModule.java127
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/LdapLoginModule.java689
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/PropertyFileLoginModule.java134
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/UserInfo.java73
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingEntryUtil.java58
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java218
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/security/package-info.java23
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/servlet/ServletHandler.java76
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/EnvConfiguration.java53
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/PlusConfiguration.java26
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/PlusDecorator.java18
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/PlusDescriptorProcessor.java216
30 files changed, 2990 insertions, 484 deletions
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java
deleted file mode 100644
index 9d93203c92..0000000000
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java
+++ /dev/null
@@ -1,113 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.plus.annotation;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.servlet.ServletContainerInitializer;
-
-import org.eclipse.jetty.util.Loader;
-import org.eclipse.jetty.webapp.WebAppContext;
-
-public class ContainerInitializer
-{
- protected ServletContainerInitializer _target;
- protected Class[] _interestedTypes;
- protected Set<String> _applicableTypeNames;
- protected Set<String> _annotatedTypeNames;
-
-
- public void setTarget (ServletContainerInitializer target)
- {
- _target = target;
- }
-
- public ServletContainerInitializer getTarget ()
- {
- return _target;
- }
-
- public Class[] getInterestedTypes ()
- {
- return _interestedTypes;
- }
-
- public void setInterestedTypes (Class[] interestedTypes)
- {
- _interestedTypes = interestedTypes;
- }
-
- /**
- * A class has been found that has an annotation of interest
- * to this initializer.
- * @param className
- */
- public void addAnnotatedTypeName (String className)
- {
- if (_annotatedTypeNames == null)
- _annotatedTypeNames = new HashSet<String>();
- _annotatedTypeNames.add(className);
- }
-
- public Set<String> getAnnotatedTypeNames ()
- {
- return _annotatedTypeNames;
- }
-
- public void addApplicableTypeName (String className)
- {
- if (_applicableTypeNames == null)
- _applicableTypeNames = new HashSet<String>();
- _applicableTypeNames.add(className);
- }
-
- public Set<String> getApplicableTypeNames ()
- {
- return _applicableTypeNames;
- }
-
-
- public void callStartup(WebAppContext context)
- throws Exception
- {
- if (_target != null)
- {
- Set<Class<?>> classes = new HashSet<Class<?>>();
-
- ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
- Thread.currentThread().setContextClassLoader(context.getClassLoader());
-
- try
- {
- if (_applicableTypeNames != null)
- {
- for (String s : _applicableTypeNames)
- classes.add(Loader.loadClass(context.getClass(), s));
- }
-
- _target.onStartup(classes, context.getServletContext());
- }
- finally
- {
- Thread.currentThread().setContextClassLoader(oldLoader);
- }
- }
- }
-}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/Injection.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/Injection.java
index df5c4bf4bc..d9b7a8ed2f 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/Injection.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/Injection.java
@@ -49,11 +49,11 @@ public class Injection
private Class<?> _paramClass;
private Class<?> _resourceClass;
-
+
public Injection ()
{
}
-
+
/**
* @return the _className
@@ -67,22 +67,22 @@ public class Injection
{
return _paramClass;
}
-
+
public Class<?> getResourceClass ()
{
return _resourceClass;
}
-
+
public boolean isField ()
{
return (_target != null && _target instanceof Field);
}
-
+
public boolean isMethod ()
{
return (_target != null && _target instanceof Method);
}
-
+
/**
* @return the jndiName
*/
@@ -111,7 +111,7 @@ public class Injection
{
this._mappingName = mappingName;
}
-
+
/**
* @return the target
*/
@@ -119,7 +119,7 @@ public class Injection
{
return _target;
}
-
+
public void setTarget(Class<?> clazz, Field field, Class<?> resourceType)
{
@@ -127,7 +127,7 @@ public class Injection
_target = field;
_resourceClass = resourceType;
}
-
+
public void setTarget(Class<?> clazz, Method method, Class<?> arg, Class<?> resourceType)
{
_targetClass = clazz;
@@ -135,12 +135,12 @@ public class Injection
_resourceClass = resourceType;
_paramClass = arg;
}
-
+
public void setTarget (Class<?> clazz, String target, Class<?> resourceType)
{
_targetClass = clazz;
_resourceClass = resourceType;
-
+
//first look for a javabeans style setter matching the targetName
String setter = "set"+target.substring(0,1).toUpperCase(Locale.ENGLISH)+target.substring(1);
try
@@ -165,13 +165,13 @@ public class Injection
}
}
-
+
/**
* Inject a value for a Resource from JNDI into an object
* @param injectable
*/
public void inject (Object injectable)
- {
+ {
if (_target != null)
{
if (_target instanceof Field)
@@ -183,7 +183,7 @@ public class Injection
throw new IllegalStateException ("No method or field to inject with "+getJndiName());
}
-
+
/**
* The Resource must already exist in the ENC of this webapp.
* @return the injected valud
@@ -195,7 +195,7 @@ public class Injection
InitialContext context = new InitialContext();
return context.lookup("java:comp/env/"+getJndiName());
}
-
+
/**
@@ -204,7 +204,7 @@ public class Injection
* @param injectable
*/
protected void injectField (Field field, Object injectable)
- {
+ {
try
{
boolean accessibility = field.isAccessible();
@@ -239,5 +239,5 @@ public class Injection
throw new IllegalStateException("Inject failed for method "+method.getName());
}
}
-
+
}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/LifeCycleCallback.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/LifeCycleCallback.java
index a45e83509d..6dac2d0e82 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/LifeCycleCallback.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/LifeCycleCallback.java
@@ -24,7 +24,6 @@ import java.lang.reflect.Modifier;
import org.eclipse.jetty.util.IntrospectionUtil;
import org.eclipse.jetty.util.Loader;
-import org.eclipse.jetty.util.TypeUtil;
@@ -40,8 +39,8 @@ public abstract class LifeCycleCallback
private Class<?> _targetClass;
private String _className;
private String _methodName;
-
-
+
+
public LifeCycleCallback()
{
}
@@ -54,17 +53,17 @@ public abstract class LifeCycleCallback
{
return _targetClass;
}
-
+
public String getTargetClassName()
{
return _className;
}
-
+
public String getMethodName()
{
return _methodName;
}
-
+
/**
* @return the target
*/
@@ -72,8 +71,8 @@ public abstract class LifeCycleCallback
{
return _target;
}
-
-
+
+
public void setTarget (String className, String methodName)
{
_className = className;
@@ -98,18 +97,18 @@ public abstract class LifeCycleCallback
}
-
-
- public void callback (Object instance)
+
+
+ public void callback (Object instance)
throws SecurityException, NoSuchMethodException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
if (_target == null)
{
if (_targetClass == null)
_targetClass = Loader.loadClass(null, _className);
- _target = _targetClass.getDeclaredMethod(_methodName, TypeUtil.NO_ARGS);
+ _target = _targetClass.getDeclaredMethod(_methodName, new Class[]{}); //TODO
}
-
+
if (_target != null)
{
boolean accessibility = getTarget().isAccessible();
@@ -119,15 +118,15 @@ public abstract class LifeCycleCallback
}
}
-
+
/**
* Find a method of the given name either directly in the given
* class, or inherited.
- *
+ *
* @param pack the package of the class under inspection
* @param clazz the class under inspection
- * @param methodName the method to find
+ * @param methodName the method to find
* @param checkInheritance false on first entry, true if a superclass is being introspected
* @return the method
*/
@@ -138,7 +137,7 @@ public abstract class LifeCycleCallback
try
{
- Method method = clazz.getDeclaredMethod(methodName);
+ Method method = clazz.getDeclaredMethod(methodName, null);
if (checkInheritance)
{
int modifiers = method.getModifiers();
@@ -162,7 +161,7 @@ public abstract class LifeCycleCallback
if (!(o instanceof LifeCycleCallback))
return false;
LifeCycleCallback callback = (LifeCycleCallback)o;
-
+
if (callback.getTargetClass()==null)
{
if (getTargetClass() != null)
@@ -177,9 +176,9 @@ public abstract class LifeCycleCallback
}
else if (!callback.getTarget().equals(getTarget()))
return false;
-
+
return true;
}
-
+
public abstract void validate (Class<?> clazz, Method m);
}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/RunAsCollection.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/RunAsCollection.java
index b43ca8666d..df8e3481b2 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/RunAsCollection.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/RunAsCollection.java
@@ -38,14 +38,14 @@ public class RunAsCollection
public static final String RUNAS_COLLECTION = "org.eclipse.jetty.runAsCollection";
private HashMap<String, RunAs> _runAsMap = new HashMap<String, RunAs>();//map of classname to run-as
-
-
-
+
+
+
public void add (RunAs runAs)
{
- if ((runAs==null) || (runAs.getTargetClassName()==null))
+ if ((runAs==null) || (runAs.getTargetClassName()==null))
return;
-
+
if (LOG.isDebugEnabled())
LOG.debug("Adding run-as for class="+runAs.getTargetClassName());
_runAsMap.put(runAs.getTargetClassName(), runAs);
@@ -56,23 +56,23 @@ public class RunAsCollection
{
if (o==null)
return null;
-
+
return (RunAs)_runAsMap.get(o.getClass().getCanonicalName());
}
-
+
public void setRunAs(Object o)
throws ServletException
{
if (o == null)
return;
-
+
if (!ServletHolder.class.isAssignableFrom(o.getClass()))
return;
-
+
RunAs runAs = (RunAs)_runAsMap.get(o.getClass().getName());
if (runAs == null)
return;
-
+
runAs.setRunAs((ServletHolder)o);
}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASGroup.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASGroup.java
new file mode 100644
index 0000000000..5310f4afa1
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASGroup.java
@@ -0,0 +1,152 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.jaas;
+
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+
+
+public class JAASGroup implements Group
+{
+ public static final String ROLES = "__roles__";
+
+ private String _name = null;
+ private HashSet<Principal> _members = null;
+
+
+
+ public JAASGroup(String n)
+ {
+ this._name = n;
+ this._members = new HashSet<Principal>();
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ *
+ * @param principal <description>
+ * @return <description>
+ */
+ public synchronized boolean addMember(Principal principal)
+ {
+ return _members.add(principal);
+ }
+
+ /**
+ *
+ * @param principal <description>
+ * @return <description>
+ */
+ public synchronized boolean removeMember(Principal principal)
+ {
+ return _members.remove(principal);
+ }
+
+ /**
+ *
+ * @param principal <description>
+ * @return <description>
+ */
+ public boolean isMember(Principal principal)
+ {
+ return _members.contains(principal);
+ }
+
+
+
+ /**
+ *
+ * @return <description>
+ */
+ public Enumeration<? extends Principal> members()
+ {
+
+ class MembersEnumeration implements Enumeration<Principal>
+ {
+ private Iterator<? extends Principal> itor;
+
+ public MembersEnumeration (Iterator<? extends Principal> itor)
+ {
+ this.itor = itor;
+ }
+
+ public boolean hasMoreElements ()
+ {
+ return this.itor.hasNext();
+ }
+
+
+ public Principal nextElement ()
+ {
+ return this.itor.next();
+ }
+
+ }
+
+ return new MembersEnumeration (_members.iterator());
+ }
+
+
+ /**
+ *
+ * @return <description>
+ */
+ public int hashCode()
+ {
+ return getName().hashCode();
+ }
+
+
+
+ /**
+ *
+ * @param object <description>
+ * @return <description>
+ */
+ public boolean equals(Object object)
+ {
+ if (! (object instanceof JAASGroup))
+ return false;
+
+ return ((JAASGroup)object).getName().equals(getName());
+ }
+
+ /**
+ *
+ * @return <description>
+ */
+ public String toString()
+ {
+ return getName();
+ }
+
+ /**
+ *
+ * @return <description>
+ */
+ public String getName()
+ {
+
+ return _name;
+ }
+
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASLoginService.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASLoginService.java
new file mode 100644
index 0000000000..b130d82470
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASLoginService.java
@@ -0,0 +1,336 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.jaas;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.eclipse.jetty.plus.jaas.callback.ObjectCallback;
+import org.eclipse.jetty.plus.jaas.callback.RequestParameterCallback;
+import org.eclipse.jetty.security.DefaultIdentityService;
+import org.eclipse.jetty.security.IdentityService;
+import org.eclipse.jetty.security.LoginService;
+import org.eclipse.jetty.server.AbstractHttpConnection;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.UserIdentity;
+import org.eclipse.jetty.util.Loader;
+import org.eclipse.jetty.util.component.AbstractLifeCycle;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+/* ---------------------------------------------------- */
+/** JAASLoginService
+ *
+ * @org.apache.xbean.XBean element="jaasUserRealm" description="Creates a UserRealm suitable for use with JAAS"
+ */
+public class JAASLoginService extends AbstractLifeCycle implements LoginService
+{
+ private static final Logger LOG = Log.getLogger(JAASLoginService.class);
+
+ public static String DEFAULT_ROLE_CLASS_NAME = "org.eclipse.jetty.plus.jaas.JAASRole";
+ public static String[] DEFAULT_ROLE_CLASS_NAMES = {DEFAULT_ROLE_CLASS_NAME};
+
+ protected String[] _roleClassNames = DEFAULT_ROLE_CLASS_NAMES;
+ protected String _callbackHandlerClass;
+ protected String _realmName;
+ protected String _loginModuleName;
+ protected JAASUserPrincipal _defaultUser = new JAASUserPrincipal(null, null, null);
+ protected IdentityService _identityService;
+
+ /* ---------------------------------------------------- */
+ /**
+ * Constructor.
+ *
+ */
+ public JAASLoginService()
+ {
+ }
+
+
+ /* ---------------------------------------------------- */
+ /**
+ * Constructor.
+ *
+ * @param name the name of the realm
+ */
+ public JAASLoginService(String name)
+ {
+ this();
+ _realmName = name;
+ _loginModuleName = name;
+ }
+
+
+ /* ---------------------------------------------------- */
+ /**
+ * Get the name of the realm.
+ *
+ * @return name or null if not set.
+ */
+ public String getName()
+ {
+ return _realmName;
+ }
+
+
+ /* ---------------------------------------------------- */
+ /**
+ * Set the name of the realm
+ *
+ * @param name a <code>String</code> value
+ */
+ public void setName (String name)
+ {
+ _realmName = name;
+ }
+
+ /* ------------------------------------------------------------ */
+ /** Get the identityService.
+ * @return the identityService
+ */
+ public IdentityService getIdentityService()
+ {
+ return _identityService;
+ }
+
+ /* ------------------------------------------------------------ */
+ /** Set the identityService.
+ * @param identityService the identityService to set
+ */
+ public void setIdentityService(IdentityService identityService)
+ {
+ _identityService = identityService;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Set the name to use to index into the config
+ * file of LoginModules.
+ *
+ * @param name a <code>String</code> value
+ */
+ public void setLoginModuleName (String name)
+ {
+ _loginModuleName = name;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setCallbackHandlerClass (String classname)
+ {
+ _callbackHandlerClass = classname;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setRoleClassNames (String[] classnames)
+ {
+ ArrayList<String> tmp = new ArrayList<String>();
+
+ if (classnames != null)
+ tmp.addAll(Arrays.asList(classnames));
+
+ if (!tmp.contains(DEFAULT_ROLE_CLASS_NAME))
+ tmp.add(DEFAULT_ROLE_CLASS_NAME);
+ _roleClassNames = tmp.toArray(new String[tmp.size()]);
+ }
+
+ /* ------------------------------------------------------------ */
+ public String[] getRoleClassNames()
+ {
+ return _roleClassNames;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
+ */
+ protected void doStart() throws Exception
+ {
+ if (_identityService==null)
+ _identityService=new DefaultIdentityService();
+ super.doStart();
+ }
+
+ /* ------------------------------------------------------------ */
+ public UserIdentity login(final String username,final Object credentials)
+ {
+ try
+ {
+ CallbackHandler callbackHandler = null;
+
+
+ if (_callbackHandlerClass == null)
+ {
+ callbackHandler = new CallbackHandler()
+ {
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
+ {
+ for (Callback callback: callbacks)
+ {
+ if (callback instanceof NameCallback)
+ {
+ ((NameCallback)callback).setName(username);
+ }
+ else if (callback instanceof PasswordCallback)
+ {
+ ((PasswordCallback)callback).setPassword((char[]) credentials.toString().toCharArray());
+ }
+ else if (callback instanceof ObjectCallback)
+ {
+ ((ObjectCallback)callback).setObject(credentials);
+ }
+ else if (callback instanceof RequestParameterCallback)
+ {
+ AbstractHttpConnection connection = AbstractHttpConnection.getCurrentConnection();
+ Request request = (connection == null? null : connection.getRequest());
+
+ if (request != null)
+ {
+ RequestParameterCallback rpc = (RequestParameterCallback)callback;
+ rpc.setParameterValues(Arrays.asList(request.getParameterValues(rpc.getParameterName())));
+ }
+ }
+ else
+ throw new UnsupportedCallbackException(callback);
+ }
+ }
+ };
+ }
+ else
+ {
+ Class clazz = Loader.loadClass(getClass(), _callbackHandlerClass);
+ callbackHandler = (CallbackHandler)clazz.newInstance();
+ }
+ //set up the login context
+ //TODO jaspi requires we provide the Configuration parameter
+ Subject subject = new Subject();
+ LoginContext loginContext = new LoginContext(_loginModuleName, subject, callbackHandler);
+
+ loginContext.login();
+
+ //login success
+ JAASUserPrincipal userPrincipal = new JAASUserPrincipal(getUserName(callbackHandler), subject, loginContext);
+ subject.getPrincipals().add(userPrincipal);
+
+ return _identityService.newUserIdentity(subject,userPrincipal,getGroups(subject));
+ }
+ catch (LoginException e)
+ {
+ LOG.debug(e);
+ }
+ catch (IOException e)
+ {
+ LOG.info(e.getMessage());
+ LOG.debug(e);
+ }
+ catch (UnsupportedCallbackException e)
+ {
+ LOG.info(e.getMessage());
+ LOG.debug(e);
+ }
+ catch (InstantiationException e)
+ {
+ LOG.info(e.getMessage());
+ LOG.debug(e);
+ }
+ catch (IllegalAccessException e)
+ {
+ LOG.info(e.getMessage());
+ LOG.debug(e);
+ }
+ catch (ClassNotFoundException e)
+ {
+ LOG.info(e.getMessage());
+ LOG.debug(e);
+ }
+ return null;
+ }
+
+ /* ------------------------------------------------------------ */
+ public boolean validate(UserIdentity user)
+ {
+ // TODO optionally check user is still valid
+ return true;
+ }
+
+ /* ------------------------------------------------------------ */
+ private String getUserName(CallbackHandler callbackHandler) throws IOException, UnsupportedCallbackException
+ {
+ NameCallback nameCallback = new NameCallback("foo");
+ callbackHandler.handle(new Callback[] {nameCallback});
+ return nameCallback.getName();
+ }
+
+ /* ------------------------------------------------------------ */
+ public void logout(UserIdentity user)
+ {
+ Set<JAASUserPrincipal> userPrincipals = user.getSubject().getPrincipals(JAASUserPrincipal.class);
+ LoginContext loginContext = userPrincipals.iterator().next().getLoginContext();
+ try
+ {
+ loginContext.logout();
+ }
+ catch (LoginException e)
+ {
+ LOG.warn(e);
+ }
+ }
+
+
+ /* ------------------------------------------------------------ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private String[] getGroups (Subject subject)
+ {
+ //get all the roles of the various types
+ String[] roleClassNames = getRoleClassNames();
+ Collection<String> groups = new LinkedHashSet<String>();
+ try
+ {
+ for (String roleClassName : roleClassNames)
+ {
+ Class load_class = Thread.currentThread().getContextClassLoader().loadClass(roleClassName);
+ Set<Principal> rolesForType = subject.getPrincipals(load_class);
+ for (Principal principal : rolesForType)
+ {
+ groups.add(principal.getName());
+ }
+ }
+
+ return groups.toArray(new String[groups.size()]);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASPrincipal.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASPrincipal.java
new file mode 100644
index 0000000000..6aa158cf36
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASPrincipal.java
@@ -0,0 +1,89 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.jaas;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+
+
+/* ---------------------------------------------------- */
+/** JAASPrincipal
+ * <p>Impl class of Principal interface.
+ *
+ * <p><h4>Notes</h4>
+ * <p>
+ *
+ * <p><h4>Usage</h4>
+ * <pre>
+ */
+/*
+ * </pre>
+ *
+ * @see
+ * @version 1.0 Tue Apr 15 2003
+ *
+ */
+public class JAASPrincipal implements Principal, Serializable
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5538962177019315479L;
+
+ private String _name = null;
+
+
+ public JAASPrincipal(String userName)
+ {
+ this._name = userName;
+ }
+
+
+ public boolean equals (Object p)
+ {
+ if (! (p instanceof JAASPrincipal))
+ return false;
+
+ return getName().equals(((JAASPrincipal)p).getName());
+ }
+
+
+ public int hashCode ()
+ {
+ return getName().hashCode();
+ }
+
+
+ public String getName ()
+ {
+ return this._name;
+ }
+
+
+ public String toString ()
+ {
+ return getName();
+ }
+
+
+
+}
+
+
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/package-info.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASRole.java
index dae277ef35..d29b1af8f7 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/package-info.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASRole.java
@@ -16,8 +16,27 @@
// ========================================================================
//
-/**
- * Jetty Plus : Limited Additional JEE Webapp Support
- */
-package org.eclipse.jetty.plus.webapp;
+package org.eclipse.jetty.plus.jaas;
+
+public class JAASRole extends JAASPrincipal
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 3465114254970134526L;
+
+ public JAASRole(String name)
+ {
+ super (name);
+ }
+
+ public boolean equals (Object o)
+ {
+ if (! (o instanceof JAASRole))
+ return false;
+
+ return getName().equals(((JAASRole)o).getName());
+ }
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASUserPrincipal.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASUserPrincipal.java
new file mode 100644
index 0000000000..e2b4c5df32
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASUserPrincipal.java
@@ -0,0 +1,79 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.jaas;
+
+import java.security.Principal;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+
+
+
+/* ---------------------------------------------------- */
+/** JAASUserPrincipal
+ * <p>Implements the JAAS version of the
+ * org.eclipse.jetty.http.UserPrincipal interface.
+ *
+ * @version $Id: JAASUserPrincipal.java 4780 2009-03-17 15:36:08Z jesse $
+ *
+ */
+public class JAASUserPrincipal implements Principal
+{
+ private final String _name;
+ private final Subject _subject;
+ private final LoginContext _loginContext;
+
+ /* ------------------------------------------------ */
+
+ public JAASUserPrincipal(String name, Subject subject, LoginContext loginContext)
+ {
+ this._name = name;
+ this._subject = subject;
+ this._loginContext = loginContext;
+ }
+
+ /* ------------------------------------------------ */
+ /** Get the name identifying the user
+ */
+ public String getName ()
+ {
+ return _name;
+ }
+
+
+ /* ------------------------------------------------ */
+ /** Provide access to the Subject
+ * @return subject
+ */
+ public Subject getSubject ()
+ {
+ return this._subject;
+ }
+
+ LoginContext getLoginContext ()
+ {
+ return this._loginContext;
+ }
+
+ public String toString()
+ {
+ return getName();
+ }
+
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/package-info.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/RoleCheckPolicy.java
index 2865c35471..ad99895d1e 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/package-info.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/RoleCheckPolicy.java
@@ -16,8 +16,21 @@
// ========================================================================
//
-/**
- * Jetty Plus : Limited JEE Annotation Support
- */
-package org.eclipse.jetty.plus.annotation;
+package org.eclipse.jetty.plus.jaas;
+import java.security.Principal;
+import java.security.acl.Group;
+
+
+public interface RoleCheckPolicy
+{
+ /* ------------------------------------------------ */
+ /** Check if a role is either a runAsRole or in a set of roles
+ * @param roleName the role to check
+ * @param runAsRole a pushed role (can be null)
+ * @param roles a Group whose Principals are role names
+ * @return <code>true</code> if <code>role</code> equals <code>runAsRole</code> or is a member of <code>roles</code>.
+ */
+ public boolean checkRole (String roleName, Principal runAsRole, Group roles);
+
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/StrictRoleCheckPolicy.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/StrictRoleCheckPolicy.java
new file mode 100644
index 0000000000..9da82eedc2
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/StrictRoleCheckPolicy.java
@@ -0,0 +1,63 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.jaas;
+
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Enumeration;
+
+
+/* ---------------------------------------------------- */
+/** StrictRoleCheckPolicy
+ * <p>Enforces that if a runAsRole is present, then the
+ * role to check must be the same as that runAsRole and
+ * the set of static roles is ignored.
+ *
+ *
+ *
+ * @org.apache.xbean.XBean description ="Check only topmost role in stack of roles for user"
+ */
+public class StrictRoleCheckPolicy implements RoleCheckPolicy
+{
+
+ public boolean checkRole (String roleName, Principal runAsRole, Group roles)
+ {
+ //check if this user has had any temporary role pushed onto
+ //them. If so, then only check if the user has that role.
+ if (runAsRole != null)
+ {
+ return (roleName.equals(runAsRole.getName()));
+ }
+ else
+ {
+ if (roles == null)
+ return false;
+ Enumeration<? extends Principal> rolesEnum = roles.members();
+ boolean found = false;
+ while (rolesEnum.hasMoreElements() && !found)
+ {
+ Principal p = (Principal)rolesEnum.nextElement();
+ found = roleName.equals(p.getName());
+ }
+ return found;
+ }
+
+ }
+
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/callback/AbstractCallbackHandler.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/callback/AbstractCallbackHandler.java
new file mode 100644
index 0000000000..a5791a17ab
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/callback/AbstractCallbackHandler.java
@@ -0,0 +1,60 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.jaas.callback;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+
+public abstract class AbstractCallbackHandler implements CallbackHandler
+{
+ protected String _userName;
+ protected Object _credential;
+
+ public void setUserName (String userName)
+ {
+ _userName = userName;
+ }
+
+ public String getUserName ()
+ {
+ return _userName;
+ }
+
+
+ public void setCredential (Object credential)
+ {
+ _credential = credential;
+ }
+
+ public Object getCredential ()
+ {
+ return _credential;
+ }
+
+ public void handle (Callback[] callbacks)
+ throws IOException, UnsupportedCallbackException
+ {
+ }
+
+
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/callback/DefaultCallbackHandler.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/callback/DefaultCallbackHandler.java
new file mode 100644
index 0000000000..6c6580c4ee
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/callback/DefaultCallbackHandler.java
@@ -0,0 +1,97 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.jaas.callback;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.eclipse.jetty.util.security.Password;
+import org.eclipse.jetty.server.Request;
+
+
+
+/* ---------------------------------------------------- */
+/** DefaultUsernameCredentialCallbackHandler
+ * <p>
+ *
+ * <p><h4>Notes</h4>
+ * <p>
+ *
+ * <p><h4>Usage</h4>
+ * <pre>
+ */
+/*
+ * </pre>
+ *
+ * @see
+ * @version 1.0 Tue Apr 15 2003
+ *
+ */
+public class DefaultCallbackHandler extends AbstractCallbackHandler
+{
+
+ private Request _request;
+
+ public void setRequest (Request request)
+ {
+ this._request = request;
+ }
+
+ public void handle (Callback[] callbacks)
+ throws IOException, UnsupportedCallbackException
+ {
+ for (int i=0; i < callbacks.length; i++)
+ {
+ if (callbacks[i] instanceof NameCallback)
+ {
+ ((NameCallback)callbacks[i]).setName(getUserName());
+ }
+ else if (callbacks[i] instanceof ObjectCallback)
+ {
+ ((ObjectCallback)callbacks[i]).setObject(getCredential());
+ }
+ else if (callbacks[i] instanceof PasswordCallback)
+ {
+ if (getCredential() instanceof Password)
+ ((PasswordCallback)callbacks[i]).setPassword (((Password)getCredential()).toString().toCharArray());
+ else if (getCredential() instanceof String)
+ {
+ ((PasswordCallback)callbacks[i]).setPassword (((String)getCredential()).toCharArray());
+ }
+ else
+ throw new UnsupportedCallbackException (callbacks[i], "User supplied credentials cannot be converted to char[] for PasswordCallback: try using an ObjectCallback instead");
+ }
+ else if (callbacks[i] instanceof RequestParameterCallback)
+ {
+ RequestParameterCallback callback = (RequestParameterCallback)callbacks[i];
+ callback.setParameterValues(Arrays.asList(_request.getParameterValues(callback.getParameterName())));
+ }
+ else
+ throw new UnsupportedCallbackException(callbacks[i]);
+ }
+
+ }
+
+}
+
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/package-info.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/callback/ObjectCallback.java
index b3d3c14838..6a49d9ae13 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/package-info.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/callback/ObjectCallback.java
@@ -16,8 +16,52 @@
// ========================================================================
//
-/**
- * Jetty Plus : Limited JEE Jndi Support
+package org.eclipse.jetty.plus.jaas.callback;
+
+import javax.security.auth.callback.Callback;
+
+
+/* ---------------------------------------------------- */
+/** ObjectCallback
+ *
+ * <p>Can be used as a LoginModule Callback to
+ * obtain a user's credential as an Object, rather than
+ * a char[], to which some credentials may not be able
+ * to be converted
+ *
+ * <p><h4>Notes</h4>
+ * <p>
+ *
+ * <p><h4>Usage</h4>
+ * <pre>
+ */
+/*
+ * </pre>
+ *
+ * @see
+ * @version 1.0 Tue Apr 15 2003
+ *
*/
-package org.eclipse.jetty.plus.jndi;
+public class ObjectCallback implements Callback
+{
+
+ protected Object _object;
+
+ public void setObject(Object o)
+ {
+ _object = o;
+ }
+
+ public Object getObject ()
+ {
+ return _object;
+ }
+
+ public void clearObject ()
+ {
+ _object = null;
+ }
+
+
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/callback/RequestParameterCallback.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/callback/RequestParameterCallback.java
new file mode 100644
index 0000000000..3129983384
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/callback/RequestParameterCallback.java
@@ -0,0 +1,61 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.jaas.callback;
+
+import java.util.List;
+
+import javax.security.auth.callback.Callback;
+
+
+/**
+ *
+ * RequestParameterCallback
+ *
+ * Allows a JAAS callback handler to access any parameter from the j_security_check FORM.
+ * This means that a LoginModule can access form fields other than the j_username and j_password
+ * fields, and use it, for example, to authenticate a user.
+ *
+ *
+ * @version $Revision: 4780 $ $Date: 2009-03-17 16:36:08 +0100 (Tue, 17 Mar 2009) $
+ *
+ */
+public class RequestParameterCallback implements Callback
+{
+ private String _paramName;
+ private List<?> _paramValues;
+
+ public void setParameterName (String name)
+ {
+ _paramName = name;
+ }
+ public String getParameterName ()
+ {
+ return _paramName;
+ }
+
+ public void setParameterValues (List<?> values)
+ {
+ _paramValues = values;
+ }
+
+ public List<?> getParameterValues ()
+ {
+ return _paramValues;
+ }
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/AbstractDatabaseLoginModule.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/AbstractDatabaseLoginModule.java
new file mode 100644
index 0000000000..dc48576518
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/AbstractDatabaseLoginModule.java
@@ -0,0 +1,144 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.jaas.spi;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+import org.eclipse.jetty.util.security.Credential;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+/**
+ * AbstractDatabaseLoginModule
+ *
+ * Abstract base class for LoginModules that interact with a
+ * database to retrieve authentication and authorization information.
+ * Used by the JDBCLoginModule and DataSourceLoginModule.
+ *
+ */
+public abstract class AbstractDatabaseLoginModule extends AbstractLoginModule
+{
+ private static final Logger LOG = Log.getLogger(AbstractDatabaseLoginModule.class);
+
+ private String userQuery;
+ private String rolesQuery;
+ private String dbUserTable;
+ private String dbUserTableUserField;
+ private String dbUserTableCredentialField;
+ private String dbUserRoleTable;
+ private String dbUserRoleTableUserField;
+ private String dbUserRoleTableRoleField;
+
+
+
+
+ /**
+ * @return a java.sql.Connection from the database
+ * @throws Exception
+ */
+ public abstract Connection getConnection () throws Exception;
+
+
+
+ /* ------------------------------------------------ */
+ /** Load info from database
+ * @param userName user info to load
+ * @exception SQLException
+ */
+ public UserInfo getUserInfo (String userName)
+ throws Exception
+ {
+ Connection connection = null;
+
+ try
+ {
+ connection = getConnection();
+
+ //query for credential
+ PreparedStatement statement = connection.prepareStatement (userQuery);
+ statement.setString (1, userName);
+ ResultSet results = statement.executeQuery();
+ String dbCredential = null;
+ if (results.next())
+ {
+ dbCredential = results.getString(1);
+ }
+ results.close();
+ statement.close();
+
+ //query for role names
+ statement = connection.prepareStatement (rolesQuery);
+ statement.setString (1, userName);
+ results = statement.executeQuery();
+ List<String> roles = new ArrayList<String>();
+
+ while (results.next())
+ {
+ String roleName = results.getString (1);
+ roles.add (roleName);
+ }
+
+ results.close();
+ statement.close();
+
+ return dbCredential==null ? null : new UserInfo (userName,
+ Credential.getCredential(dbCredential), roles);
+ }
+ finally
+ {
+ if (connection != null) connection.close();
+ }
+ }
+
+
+ public void initialize(Subject subject,
+ CallbackHandler callbackHandler,
+ Map<String,?> sharedState,
+ Map<String,?> options)
+ {
+ super.initialize(subject, callbackHandler, sharedState, options);
+
+ //get the user credential query out of the options
+ dbUserTable = (String)options.get("userTable");
+ dbUserTableUserField = (String)options.get("userField");
+ dbUserTableCredentialField = (String)options.get("credentialField");
+
+ userQuery = "select "+dbUserTableCredentialField+" from "+dbUserTable+" where "+dbUserTableUserField+"=?";
+
+
+ //get the user roles query out of the options
+ dbUserRoleTable = (String)options.get("userRoleTable");
+ dbUserRoleTableUserField = (String)options.get("userRoleUserField");
+ dbUserRoleTableRoleField = (String)options.get("userRoleRoleField");
+
+ rolesQuery = "select "+dbUserRoleTableRoleField+" from "+dbUserRoleTable+" where "+dbUserRoleTableUserField+"=?";
+
+ if(LOG.isDebugEnabled())LOG.debug("userQuery = "+userQuery);
+ if(LOG.isDebugEnabled())LOG.debug("rolesQuery = "+rolesQuery);
+ }
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/AbstractLoginModule.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/AbstractLoginModule.java
new file mode 100644
index 0000000000..f22258e2a0
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/AbstractLoginModule.java
@@ -0,0 +1,289 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.jaas.spi;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+import org.eclipse.jetty.plus.jaas.JAASPrincipal;
+import org.eclipse.jetty.plus.jaas.JAASRole;
+import org.eclipse.jetty.plus.jaas.callback.ObjectCallback;
+
+/**
+ * AbstractLoginModule
+ *
+ * Abstract base class for all LoginModules. Subclasses should
+ * just need to implement getUserInfo method.
+ *
+ */
+public abstract class AbstractLoginModule implements LoginModule
+{
+ private CallbackHandler callbackHandler;
+
+ private boolean authState = false;
+ private boolean commitState = false;
+ private JAASUserInfo currentUser;
+ private Subject subject;
+
+ public class JAASUserInfo
+ {
+ private UserInfo user;
+ private Principal principal;
+ private List<JAASRole> roles;
+
+ public JAASUserInfo (UserInfo u)
+ {
+ setUserInfo(u);
+ }
+
+ public String getUserName ()
+ {
+ return this.user.getUserName();
+ }
+
+ public Principal getPrincipal()
+ {
+ return this.principal;
+ }
+
+ public void setUserInfo (UserInfo u)
+ {
+ this.user = u;
+ this.principal = new JAASPrincipal(u.getUserName());
+ this.roles = new ArrayList<JAASRole>();
+ if (u.getRoleNames() != null)
+ {
+ Iterator<String> itor = u.getRoleNames().iterator();
+ while (itor.hasNext())
+ this.roles.add(new JAASRole((String)itor.next()));
+ }
+ }
+
+ public void setJAASInfo (Subject subject)
+ {
+ subject.getPrincipals().add(this.principal);
+ subject.getPrivateCredentials().add(this.user.getCredential());
+ subject.getPrincipals().addAll(roles);
+ }
+
+ public void unsetJAASInfo (Subject subject)
+ {
+ subject.getPrincipals().remove(this.principal);
+ subject.getPrivateCredentials().remove(this.user.getCredential());
+ subject.getPrincipals().removeAll(this.roles);
+ }
+
+ public boolean checkCredential (Object suppliedCredential)
+ {
+ return this.user.checkCredential(suppliedCredential);
+ }
+ }
+
+
+
+ public Subject getSubject ()
+ {
+ return this.subject;
+ }
+
+ public void setSubject (Subject s)
+ {
+ this.subject = s;
+ }
+
+ public JAASUserInfo getCurrentUser()
+ {
+ return this.currentUser;
+ }
+
+ public void setCurrentUser (JAASUserInfo u)
+ {
+ this.currentUser = u;
+ }
+
+ public CallbackHandler getCallbackHandler()
+ {
+ return this.callbackHandler;
+ }
+
+ public void setCallbackHandler(CallbackHandler h)
+ {
+ this.callbackHandler = h;
+ }
+
+ public boolean isAuthenticated()
+ {
+ return this.authState;
+ }
+
+ public boolean isCommitted ()
+ {
+ return this.commitState;
+ }
+
+ public void setAuthenticated (boolean authState)
+ {
+ this.authState = authState;
+ }
+
+ public void setCommitted (boolean commitState)
+ {
+ this.commitState = commitState;
+ }
+ /**
+ * @see javax.security.auth.spi.LoginModule#abort()
+ * @throws LoginException
+ */
+ public boolean abort() throws LoginException
+ {
+ this.currentUser = null;
+ return (isAuthenticated() && isCommitted());
+ }
+
+ /**
+ * @see javax.security.auth.spi.LoginModule#commit()
+ * @return true if committed, false if not (likely not authenticated)
+ * @throws LoginException
+ */
+ public boolean commit() throws LoginException
+ {
+
+ if (!isAuthenticated())
+ {
+ currentUser = null;
+ setCommitted(false);
+ return false;
+ }
+
+ setCommitted(true);
+ currentUser.setJAASInfo(subject);
+ return true;
+ }
+
+
+ public Callback[] configureCallbacks ()
+ {
+
+ Callback[] callbacks = new Callback[3];
+ callbacks[0] = new NameCallback("Enter user name");
+ callbacks[1] = new ObjectCallback();
+ callbacks[2] = new PasswordCallback("Enter password", false); //only used if framework does not support the ObjectCallback
+ return callbacks;
+ }
+
+
+
+ public abstract UserInfo getUserInfo (String username) throws Exception;
+
+
+
+ /**
+ * @see javax.security.auth.spi.LoginModule#login()
+ * @return true if is authenticated, false otherwise
+ * @throws LoginException
+ */
+ public boolean login() throws LoginException
+ {
+ try
+ {
+ if (callbackHandler == null)
+ throw new LoginException ("No callback handler");
+
+ Callback[] callbacks = configureCallbacks();
+ callbackHandler.handle(callbacks);
+
+ String webUserName = ((NameCallback)callbacks[0]).getName();
+ Object webCredential = null;
+
+ webCredential = ((ObjectCallback)callbacks[1]).getObject(); //first check if ObjectCallback has the credential
+ if (webCredential == null)
+ webCredential = ((PasswordCallback)callbacks[2]).getPassword(); //use standard PasswordCallback
+
+ if ((webUserName == null) || (webCredential == null))
+ {
+ setAuthenticated(false);
+ return isAuthenticated();
+ }
+
+ UserInfo userInfo = getUserInfo(webUserName);
+
+ if (userInfo == null)
+ {
+ setAuthenticated(false);
+ return isAuthenticated();
+ }
+
+ currentUser = new JAASUserInfo(userInfo);
+ setAuthenticated(currentUser.checkCredential(webCredential));
+ return isAuthenticated();
+ }
+ catch (IOException e)
+ {
+ throw new LoginException (e.toString());
+ }
+ catch (UnsupportedCallbackException e)
+ {
+ throw new LoginException (e.toString());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ throw new LoginException (e.toString());
+ }
+ }
+
+ /**
+ * @see javax.security.auth.spi.LoginModule#logout()
+ * @return true always
+ * @throws LoginException
+ */
+ public boolean logout() throws LoginException
+ {
+ this.currentUser.unsetJAASInfo(this.subject);
+ return true;
+ }
+
+ /**
+ * @see javax.security.auth.spi.LoginModule#initialize(javax.security.auth.Subject, javax.security.auth.callback.CallbackHandler, java.util.Map, java.util.Map)
+ * @param subject
+ * @param callbackHandler
+ * @param sharedState
+ * @param options
+ */
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map<String,?> sharedState, Map<String,?> options)
+ {
+ this.callbackHandler = callbackHandler;
+ this.subject = subject;
+ }
+
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/DataSourceLoginModule.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/DataSourceLoginModule.java
new file mode 100644
index 0000000000..303e5d44f8
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/DataSourceLoginModule.java
@@ -0,0 +1,89 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.jaas.spi;
+import java.sql.Connection;
+import java.util.Map;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.sql.DataSource;
+
+/**
+ * DataSourceLoginModule
+ *
+ * A LoginModule that uses a DataSource to retrieve user authentication
+ * and authorisation information.
+ *
+ * @see JDBCLoginModule
+ */
+public class DataSourceLoginModule extends AbstractDatabaseLoginModule
+{
+
+ private String dbJNDIName;
+ private DataSource dataSource;
+
+ /* ------------------------------------------------ */
+ /** Init LoginModule.
+ * Called once by JAAS after new instance created.
+ * @param subject
+ * @param callbackHandler
+ * @param sharedState
+ * @param options
+ */
+ public void initialize(Subject subject,
+ CallbackHandler callbackHandler,
+ Map<String,?> sharedState,
+ Map<String,?> options)
+ {
+ try
+ {
+ super.initialize(subject, callbackHandler, sharedState, options);
+
+ //get the datasource jndi name
+ dbJNDIName = (String)options.get("dbJNDIName");
+
+ InitialContext ic = new InitialContext();
+ dataSource = (DataSource)ic.lookup("java:comp/env/"+dbJNDIName);
+ }
+ catch (NamingException e)
+ {
+ throw new IllegalStateException (e.toString());
+ }
+ }
+
+
+ /**
+ * Get a connection from the DataSource
+ * @see AbstractDatabaseLoginModule#getConnection()
+ * @return the connection for the datasource
+ * @throws Exception
+ */
+ public Connection getConnection ()
+ throws Exception
+ {
+ return dataSource.getConnection();
+ }
+
+
+
+
+
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/JDBCLoginModule.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/JDBCLoginModule.java
new file mode 100644
index 0000000000..4243636105
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/JDBCLoginModule.java
@@ -0,0 +1,127 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.jaas.spi;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+import org.eclipse.jetty.util.Loader;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+
+
+/* ---------------------------------------------------- */
+/** JDBCLoginModule
+ * <p>JAAS LoginModule to retrieve user information from
+ * a database and authenticate the user.
+ *
+ * <p><h4>Notes</h4>
+ * <p>This version uses plain old JDBC connections NOT
+ * Datasources.
+ *
+ * <p><h4>Usage</h4>
+ * <pre>
+ * </pre>
+ *
+ * @version 1.0 Tue Apr 15 2003
+ */
+public class JDBCLoginModule extends AbstractDatabaseLoginModule
+{
+ private static final Logger LOG = Log.getLogger(JDBCLoginModule.class);
+
+ private String dbDriver;
+ private String dbUrl;
+ private String dbUserName;
+ private String dbPassword;
+
+
+ /**
+ * Get a connection from the DriverManager
+ * @see AbstractDatabaseLoginModule#getConnection()
+ * @return the connection for this datasource
+ * @throws Exception
+ */
+ public Connection getConnection ()
+ throws Exception
+ {
+ if (!((dbDriver != null)
+ &&
+ (dbUrl != null)))
+ throw new IllegalStateException ("Database connection information not configured");
+
+ if(LOG.isDebugEnabled())LOG.debug("Connecting using dbDriver="+dbDriver+"+ dbUserName="+dbUserName+", dbPassword="+dbUrl);
+
+ return DriverManager.getConnection (dbUrl,
+ dbUserName,
+ dbPassword);
+ }
+
+
+
+ /* ------------------------------------------------ */
+ /** Init LoginModule.
+ * Called once by JAAS after new instance created.
+ * @param subject
+ * @param callbackHandler
+ * @param sharedState
+ * @param options
+ */
+ public void initialize(Subject subject,
+ CallbackHandler callbackHandler,
+ Map<String,?> sharedState,
+ Map<String,?> options)
+ {
+ try
+ {
+ super.initialize(subject, callbackHandler, sharedState, options);
+
+ //get the jdbc username/password, jdbc url out of the options
+ dbDriver = (String)options.get("dbDriver");
+ dbUrl = (String)options.get("dbUrl");
+ dbUserName = (String)options.get("dbUserName");
+ dbPassword = (String)options.get("dbPassword");
+
+ if (dbUserName == null)
+ dbUserName = "";
+
+ if (dbPassword == null)
+ dbPassword = "";
+
+ if (dbDriver != null)
+ Loader.loadClass(this.getClass(), dbDriver).newInstance();
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new IllegalStateException (e.toString());
+ }
+ catch (InstantiationException e)
+ {
+ throw new IllegalStateException (e.toString());
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new IllegalStateException (e.toString());
+ }
+ }
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/LdapLoginModule.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/LdapLoginModule.java
new file mode 100644
index 0000000000..584c1a4f0f
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/LdapLoginModule.java
@@ -0,0 +1,689 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.jaas.spi;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.naming.Context;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+
+import org.eclipse.jetty.util.security.Credential;
+import org.eclipse.jetty.plus.jaas.callback.ObjectCallback;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+/**
+ * A LdapLoginModule for use with JAAS setups
+ * <p/>
+ * The jvm should be started with the following parameter:
+ * <br><br>
+ * <code>
+ * -Djava.security.auth.login.config=etc/ldap-loginModule.conf
+ * </code>
+ * <br><br>
+ * and an example of the ldap-loginModule.conf would be:
+ * <br><br>
+ * <pre>
+ * ldaploginmodule {
+ * org.eclipse.jetty.server.server.plus.jaas.spi.LdapLoginModule required
+ * debug="true"
+ * useLdaps="false"
+ * contextFactory="com.sun.jndi.ldap.LdapCtxFactory"
+ * hostname="ldap.example.com"
+ * port="389"
+ * bindDn="cn=Directory Manager"
+ * bindPassword="directory"
+ * authenticationMethod="simple"
+ * forceBindingLogin="false"
+ * userBaseDn="ou=people,dc=alcatel"
+ * userRdnAttribute="uid"
+ * userIdAttribute="uid"
+ * userPasswordAttribute="userPassword"
+ * userObjectClass="inetOrgPerson"
+ * roleBaseDn="ou=groups,dc=example,dc=com"
+ * roleNameAttribute="cn"
+ * roleMemberAttribute="uniqueMember"
+ * roleObjectClass="groupOfUniqueNames";
+ * };
+ * </pre>
+ *
+ *
+ *
+ *
+ */
+public class LdapLoginModule extends AbstractLoginModule
+{
+ private static final Logger LOG = Log.getLogger(LdapLoginModule.class);
+
+ /**
+ * hostname of the ldap server
+ */
+ private String _hostname;
+
+ /**
+ * port of the ldap server
+ */
+ private int _port;
+
+ /**
+ * Context.SECURITY_AUTHENTICATION
+ */
+ private String _authenticationMethod;
+
+ /**
+ * Context.INITIAL_CONTEXT_FACTORY
+ */
+ private String _contextFactory;
+
+ /**
+ * root DN used to connect to
+ */
+ private String _bindDn;
+
+ /**
+ * password used to connect to the root ldap context
+ */
+ private String _bindPassword;
+
+ /**
+ * object class of a user
+ */
+ private String _userObjectClass = "inetOrgPerson";
+
+ /**
+ * attribute that the principal is located
+ */
+ private String _userRdnAttribute = "uid";
+
+ /**
+ * attribute that the principal is located
+ */
+ private String _userIdAttribute = "cn";
+
+ /**
+ * name of the attribute that a users password is stored under
+ * <p/>
+ * NOTE: not always accessible, see force binding login
+ */
+ private String _userPasswordAttribute = "userPassword";
+
+ /**
+ * base DN where users are to be searched from
+ */
+ private String _userBaseDn;
+
+ /**
+ * base DN where role membership is to be searched from
+ */
+ private String _roleBaseDn;
+
+ /**
+ * object class of roles
+ */
+ private String _roleObjectClass = "groupOfUniqueNames";
+
+ /**
+ * name of the attribute that a username would be under a role class
+ */
+ private String _roleMemberAttribute = "uniqueMember";
+
+ /**
+ * the name of the attribute that a role would be stored under
+ */
+ private String _roleNameAttribute = "roleName";
+
+ private boolean _debug;
+
+ /**
+ * if the getUserInfo can pull a password off of the user then
+ * password comparison is an option for authn, to force binding
+ * login checks, set this to true
+ */
+ private boolean _forceBindingLogin = false;
+
+ /**
+ * When true changes the protocol to ldaps
+ */
+ private boolean _useLdaps = false;
+
+ private DirContext _rootContext;
+
+ /**
+ * get the available information about the user
+ * <p/>
+ * for this LoginModule, the credential can be null which will result in a
+ * binding ldap authentication scenario
+ * <p/>
+ * roles are also an optional concept if required
+ *
+ * @param username
+ * @return the userinfo for the username
+ * @throws Exception
+ */
+ public UserInfo getUserInfo(String username) throws Exception
+ {
+ String pwdCredential = getUserCredentials(username);
+
+ if (pwdCredential == null)
+ {
+ return null;
+ }
+
+ pwdCredential = convertCredentialLdapToJetty(pwdCredential);
+ Credential credential = Credential.getCredential(pwdCredential);
+ List<String> roles = getUserRoles(_rootContext, username);
+
+ return new UserInfo(username, credential, roles);
+ }
+
+ protected String doRFC2254Encoding(String inputString)
+ {
+ StringBuffer buf = new StringBuffer(inputString.length());
+ for (int i = 0; i < inputString.length(); i++)
+ {
+ char c = inputString.charAt(i);
+ switch (c)
+ {
+ case '\\':
+ buf.append("\\5c");
+ break;
+ case '*':
+ buf.append("\\2a");
+ break;
+ case '(':
+ buf.append("\\28");
+ break;
+ case ')':
+ buf.append("\\29");
+ break;
+ case '\0':
+ buf.append("\\00");
+ break;
+ default:
+ buf.append(c);
+ break;
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ * attempts to get the users credentials from the users context
+ * <p/>
+ * NOTE: this is not an user authenticated operation
+ *
+ * @param username
+ * @return
+ * @throws LoginException
+ */
+ private String getUserCredentials(String username) throws LoginException
+ {
+ String ldapCredential = null;
+
+ SearchControls ctls = new SearchControls();
+ ctls.setCountLimit(1);
+ ctls.setDerefLinkFlag(true);
+ ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+
+ String filter = "(&(objectClass={0})({1}={2}))";
+
+ LOG.debug("Searching for users with filter: \'" + filter + "\'" + " from base dn: " + _userBaseDn);
+
+ try
+ {
+ Object[] filterArguments = {_userObjectClass, _userIdAttribute, username};
+ NamingEnumeration<SearchResult> results = _rootContext.search(_userBaseDn, filter, filterArguments, ctls);
+
+ LOG.debug("Found user?: " + results.hasMoreElements());
+
+ if (!results.hasMoreElements())
+ {
+ throw new LoginException("User not found.");
+ }
+
+ SearchResult result = findUser(username);
+
+ Attributes attributes = result.getAttributes();
+
+ Attribute attribute = attributes.get(_userPasswordAttribute);
+ if (attribute != null)
+ {
+ try
+ {
+ byte[] value = (byte[]) attribute.get();
+
+ ldapCredential = new String(value);
+ }
+ catch (NamingException e)
+ {
+ LOG.debug("no password available under attribute: " + _userPasswordAttribute);
+ }
+ }
+ }
+ catch (NamingException e)
+ {
+ throw new LoginException("Root context binding failure.");
+ }
+
+ LOG.debug("user cred is: " + ldapCredential);
+
+ return ldapCredential;
+ }
+
+ /**
+ * attempts to get the users roles from the root context
+ * <p/>
+ * NOTE: this is not an user authenticated operation
+ *
+ * @param dirContext
+ * @param username
+ * @return
+ * @throws LoginException
+ */
+ private List<String> getUserRoles(DirContext dirContext, String username) throws LoginException, NamingException
+ {
+ String userDn = _userRdnAttribute + "=" + username + "," + _userBaseDn;
+
+ return getUserRolesByDn(dirContext, userDn);
+ }
+
+ private List<String> getUserRolesByDn(DirContext dirContext, String userDn) throws LoginException, NamingException
+ {
+ List<String> roleList = new ArrayList<String>();
+
+ if (dirContext == null || _roleBaseDn == null || _roleMemberAttribute == null || _roleObjectClass == null)
+ {
+ return roleList;
+ }
+
+ SearchControls ctls = new SearchControls();
+ ctls.setDerefLinkFlag(true);
+ ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+ ctls.setReturningAttributes(new String[]{_roleNameAttribute});
+
+ String filter = "(&(objectClass={0})({1}={2}))";
+ Object[] filterArguments = {_roleObjectClass, _roleMemberAttribute, userDn};
+ NamingEnumeration<SearchResult> results = dirContext.search(_roleBaseDn, filter, filterArguments, ctls);
+
+ LOG.debug("Found user roles?: " + results.hasMoreElements());
+
+ while (results.hasMoreElements())
+ {
+ SearchResult result = (SearchResult) results.nextElement();
+
+ Attributes attributes = result.getAttributes();
+
+ if (attributes == null)
+ {
+ continue;
+ }
+
+ Attribute roleAttribute = attributes.get(_roleNameAttribute);
+
+ if (roleAttribute == null)
+ {
+ continue;
+ }
+
+ NamingEnumeration<?> roles = roleAttribute.getAll();
+ while (roles.hasMore())
+ {
+ roleList.add(roles.next().toString());
+ }
+ }
+
+ return roleList;
+ }
+
+
+ /**
+ * since ldap uses a context bind for valid authentication checking, we override login()
+ * <p/>
+ * if credentials are not available from the users context or if we are forcing the binding check
+ * then we try a binding authentication check, otherwise if we have the users encoded password then
+ * we can try authentication via that mechanic
+ *
+ * @return true if authenticated, false otherwise
+ * @throws LoginException
+ */
+ public boolean login() throws LoginException
+ {
+ try
+ {
+ if (getCallbackHandler() == null)
+ {
+ throw new LoginException("No callback handler");
+ }
+
+ Callback[] callbacks = configureCallbacks();
+ getCallbackHandler().handle(callbacks);
+
+ String webUserName = ((NameCallback) callbacks[0]).getName();
+ Object webCredential = ((ObjectCallback) callbacks[1]).getObject();
+
+ if (webUserName == null || webCredential == null)
+ {
+ setAuthenticated(false);
+ return isAuthenticated();
+ }
+
+ if (_forceBindingLogin)
+ {
+ return bindingLogin(webUserName, webCredential);
+ }
+
+ // This sets read and the credential
+ UserInfo userInfo = getUserInfo(webUserName);
+
+ if (userInfo == null)
+ {
+ setAuthenticated(false);
+ return false;
+ }
+
+ setCurrentUser(new JAASUserInfo(userInfo));
+
+ if (webCredential instanceof String)
+ {
+ return credentialLogin(Credential.getCredential((String) webCredential));
+ }
+
+ return credentialLogin(webCredential);
+ }
+ catch (UnsupportedCallbackException e)
+ {
+ throw new LoginException("Error obtaining callback information.");
+ }
+ catch (IOException e)
+ {
+ if (_debug)
+ {
+ e.printStackTrace();
+ }
+ throw new LoginException("IO Error performing login.");
+ }
+ catch (Exception e)
+ {
+ if (_debug)
+ {
+ e.printStackTrace();
+ }
+ throw new LoginException("Error obtaining user info.");
+ }
+ }
+
+ /**
+ * password supplied authentication check
+ *
+ * @param webCredential
+ * @return true if authenticated
+ * @throws LoginException
+ */
+ protected boolean credentialLogin(Object webCredential) throws LoginException
+ {
+ setAuthenticated(getCurrentUser().checkCredential(webCredential));
+ return isAuthenticated();
+ }
+
+ /**
+ * binding authentication check
+ * This method of authentication works only if the user branch of the DIT (ldap tree)
+ * has an ACI (access control instruction) that allow the access to any user or at least
+ * for the user that logs in.
+ *
+ * @param username
+ * @param password
+ * @return true always
+ * @throws LoginException
+ */
+ public boolean bindingLogin(String username, Object password) throws LoginException, NamingException
+ {
+ SearchResult searchResult = findUser(username);
+
+ String userDn = searchResult.getNameInNamespace();
+
+ LOG.info("Attempting authentication: " + userDn);
+
+ Hashtable<Object,Object> environment = getEnvironment();
+ environment.put(Context.SECURITY_PRINCIPAL, userDn);
+ environment.put(Context.SECURITY_CREDENTIALS, password);
+
+ DirContext dirContext = new InitialDirContext(environment);
+ List<String> roles = getUserRolesByDn(dirContext, userDn);
+
+ UserInfo userInfo = new UserInfo(username, null, roles);
+ setCurrentUser(new JAASUserInfo(userInfo));
+ setAuthenticated(true);
+
+ return true;
+ }
+
+ private SearchResult findUser(String username) throws NamingException, LoginException
+ {
+ SearchControls ctls = new SearchControls();
+ ctls.setCountLimit(1);
+ ctls.setDerefLinkFlag(true);
+ ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+
+ String filter = "(&(objectClass={0})({1}={2}))";
+
+ LOG.info("Searching for users with filter: \'" + filter + "\'" + " from base dn: " + _userBaseDn);
+
+ Object[] filterArguments = new Object[]{
+ _userObjectClass,
+ _userIdAttribute,
+ username
+ };
+ NamingEnumeration<SearchResult> results = _rootContext.search(_userBaseDn, filter, filterArguments, ctls);
+
+ LOG.info("Found user?: " + results.hasMoreElements());
+
+ if (!results.hasMoreElements())
+ {
+ throw new LoginException("User not found.");
+ }
+
+ return (SearchResult) results.nextElement();
+ }
+
+
+ /**
+ * Init LoginModule.
+ * Called once by JAAS after new instance is created.
+ *
+ * @param subject
+ * @param callbackHandler
+ * @param sharedState
+ * @param options
+ */
+ public void initialize(Subject subject,
+ CallbackHandler callbackHandler,
+ Map<String,?> sharedState,
+ Map<String,?> options)
+ {
+ super.initialize(subject, callbackHandler, sharedState, options);
+
+ _hostname = (String) options.get("hostname");
+ _port = Integer.parseInt((String) options.get("port"));
+ _contextFactory = (String) options.get("contextFactory");
+ _bindDn = (String) options.get("bindDn");
+ _bindPassword = (String) options.get("bindPassword");
+ _authenticationMethod = (String) options.get("authenticationMethod");
+
+ _userBaseDn = (String) options.get("userBaseDn");
+
+ _roleBaseDn = (String) options.get("roleBaseDn");
+
+ if (options.containsKey("forceBindingLogin"))
+ {
+ _forceBindingLogin = Boolean.parseBoolean((String) options.get("forceBindingLogin"));
+ }
+
+ if (options.containsKey("useLdaps"))
+ {
+ _useLdaps = Boolean.parseBoolean((String) options.get("useLdaps"));
+ }
+
+ _userObjectClass = getOption(options, "userObjectClass", _userObjectClass);
+ _userRdnAttribute = getOption(options, "userRdnAttribute", _userRdnAttribute);
+ _userIdAttribute = getOption(options, "userIdAttribute", _userIdAttribute);
+ _userPasswordAttribute = getOption(options, "userPasswordAttribute", _userPasswordAttribute);
+ _roleObjectClass = getOption(options, "roleObjectClass", _roleObjectClass);
+ _roleMemberAttribute = getOption(options, "roleMemberAttribute", _roleMemberAttribute);
+ _roleNameAttribute = getOption(options, "roleNameAttribute", _roleNameAttribute);
+ _debug = Boolean.parseBoolean(String.valueOf(getOption(options, "debug", Boolean.toString(_debug))));
+
+ try
+ {
+ _rootContext = new InitialDirContext(getEnvironment());
+ }
+ catch (NamingException ex)
+ {
+ throw new IllegalStateException("Unable to establish root context", ex);
+ }
+ }
+
+ public boolean commit() throws LoginException
+ {
+ try
+ {
+ _rootContext.close();
+ }
+ catch (NamingException e)
+ {
+ throw new LoginException( "error closing root context: " + e.getMessage() );
+ }
+
+ return super.commit();
+ }
+
+ public boolean abort() throws LoginException
+ {
+ try
+ {
+ _rootContext.close();
+ }
+ catch (NamingException e)
+ {
+ throw new LoginException( "error closing root context: " + e.getMessage() );
+ }
+
+ return super.abort();
+ }
+
+ private String getOption(Map<String,?> options, String key, String defaultValue)
+ {
+ Object value = options.get(key);
+
+ if (value == null)
+ {
+ return defaultValue;
+ }
+
+ return (String) value;
+ }
+
+ /**
+ * get the context for connection
+ *
+ * @return the environment details for the context
+ */
+ public Hashtable<Object, Object> getEnvironment()
+ {
+ Properties env = new Properties();
+
+ env.put(Context.INITIAL_CONTEXT_FACTORY, _contextFactory);
+
+ if (_hostname != null)
+ {
+ env.put(Context.PROVIDER_URL, (_useLdaps?"ldaps://":"ldap://") + _hostname + (_port==0?"":":"+_port) +"/");
+ }
+
+ if (_authenticationMethod != null)
+ {
+ env.put(Context.SECURITY_AUTHENTICATION, _authenticationMethod);
+ }
+
+ if (_bindDn != null)
+ {
+ env.put(Context.SECURITY_PRINCIPAL, _bindDn);
+ }
+
+ if (_bindPassword != null)
+ {
+ env.put(Context.SECURITY_CREDENTIALS, _bindPassword);
+ }
+
+ return env;
+ }
+
+ public static String convertCredentialJettyToLdap(String encryptedPassword)
+ {
+ if ("MD5:".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
+ {
+ return "{MD5}" + encryptedPassword.substring("MD5:".length(), encryptedPassword.length());
+ }
+
+ if ("CRYPT:".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
+ {
+ return "{CRYPT}" + encryptedPassword.substring("CRYPT:".length(), encryptedPassword.length());
+ }
+
+ return encryptedPassword;
+ }
+
+ public static String convertCredentialLdapToJetty(String encryptedPassword)
+ {
+ if (encryptedPassword == null)
+ {
+ return encryptedPassword;
+ }
+
+ if ("{MD5}".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
+ {
+ return "MD5:" + encryptedPassword.substring("{MD5}".length(), encryptedPassword.length());
+ }
+
+ if ("{CRYPT}".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
+ {
+ return "CRYPT:" + encryptedPassword.substring("{CRYPT}".length(), encryptedPassword.length());
+ }
+
+ return encryptedPassword;
+ }
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/PropertyFileLoginModule.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/PropertyFileLoginModule.java
new file mode 100644
index 0000000000..ab5ee46aa7
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/PropertyFileLoginModule.java
@@ -0,0 +1,134 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.jaas.spi;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+import org.eclipse.jetty.util.security.Credential;
+import org.eclipse.jetty.security.PropertyUserStore;
+import org.eclipse.jetty.server.UserIdentity;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+/**
+ * PropertyFileLoginModule
+ *
+ *
+ */
+public class PropertyFileLoginModule extends AbstractLoginModule
+{
+ public static final String DEFAULT_FILENAME = "realm.properties";
+
+ private static final Logger LOG = Log.getLogger(PropertyFileLoginModule.class);
+
+ private static ConcurrentHashMap<String, PropertyUserStore> _propertyUserStores = new ConcurrentHashMap<String, PropertyUserStore>();
+
+ private int _refreshInterval = 0;
+ private String _filename = DEFAULT_FILENAME;
+
+ /**
+ * Read contents of the configured property file.
+ *
+ * @see javax.security.auth.spi.LoginModule#initialize(javax.security.auth.Subject, javax.security.auth.callback.CallbackHandler, java.util.Map,
+ * java.util.Map)
+ * @param subject
+ * @param callbackHandler
+ * @param sharedState
+ * @param options
+ */
+ public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options)
+ {
+ super.initialize(subject,callbackHandler,sharedState,options);
+ setupPropertyUserStore(options);
+ }
+
+ private void setupPropertyUserStore(Map<String, ?> options)
+ {
+ parseConfig(options);
+
+ if (_propertyUserStores.get(_filename) == null)
+ {
+ PropertyUserStore propertyUserStore = new PropertyUserStore();
+ propertyUserStore.setConfig(_filename);
+ propertyUserStore.setRefreshInterval(_refreshInterval);
+
+ PropertyUserStore prev = _propertyUserStores.putIfAbsent(_filename, propertyUserStore);
+ if (prev == null)
+ {
+ LOG.debug("setupPropertyUserStore: Starting new PropertyUserStore. PropertiesFile: " + _filename + " refreshInterval: " + _refreshInterval);
+
+ try
+ {
+ propertyUserStore.start();
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Exception while starting propertyUserStore: ",e);
+ }
+ }
+ }
+ }
+
+ private void parseConfig(Map<String, ?> options)
+ {
+ _filename = (String)options.get("file");
+ _filename = (_filename == null? DEFAULT_FILENAME : _filename);
+ String refreshIntervalString = (String)options.get("refreshInterval");
+ _refreshInterval = refreshIntervalString == null?_refreshInterval:Integer.parseInt(refreshIntervalString);
+ }
+
+ /**
+ * Don't implement this as we want to pre-fetch all of the users.
+ *
+ * @param userName
+ * @throws Exception
+ */
+ public UserInfo getUserInfo(String userName) throws Exception
+ {
+ PropertyUserStore propertyUserStore = _propertyUserStores.get(_filename);
+ if (propertyUserStore == null)
+ throw new IllegalStateException("PropertyUserStore should never be null here!");
+
+ UserIdentity userIdentity = propertyUserStore.getUserIdentity(userName);
+ if(userIdentity==null)
+ return null;
+
+ Set<Principal> principals = userIdentity.getSubject().getPrincipals();
+
+ List<String> roles = new ArrayList<String>();
+
+ for ( Principal principal : principals )
+ {
+ roles.add( principal.getName() );
+ }
+
+ Credential credential = (Credential)userIdentity.getSubject().getPrivateCredentials().iterator().next();
+ LOG.debug("Found: " + userName + " in PropertyUserStore");
+ return new UserInfo(userName, credential, roles);
+ }
+
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/UserInfo.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/UserInfo.java
new file mode 100644
index 0000000000..225e3fa25d
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/UserInfo.java
@@ -0,0 +1,73 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.jaas.spi;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jetty.util.security.Credential;
+
+/**
+ * UserInfo
+ *
+ * This is the information read from the external source
+ * about a user.
+ *
+ * Can be cached by a UserInfoCache implementation
+ */
+public class UserInfo
+{
+
+ private String _userName;
+ private Credential _credential;
+ private List<String> _roleNames;
+
+
+ public UserInfo (String userName, Credential credential, List<String> roleNames)
+ {
+ _userName = userName;
+ _credential = credential;
+ _roleNames = new ArrayList<String>();
+ if (roleNames != null)
+ {
+ _roleNames.addAll(roleNames);
+ }
+ }
+
+ public String getUserName()
+ {
+ return this._userName;
+ }
+
+ public List<String> getRoleNames ()
+ {
+ return new ArrayList<String>(_roleNames);
+ }
+
+ public boolean checkCredential (Object suppliedCredential)
+ {
+ return _credential.check(suppliedCredential);
+ }
+
+ protected Credential getCredential ()
+ {
+ return _credential;
+ }
+
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingEntryUtil.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingEntryUtil.java
index 20c0ef95d9..64ce0a3979 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingEntryUtil.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingEntryUtil.java
@@ -38,11 +38,11 @@ import org.eclipse.jetty.util.log.Logger;
public class NamingEntryUtil
{
private static Logger __log = NamingUtil.__log;
-
+
/**
* Link a name in a webapp's java:/comp/evn namespace to a pre-existing
* resource. The pre-existing resource can be either in the webapp's
- * naming environment, or in the container's naming environment. Webapp's
+ * naming environment, or in the container's naming environment. Webapp's
* environment takes precedence over the server's namespace.
*
* @param scope the scope of the lookup
@@ -52,28 +52,28 @@ public class NamingEntryUtil
*/
public static boolean bindToENC (Object scope, String asName, String mappedName)
throws NamingException
- {
+ {
if (asName==null||asName.trim().equals(""))
throw new NamingException ("No name for NamingEntry");
if (mappedName==null || "".equals(mappedName))
mappedName=asName;
-
+
NamingEntry entry = lookupNamingEntry (scope, mappedName);
if (entry == null)
return false;
-
+
entry.bindToENC(asName);
return true;
}
-
-
-
+
+
+
/**
* Find a NamingEntry in the given scope.
- *
+ *
* @param scope
* @param jndiName
* @return the naming entry for the given scope
@@ -84,12 +84,12 @@ public class NamingEntryUtil
{
NamingEntry entry = null;
try
- {
+ {
Name scopeName = getNameForScope(scope);
- InitialContext ic = new InitialContext();
+ InitialContext ic = new InitialContext();
NameParser parser = ic.getNameParser("");
- Name namingEntryName = makeNamingEntryName(parser, jndiName);
- scopeName.addAll(namingEntryName);
+ Name namingEntryName = makeNamingEntryName(parser, jndiName);
+ scopeName.addAll(namingEntryName);
entry = (NamingEntry)ic.lookup(scopeName);
}
catch (NameNotFoundException ee)
@@ -98,7 +98,7 @@ public class NamingEntryUtil
return entry;
}
-
+
public static Object lookup(Object scope, String jndiName) throws NamingException
{
Name scopeName = getNameForScope(scope);
@@ -108,18 +108,18 @@ public class NamingEntryUtil
return ic.lookup(scopeName);
}
- /**
+ /**
* Get all NameEntries of a certain type in the given naming
* environment scope (server-wide names or context-specific names)
- *
- * @param scope
+ *
+ * @param scope
* @param clazz the type of the entry
* @return all NameEntries of a certain type in the given naming environment scope (server-wide names or context-specific names)
* @throws NamingException
*/
public static List<Object> lookupNamingEntries (Object scope, Class<?> clazz)
throws NamingException
- {
+ {
try
{
Context scopeContext = getContextForScope(scope);
@@ -130,35 +130,35 @@ public class NamingEntryUtil
}
catch (NameNotFoundException e)
{
- return Collections.emptyList();
+ return Collections.emptyList();
}
}
-
-
+
+
public static Name makeNamingEntryName (NameParser parser, NamingEntry namingEntry)
throws NamingException
{
return makeNamingEntryName(parser, (namingEntry==null?null:namingEntry.getJndiName()));
}
-
+
public static Name makeNamingEntryName (NameParser parser, String jndiName)
throws NamingException
{
if (jndiName==null)
return null;
-
+
if (parser==null)
{
InitialContext ic = new InitialContext();
parser = ic.getNameParser("");
}
-
+
Name name = parser.parse("");
name.add(NamingEntry.__contextName);
name.addAll(parser.parse(jndiName));
return name;
}
-
+
public static Name getNameForScope (Object scope)
{
@@ -170,7 +170,7 @@ public class NamingEntryUtil
if (scope != null)
{
name.add(canonicalizeScope(scope));
- }
+ }
return name;
}
catch (NamingException e)
@@ -189,10 +189,10 @@ public class NamingEntryUtil
if (scope != null)
{
name.add(canonicalizeScope(scope));
- }
+ }
return (Context)ic.lookup(name);
}
-
+
public static Context getContextForNamingEntries (Object scope)
throws NamingException
{
@@ -202,7 +202,7 @@ public class NamingEntryUtil
/**
* Build up a list of NamingEntry objects that are of a specific type.
- *
+ *
* @param list
* @param context
* @param clazz
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java
index 96e9ae0e1d..1c48ff298f 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java
@@ -24,7 +24,6 @@ import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -78,13 +77,13 @@ public class DataSourceLoginService extends MappedLoginService
public DataSourceLoginService()
{
}
-
+
/* ------------------------------------------------------------ */
public DataSourceLoginService(String name)
{
setName(name);
}
-
+
/* ------------------------------------------------------------ */
public DataSourceLoginService(String name, IdentityService identityService)
{
@@ -285,38 +284,36 @@ public class DataSourceLoginService extends MappedLoginService
/* ------------------------------------------------------------ */
/** Load user's info from database.
- *
+ *
* @param userName
*/
@Override
protected UserIdentity loadUser (String userName)
{
+ Connection connection = null;
try
- {
+ {
initDb();
- try (Connection connection = getConnection();
- PreparedStatement statement1 = connection.prepareStatement(_userSql))
+ connection = getConnection();
+
+ PreparedStatement statement = connection.prepareStatement(_userSql);
+ statement.setObject(1, userName);
+ ResultSet rs = statement.executeQuery();
+
+ if (rs.next())
{
- statement1.setObject(1, userName);
- try (ResultSet rs1 = statement1.executeQuery())
- {
- if (rs1.next())
- {
- int key = rs1.getInt(_userTableKey);
- String credentials = rs1.getString(_userTablePasswordField);
- List<String> roles = new ArrayList<String>();
- try (PreparedStatement statement2 = connection.prepareStatement(_roleSql))
- {
- statement2.setInt(1, key);
- try (ResultSet rs2 = statement2.executeQuery())
- {
- while (rs2.next())
- roles.add(rs2.getString(_roleTableRoleField));
- }
- }
- return putUser(userName,new Password(credentials), roles.toArray(new String[roles.size()]));
- }
- }
+ int key = rs.getInt(_userTableKey);
+ String credentials = rs.getString(_userTablePasswordField);
+ statement.close();
+
+ statement = connection.prepareStatement(_roleSql);
+ statement.setInt(1, key);
+ rs = statement.executeQuery();
+ List<String> roles = new ArrayList<String>();
+ while (rs.next())
+ roles.add(rs.getString(_roleTableRoleField));
+ statement.close();
+ return putUser(userName,new Password(credentials), roles.toArray(new String[roles.size()]));
}
}
catch (NamingException e)
@@ -327,28 +324,46 @@ public class DataSourceLoginService extends MappedLoginService
{
LOG.warn("Problem loading user info for "+userName, e);
}
+ finally
+ {
+ if (connection != null)
+ {
+ try
+ {
+ connection.close();
+ }
+ catch (SQLException x)
+ {
+ LOG.warn("Problem closing connection", x);
+ }
+ finally
+ {
+ connection = null;
+ }
+ }
+ }
return null;
}
-
+
/* ------------------------------------------------------------ */
/**
* Lookup the datasource for the jndiName and formulate the
* necessary sql query strings based on the configured table
* and column names.
- *
+ *
* @throws NamingException
*/
public void initDb() throws NamingException, SQLException
{
if (_datasource != null)
return;
-
+
@SuppressWarnings("unused")
InitialContext ic = new InitialContext();
assert ic!=null;
-
+
//TODO webapp scope?
-
+
//try finding the datasource in the Server scope
if (_server != null)
{
@@ -361,7 +376,7 @@ public class DataSourceLoginService extends MappedLoginService
//next try the jvm scope
}
}
-
+
//try finding the datasource in the jvm scope
if (_datasource==null)
@@ -370,111 +385,110 @@ public class DataSourceLoginService extends MappedLoginService
}
// set up the select statements based on the table and column names configured
- _userSql = "select " + _userTableKey + "," + _userTablePasswordField
- + " from " + _userTableName
+ _userSql = "select " + _userTableKey + "," + _userTablePasswordField
+ + " from " + _userTableName
+ " where "+ _userTableUserField + " = ?";
-
+
_roleSql = "select r." + _roleTableRoleField
- + " from " + _roleTableName + " r, " + _userRoleTableName
+ + " from " + _roleTableName + " r, " + _userRoleTableName
+ " u where u."+ _userRoleTableUserKey + " = ?"
+ " and r." + _roleTableKey + " = u." + _userRoleTableRoleKey;
-
+
prepareTables();
}
-
-
-
+
+
+
private void prepareTables()
throws NamingException, SQLException
{
+ Connection connection = null;
+ boolean autocommit = true;
+
if (_createTables)
{
- boolean autocommit = true;
- Connection connection = getConnection();
- try (Statement stmt = connection.createStatement())
+ try
{
+ connection = getConnection();
autocommit = connection.getAutoCommit();
connection.setAutoCommit(false);
DatabaseMetaData metaData = connection.getMetaData();
-
+
//check if tables exist
String tableName = (metaData.storesLowerCaseIdentifiers()? _userTableName.toLowerCase(Locale.ENGLISH): (metaData.storesUpperCaseIdentifiers()?_userTableName.toUpperCase(Locale.ENGLISH): _userTableName));
- try (ResultSet result = metaData.getTables(null, null, tableName, null))
- {
- if (!result.next())
- {
- //user table default
- /*
- * create table _userTableName (_userTableKey integer,
- * _userTableUserField varchar(100) not null unique,
- * _userTablePasswordField varchar(20) not null, primary key(_userTableKey));
- */
- stmt.executeUpdate("create table "+_userTableName+ "("+_userTableKey+" integer,"+
- _userTableUserField+" varchar(100) not null unique,"+
- _userTablePasswordField+" varchar(20) not null, primary key("+_userTableKey+"))");
- if (LOG.isDebugEnabled()) LOG.debug("Created table "+_userTableName);
- }
+ ResultSet result = metaData.getTables(null, null, tableName, null);
+ if (!result.next())
+ {
+ //user table default
+ /*
+ * create table _userTableName (_userTableKey integer,
+ * _userTableUserField varchar(100) not null unique,
+ * _userTablePasswordField varchar(20) not null, primary key(_userTableKey));
+ */
+ connection.createStatement().executeUpdate("create table "+_userTableName+ "("+_userTableKey+" integer,"+
+ _userTableUserField+" varchar(100) not null unique,"+
+ _userTablePasswordField+" varchar(20) not null, primary key("+_userTableKey+"))");
+ if (LOG.isDebugEnabled()) LOG.debug("Created table "+_userTableName);
}
+
+ result.close();
tableName = (metaData.storesLowerCaseIdentifiers()? _roleTableName.toLowerCase(Locale.ENGLISH): (metaData.storesUpperCaseIdentifiers()?_roleTableName.toUpperCase(Locale.ENGLISH): _roleTableName));
- try (ResultSet result = metaData.getTables(null, null, tableName, null))
+ result = metaData.getTables(null, null, tableName, null);
+ if (!result.next())
{
- if (!result.next())
- {
- //role table default
- /*
- * create table _roleTableName (_roleTableKey integer,
- * _roleTableRoleField varchar(100) not null unique, primary key(_roleTableKey));
- */
- String str = "create table "+_roleTableName+" ("+_roleTableKey+" integer, "+
- _roleTableRoleField+" varchar(100) not null unique, primary key("+_roleTableKey+"))";
- stmt.executeUpdate(str);
- if (LOG.isDebugEnabled()) LOG.debug("Created table "+_roleTableName);
- }
+ //role table default
+ /*
+ * create table _roleTableName (_roleTableKey integer,
+ * _roleTableRoleField varchar(100) not null unique, primary key(_roleTableKey));
+ */
+ String str = "create table "+_roleTableName+" ("+_roleTableKey+" integer, "+
+ _roleTableRoleField+" varchar(100) not null unique, primary key("+_roleTableKey+"))";
+ connection.createStatement().executeUpdate(str);
+ if (LOG.isDebugEnabled()) LOG.debug("Created table "+_roleTableName);
}
+
+ result.close();
tableName = (metaData.storesLowerCaseIdentifiers()? _userRoleTableName.toLowerCase(Locale.ENGLISH): (metaData.storesUpperCaseIdentifiers()?_userRoleTableName.toUpperCase(Locale.ENGLISH): _userRoleTableName));
- try (ResultSet result = metaData.getTables(null, null, tableName, null))
+ result = metaData.getTables(null, null, tableName, null);
+ if (!result.next())
{
- if (!result.next())
- {
- //user-role table
- /*
- * create table _userRoleTableName (_userRoleTableUserKey integer,
- * _userRoleTableRoleKey integer,
- * primary key (_userRoleTableUserKey, _userRoleTableRoleKey));
- *
- * create index idx_user_role on _userRoleTableName (_userRoleTableUserKey);
- */
- stmt.executeUpdate("create table "+_userRoleTableName+" ("+_userRoleTableUserKey+" integer, "+
- _userRoleTableRoleKey+" integer, "+
- "primary key ("+_userRoleTableUserKey+", "+_userRoleTableRoleKey+"))");
- stmt.executeUpdate("create index indx_user_role on "+_userRoleTableName+"("+_userRoleTableUserKey+")");
- if (LOG.isDebugEnabled()) LOG.debug("Created table "+_userRoleTableName +" and index");
- }
+ //user-role table
+ /*
+ * create table _userRoleTableName (_userRoleTableUserKey integer,
+ * _userRoleTableRoleKey integer,
+ * primary key (_userRoleTableUserKey, _userRoleTableRoleKey));
+ *
+ * create index idx_user_role on _userRoleTableName (_userRoleTableUserKey);
+ */
+ connection.createStatement().executeUpdate("create table "+_userRoleTableName+" ("+_userRoleTableUserKey+" integer, "+
+ _userRoleTableRoleKey+" integer, "+
+ "primary key ("+_userRoleTableUserKey+", "+_userRoleTableRoleKey+"))");
+ connection.createStatement().executeUpdate("create index indx_user_role on "+_userRoleTableName+"("+_userRoleTableUserKey+")");
+ if (LOG.isDebugEnabled()) LOG.debug("Created table "+_userRoleTableName +" and index");
}
+
+ result.close();
connection.commit();
}
finally
{
- try
- {
- connection.setAutoCommit(autocommit);
- }
- catch (SQLException e)
- {
- if (LOG.isDebugEnabled()) LOG.debug("Prepare tables", e);
- }
- finally
+ if (connection != null)
{
try
{
+ connection.setAutoCommit(autocommit);
connection.close();
}
catch (SQLException e)
{
if (LOG.isDebugEnabled()) LOG.debug("Prepare tables", e);
}
+ finally
+ {
+ connection = null;
+ }
}
}
}
@@ -483,9 +497,9 @@ public class DataSourceLoginService extends MappedLoginService
LOG.debug("createTables false");
}
}
-
-
- private Connection getConnection ()
+
+
+ private Connection getConnection ()
throws NamingException, SQLException
{
initDb();
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/package-info.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/package-info.java
deleted file mode 100644
index 33606e8b7b..0000000000
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-/**
- * Jetty Plus : Limited JEE Security Support
- */
-package org.eclipse.jetty.plus.security;
-
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/servlet/ServletHandler.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/servlet/ServletHandler.java
new file mode 100644
index 0000000000..ab2e127f63
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/servlet/ServletHandler.java
@@ -0,0 +1,76 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.plus.servlet;
+
+import org.eclipse.jetty.plus.annotation.InjectionCollection;
+import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
+
+/**
+ * ServletHandler
+ *
+ *
+ */
+public class ServletHandler extends org.eclipse.jetty.servlet.ServletHandler
+{
+
+ private InjectionCollection _injections = null;
+ private LifeCycleCallbackCollection _callbacks = null;
+
+
+
+ /**
+ * @return the callbacks
+ */
+ public LifeCycleCallbackCollection getCallbacks()
+ {
+ return _callbacks;
+ }
+
+
+
+ /**
+ * @param callbacks the callbacks to set
+ */
+ public void setCallbacks(LifeCycleCallbackCollection callbacks)
+ {
+ this._callbacks = callbacks;
+ }
+
+
+
+ /**
+ * @return the injections
+ */
+ public InjectionCollection getInjections()
+ {
+ return _injections;
+ }
+
+
+
+ /**
+ * @param injections the injections to set
+ */
+ public void setInjections(InjectionCollection injections)
+ {
+ this._injections = injections;
+ }
+
+
+}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/EnvConfiguration.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/EnvConfiguration.java
index 26227f1555..0fb9c43ed3 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/EnvConfiguration.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/EnvConfiguration.java
@@ -31,7 +31,6 @@ import javax.naming.Name;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
-import org.eclipse.jetty.jndi.ContextFactory;
import org.eclipse.jetty.jndi.NamingContext;
import org.eclipse.jetty.jndi.NamingUtil;
import org.eclipse.jetty.jndi.local.localContextRoot;
@@ -62,26 +61,26 @@ public class EnvConfiguration extends AbstractConfiguration
this.jettyEnvXmlUrl = url;
}
- /**
+ /**
* @see Configuration#configure(WebAppContext)
* @throws Exception
*/
@Override
public void preConfigure (WebAppContext context) throws Exception
- {
+ {
//create a java:comp/env
createEnvContext(context);
}
- /**
+ /**
* @throws Exception
*/
@Override
public void configure (WebAppContext context) throws Exception
- {
+ {
if (LOG.isDebugEnabled())
LOG.debug("Created java:comp/env for webapp "+context.getContextPath());
-
+
//check to see if an explicit file has been set, if not,
//look in WEB-INF/jetty-env.xml
if (jettyEnvXmlUrl == null)
@@ -98,7 +97,7 @@ public class EnvConfiguration extends AbstractConfiguration
}
}
}
-
+
if (jettyEnvXmlUrl != null)
{
synchronized (localContextRoot.getRoot())
@@ -136,8 +135,8 @@ public class EnvConfiguration extends AbstractConfiguration
bindEnvEntries(context);
}
-
- /**
+
+ /**
* Remove jndi setup from start
* @see Configuration#deconfigure(WebAppContext)
* @throws Exception
@@ -148,7 +147,6 @@ public class EnvConfiguration extends AbstractConfiguration
//get rid of any bindings for comp/env for webapp
ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(context.getClassLoader());
- ContextFactory.associateClassLoader(context.getClassLoader());
try
{
Context ic = new InitialContext();
@@ -172,13 +170,12 @@ public class EnvConfiguration extends AbstractConfiguration
}
finally
{
- ContextFactory.disassociateClassLoader();
Thread.currentThread().setContextClassLoader(oldLoader);
}
}
-
- /**
+
+ /**
* Remove all jndi setup
* @see Configuration#deconfigure(WebAppContext)
* @throws Exception
@@ -187,7 +184,7 @@ public class EnvConfiguration extends AbstractConfiguration
public void destroy (WebAppContext context) throws Exception
{
try
- {
+ {
//unbind any NamingEntries that were configured in this webapp's name space
NamingContext scopeContext = (NamingContext)NamingEntryUtil.getContextForScope(context);
scopeContext.getParent().destroySubcontext(scopeContext.getName());
@@ -198,11 +195,11 @@ public class EnvConfiguration extends AbstractConfiguration
LOG.debug("No naming entries configured in environment for webapp "+context);
}
}
-
+
/**
* Bind all EnvEntries that have been declared, so that the processing of the
* web.xml file can potentially override them.
- *
+ *
* We first bind EnvEntries declared in Server scope, then WebAppContext scope.
* @throws NamingException
*/
@@ -220,11 +217,11 @@ public class EnvConfiguration extends AbstractConfiguration
EnvEntry ee = (EnvEntry)itor.next();
ee.bindToENC(ee.getJndiName());
Name namingEntryName = NamingEntryUtil.makeNamingEntryName(null, ee);
- NamingUtil.bind(envCtx, namingEntryName.toString(), ee);//also save the EnvEntry in the context so we can check it later
+ NamingUtil.bind(envCtx, namingEntryName.toString(), ee);//also save the EnvEntry in the context so we can check it later
}
-
+
LOG.debug("Binding env entries from the server scope");
-
+
scope = context.getServer();
list = NamingEntryUtil.lookupNamingEntries(scope, EnvEntry.class);
itor = list.iterator();
@@ -233,9 +230,9 @@ public class EnvConfiguration extends AbstractConfiguration
EnvEntry ee = (EnvEntry)itor.next();
ee.bindToENC(ee.getJndiName());
Name namingEntryName = NamingEntryUtil.makeNamingEntryName(null, ee);
- NamingUtil.bind(envCtx, namingEntryName.toString(), ee);//also save the EnvEntry in the context so we can check it later
+ NamingUtil.bind(envCtx, namingEntryName.toString(), ee);//also save the EnvEntry in the context so we can check it later
}
-
+
LOG.debug("Binding env entries from the context scope");
scope = context;
list = NamingEntryUtil.lookupNamingEntries(scope, EnvEntry.class);
@@ -247,27 +244,25 @@ public class EnvConfiguration extends AbstractConfiguration
Name namingEntryName = NamingEntryUtil.makeNamingEntryName(null, ee);
NamingUtil.bind(envCtx, namingEntryName.toString(), ee);//also save the EnvEntry in the context so we can check it later
}
- }
-
+ }
+
protected void createEnvContext (WebAppContext wac)
throws NamingException
{
ClassLoader old_loader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(wac.getClassLoader());
- ContextFactory.associateClassLoader(wac.getClassLoader());
try
{
Context context = new InitialContext();
Context compCtx = (Context)context.lookup ("java:comp");
compCtx.createSubcontext("env");
}
- finally
+ finally
{
- ContextFactory.disassociateClassLoader();
- Thread.currentThread().setContextClassLoader(old_loader);
- }
+ Thread.currentThread().setContextClassLoader(old_loader);
+ }
}
-
+
private static class Bound
{
final NamingContext _context;
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/PlusConfiguration.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/PlusConfiguration.java
index 3962994d5d..178e17391a 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/PlusConfiguration.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/PlusConfiguration.java
@@ -43,18 +43,18 @@ public class PlusConfiguration extends AbstractConfiguration
private static final Logger LOG = Log.getLogger(PlusConfiguration.class);
private Integer _key;
-
+
@Override
public void preConfigure (WebAppContext context)
throws Exception
- {
- context.addDecorator(new PlusDecorator(context));
+ {
+ context.addDecorator(new PlusDecorator(context));
}
-
+
@Override
public void cloneConfigure(WebAppContext template, WebAppContext context) throws Exception
{
- context.addDecorator(new PlusDecorator(context));
+ context.addDecorator(new PlusDecorator(context));
}
@Override
@@ -62,7 +62,7 @@ public class PlusConfiguration extends AbstractConfiguration
throws Exception
{
bindUserTransaction(context);
-
+
context.getMetaData().addDescriptorProcessor(new PlusDescriptorProcessor());
}
@@ -82,7 +82,7 @@ public class PlusConfiguration extends AbstractConfiguration
context.setAttribute(InjectionCollection.INJECTION_COLLECTION,null);
context.setAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION,null);
}
-
+
public void bindUserTransaction (WebAppContext context)
throws Exception
{
@@ -92,12 +92,12 @@ public class PlusConfiguration extends AbstractConfiguration
}
catch (NameNotFoundException e)
{
- LOG.debug("No Transaction manager found - if your webapp requires one, please configure one.");
+ LOG.info("No Transaction manager found - if your webapp requires one, please configure one.");
}
}
-
-
-
+
+
+
protected void lockCompEnv (WebAppContext wac)
throws Exception
{
@@ -116,7 +116,7 @@ public class PlusConfiguration extends AbstractConfiguration
Thread.currentThread().setContextClassLoader(old_loader);
}
}
-
+
protected void unlockCompEnv (WebAppContext wac)
throws Exception
{
@@ -129,7 +129,7 @@ public class PlusConfiguration extends AbstractConfiguration
{
Context context = new InitialContext();
Context compCtx = (Context)context.lookup("java:comp");
- compCtx.addToEnvironment("org.eclipse.jndi.unlock", _key);
+ compCtx.addToEnvironment("org.eclipse.jndi.unlock", _key);
}
finally
{
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/PlusDecorator.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/PlusDecorator.java
index 68f50bcb3b..4b4f19f5e5 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/PlusDecorator.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/PlusDecorator.java
@@ -57,7 +57,7 @@ public class PlusDecorator implements Decorator
public void decorateFilterHolder(FilterHolder filter) throws ServletException
{
}
-
+
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateFilterInstance(javax.servlet.Filter)
@@ -86,7 +86,7 @@ public class PlusDecorator implements Decorator
{
decorate(holder);
}
-
+
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#decorateServletInstance(javax.servlet.Servlet)
@@ -116,7 +116,7 @@ public class PlusDecorator implements Decorator
destroy(s);
}
- /**
+ /**
* @see org.eclipse.jetty.servlet.ServletContextHandler.Decorator#destroyListenerInstance(java.util.EventListener)
*/
public void destroyListenerInstance(EventListener l)
@@ -125,14 +125,14 @@ public class PlusDecorator implements Decorator
}
- protected void decorate (Object o)
+ protected void decorate (Object o)
throws ServletException
- {
+ {
RunAsCollection runAses = (RunAsCollection)_context.getAttribute(RunAsCollection.RUNAS_COLLECTION);
if (runAses != null)
runAses.setRunAs(o);
-
+
InjectionCollection injections = (InjectionCollection)_context.getAttribute(InjectionCollection.INJECTION_COLLECTION);
if (injections != null)
injections.inject(o);
@@ -149,11 +149,11 @@ public class PlusDecorator implements Decorator
throw new ServletException(e);
}
}
- }
-
+ }
+
protected void destroy (Object o)
{
- LifeCycleCallbackCollection callbacks = (LifeCycleCallbackCollection)_context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
+ LifeCycleCallbackCollection callbacks = (LifeCycleCallbackCollection)_context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
if (callbacks != null)
{
try
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/PlusDescriptorProcessor.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/PlusDescriptorProcessor.java
index bddd017acd..beb9f9e7be 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/PlusDescriptorProcessor.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/PlusDescriptorProcessor.java
@@ -73,11 +73,11 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
}
}
- /**
+ /**
* @see org.eclipse.jetty.webapp.IterativeDescriptorProcessor#start(WebAppContext, org.eclipse.jetty.webapp.Descriptor)
*/
public void start(WebAppContext context, Descriptor descriptor)
- {
+ {
InjectionCollection injections = (InjectionCollection)context.getAttribute(InjectionCollection.INJECTION_COLLECTION);
if (injections == null)
@@ -97,24 +97,24 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
if (runAsCollection == null)
{
runAsCollection = new RunAsCollection();
- context.setAttribute(RunAsCollection.RUNAS_COLLECTION, runAsCollection);
+ context.setAttribute(RunAsCollection.RUNAS_COLLECTION, runAsCollection);
}
}
-
- /**
+
+ /**
* {@inheritDoc}
*/
public void end(WebAppContext context,Descriptor descriptor)
{
}
-
-
-
+
+
+
/**
- * JavaEE 5.4.1.3
- *
+ * JavaEE 5.4.1.3
+ *
* @param node
* @throws Exception
*/
@@ -124,7 +124,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
String name=node.getString("env-entry-name",false,true);
String type = node.getString("env-entry-type",false,true);
String valueStr = node.getString("env-entry-value",false,true);
-
+
//if there's no value there's no point in making a jndi entry
//nor processing injection entries
if (valueStr==null || valueStr.equals(""))
@@ -132,7 +132,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
LOG.warn("No value for env-entry-name "+name);
return;
}
-
+
Origin o = context.getMetaData().getOrigin("env-entry."+name);
switch (o)
{
@@ -147,7 +147,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
//of the first one?
addInjections (context, descriptor, node, name, TypeUtil.fromName(type));
Object value = TypeUtil.valueOf(type,valueStr);
- bindEnvEntry(name, value);
+ bindEnvEntry(name, value);
break;
}
case WebXml:
@@ -164,7 +164,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
context.getMetaData().setOrigin("env-entry."+name, descriptor);
addInjections (context, descriptor, node, name, TypeUtil.fromName(type));
Object value = TypeUtil.valueOf(type,valueStr);
- bindEnvEntry(name, value);
+ bindEnvEntry(name, value);
}
else
{
@@ -184,8 +184,8 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
}
}
}
-
-
+
+
/**
* Common Annotations Spec section 2.3:
* resource-ref is for:
@@ -198,11 +198,11 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
* - javax.resource.cci.ConnectionFactory
* - org.omg.CORBA_2_3.ORB
* - any other connection factory defined by a resource adapter
- *
+ *
* TODO
* If web.xml contains a resource-ref with injection targets, all resource-ref entries
* of the same name are ignored in web fragments. If web.xml does not contain any
- * injection-targets, then they are merged from all the fragments.
+ * injection-targets, then they are merged from all the fragments.
* If web.xml does not contain a resource-ref element of same name, but 2 fragments
* declare the same name it is an error.
* resource-ref entries are ONLY for connection factories
@@ -211,20 +211,20 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
* a real resource in the environment. At the moment, we insist that the
* jetty.xml file name of the resource has to be exactly the same as the
* name in web.xml deployment descriptor, but it shouldn't have to be
- *
+ *
* Maintenance update 3.0a to spec:
- * Update Section 8.2.3.h.ii with the following - If a resource reference
- * element is specified in two fragments, while absent from the main web.xml,
- * and all the attributes and child elements of the resource reference element
- * are identical, the resource reference will be merged into the main web.xml.
- * It is considered an error if a resource reference element has the same name
- * specified in two fragments, while absent from the main web.xml and the attributes
- * and child elements are not identical in the two fragments. For example, if two
- * web fragments declare a <resource-ref> with the same <resource-ref-name> element
- * but the type in one is specified as javax.sql.DataSource while the type in the
- * other is that of a java mail resource, then an error must be reported and the
+ * Update Section 8.2.3.h.ii with the following - If a resource reference
+ * element is specified in two fragments, while absent from the main web.xml,
+ * and all the attributes and child elements of the resource reference element
+ * are identical, the resource reference will be merged into the main web.xml.
+ * It is considered an error if a resource reference element has the same name
+ * specified in two fragments, while absent from the main web.xml and the attributes
+ * and child elements are not identical in the two fragments. For example, if two
+ * web fragments declare a <resource-ref> with the same <resource-ref-name> element
+ * but the type in one is specified as javax.sql.DataSource while the type in the
+ * other is that of a java mail resource, then an error must be reported and the
* application MUST fail to deploy.
- *
+ *
* @param node
* @throws Exception
*/
@@ -235,7 +235,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
String type = node.getString("res-type", false, true);
String auth = node.getString("res-auth", false, true);
String shared = node.getString("res-sharing-scope", false, true);
-
+
Origin o = context.getMetaData().getOrigin("resource-ref."+jndiName);
switch (o)
{
@@ -243,45 +243,45 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
{
//No descriptor or annotation previously declared a resource-ref of this name.
context.getMetaData().setOrigin("resource-ref."+jndiName, descriptor);
-
+
//check for <injection> elements
Class<?> typeClass = TypeUtil.fromName(type);
if (typeClass==null)
typeClass = context.loadClass(type);
- addInjections(context, descriptor, node, jndiName, typeClass);
+ addInjections(context, descriptor, node, jndiName, typeClass);
bindResourceRef(context,jndiName, typeClass);
break;
}
case WebXml:
case WebDefaults:
- case WebOverride:
+ case WebOverride:
{
- //A web xml previously declared the resource-ref.
+ //A web xml previously declared the resource-ref.
if (!(descriptor instanceof FragmentDescriptor))
{
//We're processing web-defaults, web.xml or web-override. Any of them can
//set or change the resource-ref.
context.getMetaData().setOrigin("resource-ref."+jndiName, descriptor);
-
+
//check for <injection> elements
Class<?> typeClass = TypeUtil.fromName(type);
if (typeClass==null)
typeClass = context.loadClass(type);
-
+
addInjections(context, descriptor, node, jndiName, typeClass);
-
+
//bind the entry into jndi
bindResourceRef(context,jndiName, typeClass);
}
else
{
- //A web xml declared the resource-ref and we're processing a
- //web-fragment. Check to see if any injections were declared for it by web.xml.
+ //A web xml declared the resource-ref and we're processing a
+ //web-fragment. Check to see if any injections were declared for it by web.xml.
//If any injection was declared in web.xml then don't merge any injections.
//If it was declared in a web-fragment, then we can keep merging fragments.
Descriptor d = context.getMetaData().getOriginDescriptor("resource-ref."+jndiName+".injection");
if (d==null || d instanceof FragmentDescriptor)
- {
+ {
Class<?> typeClass = TypeUtil.fromName(type);
if (typeClass==null)
typeClass = context.loadClass(type);
@@ -291,7 +291,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
break;
}
case WebFragment:
- {
+ {
Descriptor otherFragment = context.getMetaData().getOriginDescriptor("resource-ref."+jndiName);
XmlParser.Node otherFragmentRoot = otherFragment.getRoot();
Iterator<Object> iter = otherFragmentRoot.iterator();
@@ -304,7 +304,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
if ("resource-ref".equals(n.getTag()) && jndiName.equals(n.getString("res-ref-name",false,true)))
otherNode = n;
}
-
+
//If declared in another web-fragment
if (otherNode != null)
{
@@ -312,7 +312,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
String otherType = otherNode.getString("res-type", false, true);
String otherAuth = otherNode.getString("res-auth", false, true);
String otherShared = otherNode.getString("res-sharing-scope", false, true);
-
+
//otherType, otherAuth and otherShared must be the same as type, auth, shared
type = (type == null?"":type);
otherType = (otherType == null?"":otherType);
@@ -320,7 +320,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
otherAuth = (otherAuth == null?"":otherAuth);
shared = (shared == null?"":shared);
otherShared = (otherShared == null?"":otherShared);
-
+
//ServletSpec p.75. No declaration of resource-ref in web xml, but different in multiple web-fragments. Error.
if (!type.equals(otherType) || !auth.equals(otherAuth) || !shared.equals(otherShared))
throw new IllegalStateException("Conflicting resource-ref "+jndiName+" in "+descriptor.getResource());
@@ -329,20 +329,20 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
}
else
throw new IllegalStateException("resource-ref."+jndiName+" not found in declaring descriptor "+otherFragment);
-
+
}
}
-
+
}
-
-
+
+
/**
* Common Annotations Spec section 2.3:
* resource-env-ref is for:
* - javax.transaction.UserTransaction
* - javax.resource.cci.InteractionSpec
* - anything else that is not a connection factory
- *
+ *
* @param node
* @throws Exception
*/
@@ -351,7 +351,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
{
String jndiName = node.getString("resource-env-ref-name",false,true);
String type = node.getString("resource-env-ref-type", false, true);
-
+
Origin o = context.getMetaData().getOrigin("resource-env-ref."+jndiName);
switch (o)
{
@@ -369,7 +369,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
}
case WebXml:
case WebDefaults:
- case WebOverride:
+ case WebOverride:
{
//A resource-env-ref of this name has been declared first in a web xml.
//Only allow other web-default, web.xml, web-override to change it.
@@ -382,7 +382,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
if (typeClass==null)
typeClass = context.loadClass(type);
addInjections (context, descriptor, node, jndiName, typeClass);
- bindResourceEnvRef(context,jndiName, typeClass);
+ bindResourceEnvRef(context,jndiName, typeClass);
}
else
{
@@ -424,8 +424,8 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
//ServletSpec p.75. No declaration of resource-ref in web xml, but different in multiple web-fragments. Error.
if (!type.equals(otherType))
- throw new IllegalStateException("Conflicting resource-env-ref "+jndiName+" in "+descriptor.getResource());
-
+ throw new IllegalStateException("Conflicting resource-env-ref "+jndiName+" in "+descriptor.getResource());
+
//same in multiple web-fragments, merge the injections
addInjections(context, descriptor, node, jndiName, TypeUtil.fromName(type));
}
@@ -450,25 +450,25 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
String jndiName = node.getString("message-destination-ref-name",false,true);
String type = node.getString("message-destination-type",false,true);
String usage = node.getString("message-destination-usage",false,true);
-
+
Origin o = context.getMetaData().getOrigin("message-destination-ref."+jndiName);
switch (o)
{
case NotSet:
- {
+ {
//A message-destination-ref of this name has not been previously declared
Class<?> typeClass = TypeUtil.fromName(type);
if (typeClass==null)
typeClass = context.loadClass(type);
- addInjections(context, descriptor, node, jndiName, typeClass);
+ addInjections(context, descriptor, node, jndiName, typeClass);
bindMessageDestinationRef(context,jndiName, typeClass);
context.getMetaData().setOrigin("message-destination-ref."+jndiName, descriptor);
break;
}
case WebXml:
case WebDefaults:
- case WebOverride:
- {
+ case WebOverride:
+ {
//A message-destination-ref of this name has been declared first in a web xml.
//Only allow other web-default, web.xml, web-override to change it.
if (!(descriptor instanceof FragmentDescriptor))
@@ -476,7 +476,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
Class<?> typeClass = TypeUtil.fromName(type);
if (typeClass==null)
typeClass = context.loadClass(type);
- addInjections(context, descriptor, node, jndiName, typeClass);
+ addInjections(context, descriptor, node, jndiName, typeClass);
bindMessageDestinationRef(context,jndiName, typeClass);
context.getMetaData().setOrigin("message-destination-ref."+jndiName, descriptor);
}
@@ -486,11 +486,11 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
//It can only contribute injections, and only if the web xml didn't declare any.
Descriptor d = context.getMetaData().getOriginDescriptor("message-destination-ref."+jndiName+".injection");
if (d == null || d instanceof FragmentDescriptor)
- {
+ {
Class<?> typeClass = TypeUtil.fromName(type);
if (typeClass==null)
typeClass = context.loadClass(type);
- addInjections(context, descriptor, node, jndiName, typeClass);
+ addInjections(context, descriptor, node, jndiName, typeClass);
}
}
break;
@@ -518,7 +518,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
usage = (usage==null?"":usage);
if (!type.equals(otherType) || !usage.equalsIgnoreCase(otherUsage))
throw new IllegalStateException("Conflicting message-destination-ref "+jndiName+" in "+descriptor.getResource());
-
+
//same in multiple web-fragments, merge the injections
addInjections(context, descriptor, node, jndiName, TypeUtil.fromName(type));
}
@@ -528,8 +528,8 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
}
}
-
-
+
+
/**
* If web.xml has at least 1 post-construct, then all post-constructs in fragments
@@ -542,7 +542,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
{
String className = node.getString("lifecycle-callback-class", false, true);
String methodName = node.getString("lifecycle-callback-method", false, true);
-
+
if (className==null || className.equals(""))
{
LOG.warn("No lifecycle-callback-class specified");
@@ -553,7 +553,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
LOG.warn("No lifecycle-callback-method specified for class "+className);
return;
}
-
+
//ServletSpec 3.0 p80 If web.xml declares a post-construct then all post-constructs
//in fragments must be ignored. Otherwise, they are additive.
Origin o = context.getMetaData().getOrigin("post-construct");
@@ -563,7 +563,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
{
//No post-constructs have been declared previously.
context.getMetaData().setOrigin("post-construct", descriptor);
-
+
try
{
Class<?> clazz = context.loadClass(className);
@@ -579,7 +579,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
}
case WebXml:
case WebDefaults:
- case WebOverride:
+ case WebOverride:
{
//A web xml first declared a post-construct. Only allow other web xml files (web-defaults, web-overrides etc)
//to add to it
@@ -616,12 +616,12 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
break;
}
}
-
+
}
-
+
/**
- *
+ *
* pre-destroy is the name of a class and method to call just as
* the instance is being destroyed
* @param node
@@ -639,8 +639,8 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
{
LOG.warn("No lifecycle-callback-method specified for pre-destroy class "+className);
return;
- }
-
+ }
+
Origin o = context.getMetaData().getOrigin("pre-destroy");
switch(o)
{
@@ -664,7 +664,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
}
case WebXml:
case WebDefaults:
- case WebOverride:
+ case WebOverride:
{
//A web xml file previously declared a pre-destroy. Only allow other web xml files
//(not web-fragments) to add to them.
@@ -680,7 +680,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
catch (ClassNotFoundException e)
{
LOG.warn("Couldn't load pre-destory target class "+className);
- }
+ }
}
break;
}
@@ -697,16 +697,16 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
catch (ClassNotFoundException e)
{
LOG.warn("Couldn't load pre-destory target class "+className);
- }
+ }
break;
}
- }
+ }
}
-
-
+
+
/**
* Iterate over the &lt;injection-target&gt; entries for a node
- *
+ *
* @param descriptor
* @param node
* @param jndiName
@@ -715,10 +715,10 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
public void addInjections (WebAppContext context, Descriptor descriptor, XmlParser.Node node, String jndiName, Class<?> valueClass)
{
Iterator<XmlParser.Node> itor = node.iterator("injection-target");
-
+
while(itor.hasNext())
{
- XmlParser.Node injectionNode = itor.next();
+ XmlParser.Node injectionNode = itor.next();
String targetClassName = injectionNode.getString("injection-target-class", false, true);
String targetName = injectionNode.getString("injection-target-name", false, true);
if ((targetClassName==null) || targetClassName.equals(""))
@@ -747,7 +747,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
injection.setJndiName(jndiName);
injection.setTarget(clazz, targetName, valueClass);
injections.add(injection);
-
+
//Record which was the first descriptor to declare an injection for this name
if (context.getMetaData().getOriginDescriptor(node.getTag()+"."+jndiName+".injection") == null)
context.getMetaData().setOrigin(node.getTag()+"."+jndiName+".injection", descriptor);
@@ -758,17 +758,17 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
}
}
}
+
+
-
-
-
- /**
+
+ /**
* @param name
* @param value
* @throws Exception
*/
public void bindEnvEntry(String name, Object value) throws Exception
- {
+ {
InitialContext ic = null;
boolean bound = false;
//check to see if we bound a value and an EnvEntry with this name already
@@ -797,12 +797,12 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
}
}
- /**
+ /**
* Bind a resource reference.
- *
+ *
* If a resource reference with the same name is in a jetty-env.xml
* file, it will already have been bound.
- *
+ *
* @param name
* @throws Exception
*/
@@ -812,7 +812,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
bindEntry(context, name, typeClass);
}
- /**
+ /**
* @param name
* @throws Exception
*/
@@ -821,28 +821,28 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
{
bindEntry(context, name, typeClass);
}
-
-
+
+
public void bindMessageDestinationRef(WebAppContext context, String name, Class<?> typeClass)
throws Exception
{
bindEntry(context, name, typeClass);
}
-
-
+
+
/**
* Bind a resource with the given name from web.xml of the given type
- * with a jndi resource from either the server or the webapp's naming
+ * with a jndi resource from either the server or the webapp's naming
* environment.
- *
+ *
* As the servlet spec does not cover the mapping of names in web.xml with
* names from the execution environment, jetty uses the concept of a Link, which is
* a subclass of the NamingEntry class. A Link defines a mapping of a name
* from web.xml with a name from the execution environment (ie either the server or the
* webapp's naming environment).
- *
+ *
* @param name name of the resource from web.xml
- * @param typeClass
+ * @param typeClass
* @throws Exception
*/
protected void bindEntry (WebAppContext context, String name, Class<?> typeClass)
@@ -850,12 +850,12 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
{
String nameInEnvironment = name;
boolean bound = false;
-
+
//check if the name in web.xml has been mapped to something else
//check a context-specific naming environment first
Object scope = context;
NamingEntry ne = NamingEntryUtil.lookupNamingEntry(scope, name);
-
+
if (ne!=null && (ne instanceof Link))
{
//if we found a mapping, get out name it is mapped to in the environment
@@ -865,10 +865,10 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
//try finding that mapped name in the webapp's environment first
scope = context;
bound = NamingEntryUtil.bindToENC(scope, name, nameInEnvironment);
-
+
if (bound)
return;
-
+
//try the server's environment
scope = context.getServer();
bound = NamingEntryUtil.bindToENC(scope, name, nameInEnvironment);
@@ -888,12 +888,12 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
NamingEntry defaultNE = NamingEntryUtil.lookupNamingEntry(context.getServer(), nameInEnvironment);
if (defaultNE==null)
defaultNE = NamingEntryUtil.lookupNamingEntry(null, nameInEnvironment);
-
+
if (defaultNE!=null)
defaultNE.bindToENC(name);
else
throw new IllegalStateException("Nothing to bind for name "+nameInEnvironment);
}
-
+
}

Back to the top