Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #4210 from pdudits/payara-4077
PAYARA-4077: Implement Weld SecurityContext
  • Loading branch information
pdudits committed Sep 11, 2019
2 parents b08be47 + 4451006 commit 6c1cc81
Show file tree
Hide file tree
Showing 10 changed files with 326 additions and 11 deletions.
4 changes: 4 additions & 0 deletions Jenkinsfile
Expand Up @@ -42,6 +42,7 @@ pipeline {
}
stage('Setup for Quicklook Tests') {
steps {
sh "rm *.zip"
setupDomain()
}
}
Expand All @@ -58,6 +59,7 @@ pipeline {
}
post {
always {
zip archive: true, dir: "appserver/distributions/payara/target/stage/payara5/glassfish/domains/${DOMAIN_NAME}/logs", glob: 'server.*', zipFile: 'quicklook-log.zip'
teardownDomain()
junit '**/target/surefire-reports/*.xml'
}
Expand Down Expand Up @@ -88,6 +90,7 @@ pipeline {
}
post {
always {
zip archive: true, dir: "appserver/distributions/payara/target/stage/payara5/glassfish/domains/${DOMAIN_NAME}/logs", glob: 'server.*', zipFile: 'ee8-samples-log.zip'
teardownDomain()
junit '**/target/surefire-reports/*.xml'
}
Expand Down Expand Up @@ -146,6 +149,7 @@ pipeline {
}
post {
always {
zip archive: true, dir: "appserver/distributions/payara/target/stage/payara5/glassfish/domains/${DOMAIN_NAME}/logs", glob: 'server.*', zipFile: 'ee7-samples-log.zip'
teardownDomain()
junit '**/target/surefire-reports/*.xml'
}
Expand Down
2 changes: 1 addition & 1 deletion appserver/admingui/cluster/pom.xml
Expand Up @@ -90,7 +90,7 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.main.common</groupId>
<groupId>fish.payara.server.internal.common</groupId>
<artifactId>glassfish-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
Expand Down
@@ -1 +1 @@
fish.payara.microprofile.config.spi.ConfigProviderResolver
fish.payara.nucleus.microprofile.config.spi.ConfigProviderResolverSync
Expand Up @@ -87,7 +87,6 @@ public class ClusteredCDIEventBusImpl implements CDIEventListener, ClusteredCDIE
@Inject
private BeanManager bm;

@Resource
private ManagedExecutorService managedExecutorService;

private JavaEEContextUtil ctxUtil;
Expand Down
Expand Up @@ -64,6 +64,7 @@
import org.glassfish.javaee.core.deployment.ApplicationHolder;
import org.glassfish.weld.connector.WeldUtils;
import org.glassfish.weld.connector.WeldUtils.BDAType;
import org.glassfish.weld.services.ResourceInjectionServicesImpl;
import org.jboss.weld.bootstrap.WeldBootstrap;
import org.jboss.weld.bootstrap.api.ServiceRegistry;
import org.jboss.weld.bootstrap.api.helpers.SimpleServiceRegistry;
Expand All @@ -77,6 +78,7 @@
import com.sun.enterprise.deployment.util.DOLUtils;
import org.glassfish.weld.services.InjectionServicesImpl;
import org.jboss.weld.injection.spi.InjectionServices;
import org.jboss.weld.injection.spi.ResourceInjectionServices;

/*
* Represents a deployment of a CDI (Weld) application.
Expand Down Expand Up @@ -426,6 +428,7 @@ public BeanDeploymentArchive loadBeanDeploymentArchive(Class<?> beanClass) {
beanClasses, beanXMLUrls, ejbs, context);
// have to create new InjectionServicesImpl for each new BDA so injection context is propagated for the correct bundle
newBda.getServices().add(InjectionServices.class, new InjectionServicesImpl(injectionManager, DOLUtils.getCurrentBundleForContext(context), this));
newBda.getServices().add(ResourceInjectionServices.class, new ResourceInjectionServicesImpl());
BeansXml beansXml = newBda.getBeansXml();
if (beansXml == null || !beansXml.getBeanDiscoveryMode().equals(BeanDiscoveryMode.NONE)) {
if ( logger.isLoggable( FINE ) ) {
Expand Down
Expand Up @@ -110,13 +110,7 @@
import org.glassfish.web.deployment.descriptor.ServletFilterDescriptor;
import org.glassfish.web.deployment.descriptor.ServletFilterMappingDescriptor;
import org.glassfish.weld.connector.WeldUtils;
import org.glassfish.weld.services.EjbServicesImpl;
import org.glassfish.weld.services.ExternalConfigurationImpl;
import org.glassfish.weld.services.InjectionServicesImpl;
import org.glassfish.weld.services.NonModuleInjectionServices;
import org.glassfish.weld.services.ProxyServicesImpl;
import org.glassfish.weld.services.SecurityServicesImpl;
import org.glassfish.weld.services.TransactionServicesImpl;
import org.glassfish.weld.services.*;
import org.jboss.weld.bootstrap.WeldBootstrap;
import org.jboss.weld.bootstrap.spi.BeanDeploymentArchive;
import org.jboss.weld.bootstrap.spi.EEModuleDescriptor;
Expand All @@ -127,6 +121,7 @@
import org.jboss.weld.ejb.spi.EjbServices;
import org.jboss.weld.exceptions.WeldException;
import org.jboss.weld.injection.spi.InjectionServices;
import org.jboss.weld.injection.spi.ResourceInjectionServices;
import org.jboss.weld.probe.ProbeExtension;
import org.jboss.weld.resources.spi.ResourceLoader;
import org.jboss.weld.security.NewInstanceAction;
Expand All @@ -146,7 +141,6 @@
import com.sun.enterprise.deployment.web.ContextParameter;
import com.sun.enterprise.deployment.web.ServletFilterMapping;
import fish.payara.nucleus.executorservice.PayaraExecutorService;
import org.glassfish.weld.services.ExecutorServicesImpl;
import org.jboss.weld.manager.api.ExecutorServices;

@Service
Expand Down Expand Up @@ -379,12 +373,15 @@ public WeldApplicationContainer load(WeldContainer container, DeploymentContext
// We use the generic InjectionService service to handle all EE-style
// injection instead of the per-dependency-type InjectionPoint approach.
// Each InjectionServicesImpl instance knows its associated GlassFish bundle.

InjectionServices injectionServices = new InjectionServicesImpl(deploymentImpl.injectionManager, bundle, deploymentImpl);
ResourceInjectionServicesImpl resourceInjectionServices = new ResourceInjectionServicesImpl();
if (logger.isLoggable(FINE)) {
logger.log(FINE, ADDING_INJECTION_SERVICES, new Object[] { injectionServices, beanDeploymentArchive.getId() });
}

beanDeploymentArchive.getServices().add(InjectionServices.class, injectionServices);
beanDeploymentArchive.getServices().add(ResourceInjectionServices.class, resourceInjectionServices);
EEModuleDescriptor eeModuleDescriptor = getEEModuleDescriptor(beanDeploymentArchive);
if (eeModuleDescriptor != null) {
beanDeploymentArchive.getServices().add(EEModuleDescriptor.class, eeModuleDescriptor);
Expand Down
@@ -0,0 +1,173 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) [2019] Payara Foundation and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://github.com/payara/Payara/blob/master/LICENSE.txt
* See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* The Payara Foundation designates this particular file as subject to the "Classpath"
* exception as provided by the Payara Foundation in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package org.glassfish.weld.services;

import org.jboss.weld.injection.spi.ResourceInjectionServices;
import org.jboss.weld.injection.spi.ResourceReferenceFactory;
import org.jboss.weld.injection.spi.helpers.SimpleResourceReference;

import javax.annotation.Resource;
import javax.enterprise.inject.spi.Annotated;
import javax.enterprise.inject.spi.AnnotatedParameter;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.beans.Introspector;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ResourceInjectionServicesImpl implements ResourceInjectionServices {
static final String ENV = "java:comp/env";
private static final Logger LOG = Logger.getLogger(ResourceInjectionServicesImpl.class.getName());


private final InitialContext namingContext;

public ResourceInjectionServicesImpl() {
try {
this.namingContext = new InitialContext();
} catch (NamingException e) {
throw new RuntimeException("Initial context not available at deployment time", e);
}
}

@Override
public ResourceReferenceFactory<Object> registerResourceInjectionPoint(InjectionPoint injectionPoint) {
if (getResourceAnnotation(injectionPoint) == null) {
throw new IllegalArgumentException("No @Resource annotation found on injection point " + injectionPoint);
}
if (injectionPoint.getMember() instanceof Method
&& ((Method) injectionPoint.getMember()).getParameterCount() != 1) {
throw new IllegalArgumentException(
"Resource injection point represents a method which doesn't have exactly one parameter "
+ injectionPoint);
}
return () -> new SimpleResourceReference<>(resolveResource(injectionPoint));
}

private Context getContext() {
return this.namingContext;
}

private Resource getResourceAnnotation(InjectionPoint injectionPoint) {
Annotated annotated = injectionPoint.getAnnotated();
if (annotated instanceof AnnotatedParameter) {
// the injection point is parameter, however, it's method that's annotated
annotated = ((AnnotatedParameter) annotated).getDeclaringCallable();
}
return annotated.getAnnotation(Resource.class);
}

private Object resolveResource(InjectionPoint injectionPoint) {
String name = determineResourceName(injectionPoint);
try {
return getContext().lookup(name);
} catch (NamingException e) {
// Missing resource injections shall be quietly ignored, just like before.
LOG.log(Level.FINE, e, () -> "Failed to find "+name+" in JNDI");
}
return null;
}

private String determineResourceName(InjectionPoint injectionPoint) {
Resource resource = getResourceAnnotation(injectionPoint);
String lookup = resource.lookup();
if (!lookup.isEmpty()) {
return lookup;
}
String mappedName = resource.mappedName();
if (!mappedName.isEmpty()) {
return mappedName;
}
String name = resource.name();
if (!name.isEmpty()) {
return ENV + "/" + name;
}

String propertyName;
if (injectionPoint.getMember() instanceof Field) {
propertyName = injectionPoint.getMember().getName();
} else if (injectionPoint.getMember() instanceof Method) {
propertyName = determinePropertyName((Method) injectionPoint.getMember(), injectionPoint);
} else {
throw new AssertionError("Unable to inject Resource into " + injectionPoint);
}

String className = injectionPoint.getMember().getDeclaringClass().getName();
return ENV + "/" + className + "/" + propertyName;
}

static String determinePropertyName(Method method, InjectionPoint injectionPoint) {
String methodName = method.getName();
if (methodName.startsWith("get") && method.getParameterCount() == 0) {
return Introspector.decapitalize(methodName.substring(3));
} else if (methodName.startsWith("set") && method.getParameterCount() == 1) {
return Introspector.decapitalize(methodName.substring(3));
} else if (methodName.startsWith("is") && method.getParameterCount() == 0) {
return Introspector.decapitalize(methodName.substring(2));
} else {
throw new IllegalArgumentException("Injection point doesn't follow "
+ "JavaBean conventions (unable to determine property name) " + injectionPoint);
}
}

@Override
public ResourceReferenceFactory<Object> registerResourceInjectionPoint(String jndiName, String mappedName) {
return () -> new SimpleResourceReference<>(resolveResource(jndiName, mappedName));
}

private Object resolveResource(String jndiName, String mappedName) {
if (mappedName != null && !mappedName.isEmpty()) {
return mappedName;
} else {
return jndiName;
}
}


@Override
public void cleanup() {

}
}
Expand Up @@ -42,6 +42,8 @@

import com.sun.enterprise.security.SecurityContext;
import java.security.Principal;
import java.util.function.Consumer;

import org.jboss.weld.security.spi.SecurityServices;

public class SecurityServicesImpl implements SecurityServices {
Expand All @@ -53,5 +55,41 @@ public Principal getPrincipal() {

@Override
public void cleanup() {}

@Override
public org.jboss.weld.security.spi.SecurityContext getSecurityContext() {
return new SecurityContextImpl();
}

static class SecurityContextImpl implements org.jboss.weld.security.spi.SecurityContext {

private final SecurityContext myContext;
private SecurityContext oldContext;

private SecurityContextImpl() {
this.myContext = SecurityContext.getCurrent();
}

@Override
public void associate() {
if (oldContext == null) {
oldContext = SecurityContext.getCurrent();
} else {
throw new IllegalStateException("Security context is already associated");
}
SecurityContext.setCurrent(myContext);
}

@Override
public void dissociate() {
SecurityContext.setCurrent(oldContext);
oldContext = null;
}

@Override
public void close() {

}
}
}

Expand Up @@ -54,6 +54,7 @@
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.logging.Level;
import java.util.logging.Logger;

Expand Down Expand Up @@ -116,6 +117,8 @@ public class ConfigProviderResolverImpl extends ConfigProviderResolver {
private static final String CUSTOM_CONVERTERS_KEY = "MICROPROFILE_CUSTOM_CONVERTERS";
private final static String APP_METADATA_KEY = "payara.microprofile.config";

static final CountDownLatch initialized = new CountDownLatch(1);

@Inject
private InvocationManager invocationManager;

Expand All @@ -142,6 +145,7 @@ public ConfigProviderResolverImpl() {
@PostConstruct
public void postConstruct() {
ConfigProviderResolver.setInstance(this);
initialized.countDown();
}


Expand Down

0 comments on commit 6c1cc81

Please sign in to comment.