Repository: tomee Updated Branches: refs/heads/tomee-1.7.x 0f3ae49a1 -> 12334ec61
TOMEE-1490 more cdi logic for lazy realm + enhancing cdi-realm test with a sample Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/12334ec6 Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/12334ec6 Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/12334ec6 Branch: refs/heads/tomee-1.7.x Commit: 12334ec613b53d50f3bf311c09b588b8be3c9042 Parents: 0f3ae49 Author: Romain Manni-Bucau <[email protected]> Authored: Fri Jan 9 11:20:05 2015 +0100 Committer: Romain Manni-Bucau <[email protected]> Committed: Fri Jan 9 11:20:05 2015 +0100 ---------------------------------------------------------------------- .../tests/realm/CdiLazyRealmTOMEE1490Test.java | 62 ++++++++++ .../CdiLifecycleLazyRealmTOMEE1490Test.java | 62 ++++++++++ .../openejb/arquillian/tests/realm/Https.java | 44 +++++++ .../arquillian/tests/realm/MyCdiLazyRealm.java | 114 +++++++++++++++++++ .../tests/realm/MyCdiRealmBaseLazyRealm.java | 42 +++++++ .../arquillian/tests/realm/SimpleEndpoint.java | 33 ++++++ examples/cdi-realm/pom.xml | 40 ++++++- .../src/main/java/org/superbiz/AuthBean.java | 20 ++-- .../main/java/org/superbiz/SecuredServlet.java | 32 ++++++ .../src/main/webapp/META-INF/context.xml | 8 +- .../test/java/org/superbiz/AuthBeanTest.java | 102 +++++++++++++++++ .../cdi-realm/src/test/resources/arquillian.xml | 31 +++++ .../apache/tomee/catalina/realm/LazyRealm.java | 98 ++++++++++++---- 13 files changed, 647 insertions(+), 41 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/12334ec6/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/CdiLazyRealmTOMEE1490Test.java ---------------------------------------------------------------------- diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/CdiLazyRealmTOMEE1490Test.java b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/CdiLazyRealmTOMEE1490Test.java new file mode 100644 index 0000000..6cffb59 --- /dev/null +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/CdiLazyRealmTOMEE1490Test.java @@ -0,0 +1,62 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.arquillian.tests.realm; + +import org.apache.catalina.authenticator.BasicAuthenticator; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.net.URL; + +import static org.junit.Assert.assertEquals; + +@RunWith(Arquillian.class) +public class CdiLazyRealmTOMEE1490Test { + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ShrinkWrap.create(WebArchive.class, "example.war") + .addClasses(SimpleEndpoint.class, MyCdiLazyRealm.class) + .addAsManifestResource(new StringAsset("<Context preemptiveAuthentication=\"true\">\n" + + " <Valve className=\"" + BasicAuthenticator.class.getName() + "\" />\n" + + " <Realm cdi=\"true\"\n" + + " className=\"org.apache.tomee.catalina.realm.LazyRealm\"\n" + + " realmClass=\"" + MyCdiLazyRealm.class.getName() + "\" />\n" + + "</Context>"), "context.xml") + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); + } + + @ArquillianResource + private URL webapp; + + @Test + public void success() throws IOException { + assertEquals("ok", Https.connection(webapp, "", "user", "pwd")); + } + + @Test(expected = Exception.class) + public void failure() throws IOException { + Https.connection(webapp, "", "user", "wrong"); + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/12334ec6/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/CdiLifecycleLazyRealmTOMEE1490Test.java ---------------------------------------------------------------------- diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/CdiLifecycleLazyRealmTOMEE1490Test.java b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/CdiLifecycleLazyRealmTOMEE1490Test.java new file mode 100644 index 0000000..909dcf7 --- /dev/null +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/CdiLifecycleLazyRealmTOMEE1490Test.java @@ -0,0 +1,62 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.arquillian.tests.realm; + +import org.apache.catalina.authenticator.BasicAuthenticator; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.net.URL; + +import static org.junit.Assert.assertEquals; + +@RunWith(Arquillian.class) +public class CdiLifecycleLazyRealmTOMEE1490Test { + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ShrinkWrap.create(WebArchive.class, "example.war") + .addClasses(SimpleEndpoint.class, MyCdiRealmBaseLazyRealm.class) + .addAsManifestResource(new StringAsset("<Context preemptiveAuthentication=\"true\">\n" + + " <Valve className=\"" + BasicAuthenticator.class.getName() + "\" />\n" + + " <Realm cdi=\"true\"\n" + + " className=\"org.apache.tomee.catalina.realm.LazyRealm\"\n" + + " realmClass=\"" + MyCdiRealmBaseLazyRealm.class.getName() + "\" />\n" + + "</Context>"), "context.xml") + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); + } + + @ArquillianResource + private URL webapp; + + @Test + public void success() throws IOException { + assertEquals("ok", Https.connection(webapp, "", "user", "pwd")); + } + + @Test(expected = Exception.class) + public void failure() throws IOException { + Https.connection(webapp, "", "user", "wrong"); + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/12334ec6/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/Https.java ---------------------------------------------------------------------- diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/Https.java b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/Https.java new file mode 100644 index 0000000..a7a4c19 --- /dev/null +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/Https.java @@ -0,0 +1,44 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.arquillian.tests.realm; + +import org.apache.openejb.arquillian.common.IO; + +import javax.xml.bind.DatatypeConverter; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; + +public class Https { + public static String connection(final URL webapp, final String path, final String username, final String password) throws IOException { + final HttpURLConnection con = (HttpURLConnection) new URL(webapp.toExternalForm() + path).openConnection(); + String userCredentials = username + ":" + password; + String basicAuth = "Basic " + DatatypeConverter.printBase64Binary(userCredentials.getBytes()); + con.setRequestProperty("Authorization", basicAuth); + con.setUseCaches(false); + try { + return IO.slurp(con.getInputStream()); + } finally { + IO.close(con.getInputStream()); + con.disconnect(); + } + } + + private Https() { + // no-op + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/12334ec6/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/MyCdiLazyRealm.java ---------------------------------------------------------------------- diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/MyCdiLazyRealm.java b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/MyCdiLazyRealm.java new file mode 100644 index 0000000..2c82356 --- /dev/null +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/MyCdiLazyRealm.java @@ -0,0 +1,114 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.arquillian.tests.realm; + +import org.apache.catalina.Container; +import org.apache.catalina.Context; +import org.apache.catalina.Realm; +import org.apache.catalina.Wrapper; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.deploy.SecurityConstraint; +import org.apache.catalina.realm.GenericPrincipal; +import org.ietf.jgss.GSSContext; + +import javax.enterprise.context.ApplicationScoped; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.security.Principal; +import java.security.cert.X509Certificate; + +import static java.util.Arrays.asList; + +@ApplicationScoped // can't be request scoped cause it is a realm impl +public class MyCdiLazyRealm implements Realm { + private Container container; + + @Override + public Container getContainer() { + return container; + } + + @Override + public void setContainer(final Container container) { + this.container = container; + } + + @Override + public String getInfo() { + return null; + } + + @Override + public void addPropertyChangeListener(final PropertyChangeListener listener) { + + } + + @Override + public Principal authenticate(final String username, final String credentials) { + return "user".equalsIgnoreCase(username) && "pwd".equalsIgnoreCase(credentials) ? new GenericPrincipal(username, "pwd", asList("role")) : null; + } + + @Override + public Principal authenticate(final String username, final String digest, final String nonce, + final String nc, final String cnonce, final String qop, + final String realm, final String md5a2) { + throw new UnsupportedOperationException(); + } + + @Override + public Principal authenticate(final GSSContext gssContext, final boolean storeCreds) { + throw new UnsupportedOperationException(); + } + + @Override + public Principal authenticate(final X509Certificate[] certs) { + throw new UnsupportedOperationException(); + } + + @Override + public void backgroundProcess() { + // no-op + } + + @Override + public SecurityConstraint[] findSecurityConstraints(final Request request, final Context context) { + return null; + } + + @Override + public boolean hasResourcePermission(final Request request, final Response response, + final SecurityConstraint[] securityConstraints, final Context context) throws IOException { + return false; + } + + @Override + public boolean hasRole(final Wrapper wrapper, final Principal principal, final String s) { + return false; + } + + @Override + public boolean hasUserDataPermission(final Request request, final Response response, + final SecurityConstraint[] securityConstraints) throws IOException { + return false; + } + + @Override + public void removePropertyChangeListener(final PropertyChangeListener listener) { + // no-op + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/12334ec6/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/MyCdiRealmBaseLazyRealm.java ---------------------------------------------------------------------- diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/MyCdiRealmBaseLazyRealm.java b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/MyCdiRealmBaseLazyRealm.java new file mode 100644 index 0000000..f1b5e30 --- /dev/null +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/MyCdiRealmBaseLazyRealm.java @@ -0,0 +1,42 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.arquillian.tests.realm; + +import org.apache.catalina.realm.GenericPrincipal; +import org.apache.catalina.realm.RealmBase; + +import java.security.Principal; + +import static java.util.Arrays.asList; + +// no scope cause RealmBase is not proxyable, realm impl would put a scope + implement Realm, Lifecycle +public class MyCdiRealmBaseLazyRealm extends RealmBase { + @Override + protected String getName() { + return "user"; + } + + @Override + protected String getPassword(final String username) { + return "pwd"; + } + + @Override + protected Principal getPrincipal(final String username) { + return new GenericPrincipal(username, getPassword(username), asList("role")); + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/12334ec6/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/SimpleEndpoint.java ---------------------------------------------------------------------- diff --git a/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/SimpleEndpoint.java b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/SimpleEndpoint.java new file mode 100644 index 0000000..1157436 --- /dev/null +++ b/arquillian/arquillian-tomee-tests/arquillian-tomee-webprofile-tests/src/test/java/org/apache/openejb/arquillian/tests/realm/SimpleEndpoint.java @@ -0,0 +1,33 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.arquillian.tests.realm; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@WebServlet("/*") +public class SimpleEndpoint extends HttpServlet { + @Override + protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { + resp.getWriter().write("ok"); + resp.setContentType("text/plain"); + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/12334ec6/examples/cdi-realm/pom.xml ---------------------------------------------------------------------- diff --git a/examples/cdi-realm/pom.xml b/examples/cdi-realm/pom.xml index 164a670..b367bb4 100644 --- a/examples/cdi-realm/pom.xml +++ b/examples/cdi-realm/pom.xml @@ -26,6 +26,7 @@ <name>OpenEJB :: Examples :: CDI Realm</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <tomee.version>2.0.0-SNAPSHOT</tomee.version> </properties> <build> <defaultGoal>install</defaultGoal> @@ -65,7 +66,44 @@ <dependency> <groupId>org.apache.openejb</groupId> <artifactId>javaee-api</artifactId> - <version>6.0-6</version> + <version>7.0-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.jboss.arquillian.junit</groupId> + <artifactId>arquillian-junit-container</artifactId> + <version>1.1.5.Final</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.openejb</groupId> + <artifactId>arquillian-tomee-remote</artifactId> + <version>1.7.2-SNAPSHOT</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.3.6</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.openejb</groupId> + <artifactId>tomee-catalina</artifactId> + <version>1.7.2-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.tomcat</groupId> + <artifactId>tomcat-catalina</artifactId> + <version>7.0.57</version> <scope>provided</scope> </dependency> </dependencies> http://git-wip-us.apache.org/repos/asf/tomee/blob/12334ec6/examples/cdi-realm/src/main/java/org/superbiz/AuthBean.java ---------------------------------------------------------------------- diff --git a/examples/cdi-realm/src/main/java/org/superbiz/AuthBean.java b/examples/cdi-realm/src/main/java/org/superbiz/AuthBean.java index 66fb943..bee66b9 100644 --- a/examples/cdi-realm/src/main/java/org/superbiz/AuthBean.java +++ b/examples/cdi-realm/src/main/java/org/superbiz/AuthBean.java @@ -19,9 +19,8 @@ package org.superbiz; import javax.enterprise.context.RequestScoped; import java.security.Principal; -@RequestScoped +@RequestScoped // just to show we can be bound to the request but @ApplicationScoped is what makes sense public class AuthBean { - public Principal authenticate(final String username, String password) { if (("userA".equals(username) || "userB".equals(username)) && "test".equals(password)) { return new Principal() { @@ -39,16 +38,11 @@ public class AuthBean { return null; } - public boolean hasRole(Principal principal, String role) { - if (principal == null) { - return false; - } - if (principal.getName().equals("userA") && (role.equals("admin") || role.equals("user"))) { - return true; - } - if (principal.getName().equals("userB") && (role.equals("user"))) { - return true; - } - return false; + public boolean hasRole(final Principal principal, final String role) { + return principal != null && ( + principal.getName().equals("userA") && (role.equals("admin") + || role.equals("user")) + || principal.getName().equals("userB") && (role.equals("user")) + ); } } http://git-wip-us.apache.org/repos/asf/tomee/blob/12334ec6/examples/cdi-realm/src/main/java/org/superbiz/SecuredServlet.java ---------------------------------------------------------------------- diff --git a/examples/cdi-realm/src/main/java/org/superbiz/SecuredServlet.java b/examples/cdi-realm/src/main/java/org/superbiz/SecuredServlet.java new file mode 100644 index 0000000..884db32 --- /dev/null +++ b/examples/cdi-realm/src/main/java/org/superbiz/SecuredServlet.java @@ -0,0 +1,32 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.superbiz; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@WebServlet("/servlet") +public class SecuredServlet extends HttpServlet { + @Override + protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { + resp.getWriter().write("Servlet!"); + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/12334ec6/examples/cdi-realm/src/main/webapp/META-INF/context.xml ---------------------------------------------------------------------- diff --git a/examples/cdi-realm/src/main/webapp/META-INF/context.xml b/examples/cdi-realm/src/main/webapp/META-INF/context.xml index d7959ae..367d033 100644 --- a/examples/cdi-realm/src/main/webapp/META-INF/context.xml +++ b/examples/cdi-realm/src/main/webapp/META-INF/context.xml @@ -15,6 +15,8 @@ See the License for the specific language governing permissions and limitations under the License. --> -<Context> - <Realm cdi="true" className="org.apache.tomee.catalina.realm.LazyRealm" realmClass="org.superbiz.AuthBean"/> -</Context> \ No newline at end of file +<Context preemptiveAuthentication="true"> + <Valve className="org.apache.catalina.authenticator.BasicAuthenticator" /> + <Realm className="org.apache.tomee.catalina.realm.LazyRealm" + cdi="true" realmClass="org.superbiz.AuthBean"/> +</Context> http://git-wip-us.apache.org/repos/asf/tomee/blob/12334ec6/examples/cdi-realm/src/test/java/org/superbiz/AuthBeanTest.java ---------------------------------------------------------------------- diff --git a/examples/cdi-realm/src/test/java/org/superbiz/AuthBeanTest.java b/examples/cdi-realm/src/test/java/org/superbiz/AuthBeanTest.java new file mode 100644 index 0000000..d89d691 --- /dev/null +++ b/examples/cdi-realm/src/test/java/org/superbiz/AuthBeanTest.java @@ -0,0 +1,102 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.superbiz; + +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.AuthCache; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.impl.auth.BasicScheme; +import org.apache.http.impl.client.BasicAuthCache; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.apache.openejb.arquillian.common.IO; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.asset.FileAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; +import java.io.IOException; +import java.net.URL; + +import static org.hamcrest.CoreMatchers.startsWith; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +@RunWith(Arquillian.class) +public class AuthBeanTest { + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ShrinkWrap.create(WebArchive.class, "low-typed-realm.war") + .addClasses(SecuredServlet.class, AuthBean.class) + .addAsManifestResource(new FileAsset(new File("src/main/webapp/META-INF/context.xml")), "context.xml") + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); + } + + @ArquillianResource + private URL webapp; + + @Test + public void success() throws IOException { + assertEquals("200 Servlet!", get("userA", "test")); + } + + @Test + public void failure() throws IOException { + assertThat(get("userA", "oops, wrong password"), startsWith("401")); + } + + private String get(final String user, final String password) { + final BasicCredentialsProvider basicCredentialsProvider = new BasicCredentialsProvider(); + basicCredentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(user, password)); + final CloseableHttpClient client = HttpClients.custom() + .setDefaultCredentialsProvider(basicCredentialsProvider).build(); + + final HttpHost httpHost = new HttpHost(webapp.getHost(), webapp.getPort(), webapp.getProtocol()); + final AuthCache authCache = new BasicAuthCache(); + final BasicScheme basicAuth = new BasicScheme(); + authCache.put(httpHost, basicAuth); + final HttpClientContext context = HttpClientContext.create(); + context.setAuthCache(authCache); + + final HttpGet get = new HttpGet(webapp.toExternalForm() + "servlet"); + CloseableHttpResponse response = null; + try { + response = client.execute(httpHost, get, context); + return response.getStatusLine().getStatusCode() + " " + EntityUtils.toString(response.getEntity()); + } catch (final IOException e) { + throw new IllegalStateException(e); + } finally { + try { + IO.close(response); + } catch (final IOException e) { + // no-op + } + } + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/12334ec6/examples/cdi-realm/src/test/resources/arquillian.xml ---------------------------------------------------------------------- diff --git a/examples/cdi-realm/src/test/resources/arquillian.xml b/examples/cdi-realm/src/test/resources/arquillian.xml new file mode 100644 index 0000000..1db3d40 --- /dev/null +++ b/examples/cdi-realm/src/test/resources/arquillian.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<!-- + + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<arquillian xmlns="http://jboss.org/schema/arquillian" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd"> + <container qualifier="tomee" default="true"> + <configuration> + <property name="httpPort">-1</property> + <property name="stopPort">-1</property> + <property name="ajpPort">-1</property> + <property name="dir">target/tomee</property> + <property name="appWorkingDir">target/arquillian-dump-dir</property> + </configuration> + </container> +</arquillian> http://git-wip-us.apache.org/repos/asf/tomee/blob/12334ec6/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/realm/LazyRealm.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/realm/LazyRealm.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/realm/LazyRealm.java index 3eccfbe..40d40c2 100644 --- a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/realm/LazyRealm.java +++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/realm/LazyRealm.java @@ -40,6 +40,7 @@ import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; import java.io.IOException; import java.security.Principal; import java.security.cert.X509Certificate; @@ -49,13 +50,21 @@ import java.util.Set; public class LazyRealm extends LifecycleBase implements Realm { private String realmClass; private String properties; + private String name; private boolean cdi; + private volatile boolean init; + private volatile boolean start; private volatile Realm delegate; private Context container; + private final PropertyChangeSupport support = new PropertyChangeSupport(this); private CreationalContext<Object> creationalContext; + public void setName(final String name) { + this.name = name; + } + public void setRealmClass(final String realmClass) { this.realmClass = realmClass; } @@ -103,10 +112,16 @@ public class LazyRealm extends LifecycleBase implements Realm { throw new TomEERuntimeException(e); } } else { - final WebBeansContext webBeansContext = WebBeansContext.currentInstance(); - if (webBeansContext == null) { + final WebBeansContext webBeansContext; + try { + webBeansContext = WebBeansContext.currentInstance(); + if (webBeansContext == null) { + return null; + } + } catch (final IllegalStateException ise) { return null; // too early to have a cdi bean, skip these methods - mainly init() but @PostConstruct works then } + final BeanManager bm = webBeansContext.getBeanManagerImpl(); final Set<Bean<?>> beans = bm.getBeans(clazz); final Bean<?> bean = bm.resolve(beans); @@ -122,47 +137,79 @@ public class LazyRealm extends LifecycleBase implements Realm { } if (instance instanceof Realm) { delegate = (Realm) instance; + delegate.setContainer(container); + if (Lifecycle.class.isInstance(delegate)) { + if (init) { + try { + final Lifecycle lifecycle = Lifecycle.class.cast(delegate); + lifecycle.init(); + if (start) { + lifecycle.start(); + } + } catch (final LifecycleException e) { + // no-op + } + } + } } else { delegate = new LowTypedRealm(instance); + delegate.setContainer(container); + } + for (final PropertyChangeListener listener : support.getPropertyChangeListeners()) { + delegate.addPropertyChangeListener(listener); } - delegate.setContainer(container); } } } return delegate; } + private Class<?> loadClass() { + if (container != null && container.getLoader() != null && container.getLoader().getClassLoader() != null) { + try { + return container.getLoader().getClassLoader().loadClass(realmClass); + } catch (final ClassNotFoundException e) { + // no-op + } + } + return null; + } + @Override protected void initInternal() throws LifecycleException { - final Realm r = instance(); - if (r != null && Lifecycle.class.isInstance(r)) { - Lifecycle.class.cast(r).init(); + final Class<?> r = loadClass(); + if (r != null && Lifecycle.class.isAssignableFrom(r) && instance() != null) { + Lifecycle.class.cast(delegate).init(); + } else { + init = true; } } @Override protected void startInternal() throws LifecycleException { - final Realm r = instance(); - if (r != null && Lifecycle.class.isInstance(r)) { - Lifecycle.class.cast(r).start(); + final Class<?> r = loadClass(); + if (r != null && Lifecycle.class.isAssignableFrom(r) && instance() != null) { + Lifecycle.class.cast(instance()).start(); + } else { + start = true; } setState(LifecycleState.STARTING); } @Override protected void stopInternal() throws LifecycleException { - final Realm r = instance(); - if (r != null && Lifecycle.class.isInstance(r)) { - Lifecycle.class.cast(r).stop(); + final Class<?> r = loadClass(); + if (r != null && Lifecycle.class.isAssignableFrom(r) && instance() != null) { + Lifecycle.class.cast(delegate).stop(); } setState(LifecycleState.STOPPING); } @Override protected void destroyInternal() throws LifecycleException { - final Realm r = instance(); - if (r != null && Lifecycle.class.isInstance(r)) { - Lifecycle.class.cast(r).destroy(); + final Class<?> r = loadClass(); + if (r != null && Lifecycle.class.isAssignableFrom(r) && instance() != null) { + Lifecycle.class.cast(delegate).destroy(); } } @@ -196,6 +243,9 @@ public class LazyRealm extends LifecycleBase implements Realm { @Override public String getInfo() { + if (name != null) { + return name; + } final Realm instance = instance(); if (instance == null) { return getClass().getName() + "/1.0"; @@ -205,11 +255,10 @@ public class LazyRealm extends LifecycleBase implements Realm { @Override public void addPropertyChangeListener(final PropertyChangeListener listener) { - final Realm instance = instance(); - if (instance == null) { - return; + if (delegate != null) { + delegate.addPropertyChangeListener(listener); } - instance.addPropertyChangeListener(listener); + support.addPropertyChangeListener(listener); } @Override @@ -235,7 +284,9 @@ public class LazyRealm extends LifecycleBase implements Realm { @Override public void backgroundProcess() { - instance().backgroundProcess(); + if (delegate != null) { + instance().backgroundProcess(); + } } @Override @@ -262,10 +313,9 @@ public class LazyRealm extends LifecycleBase implements Realm { @Override public void removePropertyChangeListener(final PropertyChangeListener listener) { - final Realm instance = instance(); - if (instance == null) { - return; + if (delegate != null) { + delegate.removePropertyChangeListener(listener); } - instance.removePropertyChangeListener(listener); + support.removePropertyChangeListener(listener); } }
