/* * Copyright (C) 2011 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.errai.enterprise.rebind; import java.util.HashSet; import java.util.Set; import javax.enterprise.event.Observes; import javax.enterprise.inject.Produces; import org.jboss.errai.codegen.BlockStatement; import org.jboss.errai.codegen.Modifier; import org.jboss.errai.codegen.Statement; import org.jboss.errai.codegen.builder.MethodCommentBuilder; import org.jboss.errai.codegen.meta.MetaClass; import org.jboss.errai.codegen.meta.MetaParameter; import org.jboss.errai.codegen.util.Stmt; import org.jboss.errai.config.util.ClassScanner; import org.jboss.errai.enterprise.client.cdi.CDIEventTypeLookup; import org.jboss.errai.enterprise.client.cdi.api.CDI; import org.jboss.errai.ioc.client.api.IOCExtension; import org.jboss.errai.ioc.rebind.ioc.bootstrapper.IOCProcessingContext; import org.jboss.errai.ioc.rebind.ioc.extension.IOCExtensionConfigurator; import org.jboss.errai.ioc.rebind.ioc.injector.api.InjectionContext; import org.jboss.errai.ioc.rebind.ioc.injector.api.WiringElementType; @IOCExtension public class JSR299IOCExtensionConfigurator implements IOCExtensionConfigurator { @Override public void configure(final IOCProcessingContext context, final InjectionContext injectionContext) { injectionContext.mapElementType(WiringElementType.ProducerElement, Produces.class); } @SuppressWarnings("unchecked") private static void addTypeHierarchyFor(final IOCProcessingContext context, final Set<MetaClass> classes) { final BlockStatement instanceInitializer = context.getBootstrapClass().getInstanceInitializer(); int i = 0, addLookupMethodCount = 0; MethodCommentBuilder<?> currentBlock = null; for (final MetaClass subClass : classes) { // We'll generate a separate lookup method for every 500 lines to make sure we're not // exceeding the method size byte limit. See ERRAI-346 and ERRAI-679 if ((i++ % 500) == 0) { final Statement lookupMethod = Stmt.invokeStatic(context.getBootstrapClass(), "addLookups_" + addLookupMethodCount); if (currentBlock != null) { currentBlock .append(lookupMethod); currentBlock.modifiers(Modifier.Static).finish(); } else { instanceInitializer.addStatement(lookupMethod); } currentBlock = context.getBootstrapBuilder().privateMethod(void.class, "addLookups_" + addLookupMethodCount++); } if (subClass.getSuperClass() != null) { currentBlock.append(Stmt.invokeStatic(CDIEventTypeLookup.class, "get") .invoke("addLookup", subClass.getFullyQualifiedName(), subClass.getSuperClass().getFullyQualifiedName())); } for (final MetaClass interfaceClass : subClass.getInterfaces()) { currentBlock.append(Stmt.invokeStatic(CDIEventTypeLookup.class, "get") .invoke("addLookup", subClass.getFullyQualifiedName(), interfaceClass.getFullyQualifiedName())); } } if (currentBlock != null) { currentBlock.modifiers(Modifier.Static).finish(); } } @Override public void afterInitialization(final IOCProcessingContext context, final InjectionContext injectionContext) { final BlockStatement instanceInitializer = context.getBootstrapClass().getInstanceInitializer(); final Set<MetaClass> knownObserverTypes = new HashSet<>(); for (final MetaParameter parameter : ClassScanner.getParametersAnnotatedWith(Observes.class, context.getGeneratorContext())) { knownObserverTypes.add(parameter.getType()); } final Set<MetaClass> knownTypesWithSuperTypes = new HashSet<>(knownObserverTypes); for (final MetaClass cls : knownObserverTypes) { for (final MetaClass subClass : ClassScanner.getSubTypesOf(cls, context.getGeneratorContext())) { knownTypesWithSuperTypes.add(subClass); } } addTypeHierarchyFor(context, knownTypesWithSuperTypes); instanceInitializer.addStatement(Stmt.nestedCall(Stmt.newObject(CDI.class)) .invoke("initLookupTable", Stmt.invokeStatic(CDIEventTypeLookup.class, "get"))); } }