Package org.infinispan.factories.components

Source Code of org.infinispan.factories.components.ComponentMetadata$PrioritizedMethodMetadata

/*
* Copyright 2011 Red Hat, Inc. and/or its affiliates.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/

package org.infinispan.factories.components;

import org.infinispan.factories.ComponentRegistry;
import org.infinispan.factories.annotations.ComponentName;
import org.infinispan.factories.annotations.DefaultFactoryFor;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.factories.annotations.Start;
import org.infinispan.factories.annotations.Stop;
import org.infinispan.factories.annotations.SurvivesRestarts;
import org.infinispan.factories.scopes.Scope;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
* This class contains all of the metadata and implications expressed via the {@link Scope}, {@link SurvivesRestarts},
* {@link DefaultFactoryFor}, {@link ComponentName}, {@link Inject}, {@link Start} and {@link Stop} annotations.  Instead
* of scanning for these annotations and working out dependency chains at runtime "on-demand", since Infinispan 5.1, this
* process now happens offline, at build-time. 
* <p />
* When compiling Infinispan, components and their dependency chains are inspected and the information expressed by the
* annotations above are denormalized and a series of {@link ComponentMetadata} objects are created and persisted in the
* Infinispan jar.
* <p />
* This metadata is then read in by the {@link ComponentMetadataRepo} at runtime, and used by the {@link ComponentRegistry}
* and other factory-like classes to bootstrap an Infinispan node.
* <p />
* Also see {@link ManageableComponentMetadata} for components that also expose JMX information.

* @author Manik Surtani
* @since 5.1
* @see ManageableComponentMetadata
* @see ComponentMetadataRepo
*/
public class ComponentMetadata implements Serializable {
   public static final InjectMetadata[] EMPTY_INJECT_METHODS = {};
   public static final PrioritizedMethodMetadata[] EMPTY_PRIORITIZED_METHODS = {};

   private String name;
   private transient Map<String, String> dependencies;
   private InjectMetadata[] injectMetadata;
   private PrioritizedMethodMetadata[] startMethods;
   private PrioritizedMethodMetadata[] stopMethods;
   private boolean globalScope = false;
   private boolean survivesRestarts = false;
   private transient Class<?> clazz;

   ComponentMetadata() {
      globalScope = false;
      survivesRestarts = true;
   }

   public ComponentMetadata(Class<?> component, List<Method> injectMethods, List<Method> startMethods, List<Method> stopMethods, boolean global, boolean survivesRestarts) {
      clazz = component;
      name = component.getName();
      globalScope = global;
      this.survivesRestarts = survivesRestarts;

      if (startMethods != null && !startMethods.isEmpty()) {
         this.startMethods = new PrioritizedMethodMetadata[startMethods.size()];
         int i=0;
         for (Method m : startMethods) {
            Start s = m.getAnnotation(Start.class);
            this.startMethods[i++] = new PrioritizedMethodMetadata(m.getName(), s.priority());
         }
      }

      if (stopMethods != null && !stopMethods.isEmpty()) {
         this.stopMethods = new PrioritizedMethodMetadata[stopMethods.size()];
         int i=0;
         for (Method m : stopMethods) {
            Stop s = m.getAnnotation(Stop.class);
            this.stopMethods[i++] = new PrioritizedMethodMetadata(m.getName(), s.priority());
         }
      }

      if (injectMethods != null && !injectMethods.isEmpty()) {
         this.injectMetadata = new InjectMetadata[injectMethods.size()];
         this.dependencies = new HashMap<String, String>(injectMethods.size() * 2);
         int j=0;
         for (Method m : injectMethods) {
           
            List<String> params = new LinkedList<String>();
            InjectMetadata injectMetadata = new InjectMetadata(m.getName());
           
            Class<?>[] parameterTypes = m.getParameterTypes();

            // Add this to our dependencies map
            Annotation[][] annotations = m.getParameterAnnotations();
            for (int i=0; i<parameterTypes.length; i++) {
               String componentName = findComponentName(annotations, i);
               String parameterType = parameterTypes[i].getName();
               params.add(parameterType);
               if (componentName == null) {
                  dependencies.put(parameterType, parameterType);
               } else {
                  injectMetadata.addParameterName(i, componentName);
                  dependencies.put(componentName, parameterType);
               }
            }
            injectMetadata.parameters = params.toArray(new String[params.size()]);
            this.injectMetadata[j++] = injectMetadata;
         }
      }
   }
  
   private String findComponentName(Annotation[][] annotations, int position) {
      if (annotations != null && annotations.length > position) {
         Annotation[] paramAnnotations = annotations[position];
         if (paramAnnotations != null) {
            for (Annotation a: paramAnnotations) {
               if (a instanceof ComponentName) {
                  return ((ComponentName) a).value();
               }
            }
         }
      }
      return null;
   }

   public String getName() {
      return name;
   }

   public Map<String, String> getDependencies() {
      return dependencies;
   }

   public InjectMetadata[] getInjectMethods() {
      if (injectMetadata == null) return EMPTY_INJECT_METHODS;
      return injectMetadata;
   }

   public PrioritizedMethodMetadata[] getStartMethods() {
      if (startMethods == null) return EMPTY_PRIORITIZED_METHODS;
      return startMethods;
   }

   public PrioritizedMethodMetadata[] getStopMethods() {
      if (stopMethods == null) return EMPTY_PRIORITIZED_METHODS;
      return stopMethods;
   }

   public boolean isGlobalScope() {
      return globalScope;
   }

   public boolean isSurvivesRestarts() {
      return survivesRestarts;
   }

   public boolean isManageable() {
      return false;
   }

   public Class<?> getClazz() {
      return clazz;
   }

   public ManageableComponentMetadata toManageableComponentMetadata() {
      throw new UnsupportedOperationException("This component is not manageable!");
   }

   @Override
   public String toString() {
      return "ComponentMetadata{" +
            "name='" + name + '\'' +
            ", dependencies=" + dependencies +
            ", injectMetadata=" + Arrays.toString(injectMetadata) +
            ", startMethods=" + Arrays.toString(startMethods) +
            ", stopMethods=" + Arrays.toString(stopMethods) +
            ", globalScope=" + globalScope +
            ", survivesRestarts=" + survivesRestarts +
            '}';
   }

   /**
    * This class encapsulates metadata on a prioritized method, such as one annotated with {@link Start} or {@link @Stop}
    */
   public static class PrioritizedMethodMetadata implements Serializable {
      String methodName;
      transient Method method;
      int priority;

      public PrioritizedMethodMetadata(String methodName, int priority) {
         this.methodName = methodName;
         this.priority = priority;
      }

      public String getMethodName() {
         return methodName;
      }

      public Method getMethod() {
         return method;
      }

      public void setMethod(Method method) {
         this.method = method;
      }

      public int getPriority() {
         return priority;
      }
   }

   /**
    * This class encapsulates metadata on an inject method, such as one annotated with {@link Inject}
    */
   public static class InjectMetadata implements Serializable {

      //To avoid mismatches during development like as created by Maven vs IDE compiled classes:
      private static final long serialVersionUID = 4848856551345751894L;

      String methodName;
      transient Method method;
      String[] parameters;
      transient Class<?>[] parameterClasses;
      Map<Integer, String> parameterNames;

      private InjectMetadata(String methodName) {
         this.methodName = methodName;
      }

      public String getMethodName() {
         return methodName;
      }

      public String[] getParameters() {
         return parameters;
      }
     
      public String getParameterName(int subscript) {
         String name = parameterNames == null ? null : parameterNames.get(subscript);
         return name == null ? parameters[subscript] : name;
      }

      public boolean isParameterNameSet(int subscript) {
         return parameterNames != null && parameterNames.containsKey(subscript);
      }
     
      void addParameterName(int subscript, String name) {
         if (parameterNames == null) parameterNames = new HashMap<Integer, String>(1);
         parameterNames.put(subscript, name);
      }

      public synchronized Method getMethod() {
         return method;
      }

      public synchronized void setMethod(Method method) {
         this.method = method;
      }

      public synchronized Class<?>[] getParameterClasses() {
         return parameterClasses;
      }

      public synchronized void setParameterClasses(Class<?>[] parameterClasses) {
         this.parameterClasses = parameterClasses;
      }
   }
}
TOP

Related Classes of org.infinispan.factories.components.ComponentMetadata$PrioritizedMethodMetadata

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.