Package org.springsource.loaded.ri

Source Code of org.springsource.loaded.ri.FieldLookup$JavaClassFieldProvider

/*
* Copyright 2010-2012 VMware and contributors
*
* 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.springsource.loaded.ri;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

import org.objectweb.asm.Type;
import org.springsource.loaded.CurrentLiveVersion;
import org.springsource.loaded.FieldMember;
import org.springsource.loaded.GlobalConfiguration;
import org.springsource.loaded.ReloadableType;
import org.springsource.loaded.TypeRegistry;
import org.springsource.loaded.Utils;
import org.springsource.loaded.jvm.JVM;


/**
* This class contains code that is used as support infrastructure to implement Field lookup algorithms.
*
* Mainly, it provides an abstraction to allows Java classes and reloadable types to be treated as instances of a common abstraction
* "FieldProvider" and then implement algorithms to find fields in those providers independent of how the fields are being provided.
*
* @author Kris De Volder
* @since 0.5.0
*/
public class FieldLookup {

  private static class JavaFieldRef extends FieldRef {

    private Field f;

    public JavaFieldRef(Field f) {
      this.f = f;
    }

    @Override
    public Field getField() {
      return f;
    }

    @Override
    public String getName() {
      return f.getName();
    }

    @Override
    public boolean isPublic() {
      return Modifier.isPublic(f.getModifiers());
    }

  }

  private static class JavaClassFieldProvider extends FieldProvider {

    private Class<?> clazz;

    public JavaClassFieldProvider(Class<?> clazz) {
      this.clazz = clazz;
    }

    @Override
    List<FieldRef> getFields() {
      Field[] fields = clazz.getDeclaredFields();
      List<FieldRef> refs = new ArrayList<FieldLookup.FieldRef>();
      for (Field f : fields) {
        refs.add(new JavaFieldRef(f));
      }
      return refs;
    }

    @Override
    public boolean isInterface() {
      return clazz.isInterface();
    }

    @Override
    public FieldProvider[] getInterfaces() {
      Class<?>[] itfs = clazz.getInterfaces();
      FieldProvider[] provs = new FieldProvider[itfs.length];
      for (int i = 0; i < itfs.length; i++) {
        provs[i] = FieldProvider.create(itfs[i]);
      }
      return provs;
    }

    @Override
    public FieldProvider getSuper() {
      Class<?> supr = clazz.getSuperclass();
      if (supr != null) {
        FieldProvider.create(supr);
      }
      return null;
    }

  }

  static abstract class FieldRef {

    public abstract Field getField();

    public abstract String getName();

    public abstract boolean isPublic();

  }

  public static class ReloadedTypeFieldRef extends FieldRef {

    private ReloadableType rtype;
    private FieldMember f;

    public ReloadedTypeFieldRef(ReloadableType rtype, FieldMember f) {
      if (GlobalConfiguration.assertsMode) {
        Utils.assertTrue(rtype.hasBeenReloaded(), "Not yet reloaded: " + rtype.getName());
      }
      this.rtype = rtype;
      this.f = f;
    }

    @Override
    public Field getField() {
      Class<?> declaring = Utils.toClass(rtype);
      Class<?> type;
      try {
        type = Utils.toClass(Type.getType(f.getDescriptor()), rtype.typeRegistry.getClassLoader());
      } catch (ClassNotFoundException e) {
        throw new IllegalStateException(e);
      }
      return JVM.newField(declaring, type, f.getModifiers(), f.getName(), f.getGenericSignature());
    }

    @Override
    public String getName() {
      return f.getName();
    }

    @Override
    public boolean isPublic() {
      return f.isPublic();
    }

  }

  protected static abstract class FieldProvider {

    abstract List<FieldRef> getFields();

    public abstract boolean isInterface();

    public abstract FieldProvider[] getInterfaces();

    public abstract FieldProvider getSuper();

    public static FieldProvider create(ReloadableType rtype) {
      return new ReloadableTypeFieldProvider(rtype);
    }

    public static FieldProvider create(TypeRegistry typeRegistry, String slashyName) {
      if (typeRegistry.isReloadableTypeName(slashyName)) {
        return create(typeRegistry.getReloadableType(slashyName));
      } else {
        try {
          return create(Utils.toClass(Type.getObjectType(slashyName), typeRegistry.getClassLoader()));
        } catch (ClassNotFoundException e) {
          throw new IllegalStateException(e);
        }
      }
    }

    public static FieldProvider create(Class<?> clazz) {
      return new JavaClassFieldProvider(clazz);
    }
  }

  public static class ReloadableTypeFieldProvider extends FieldProvider {
    private ReloadableType rtype;

    public ReloadableTypeFieldProvider(ReloadableType rtype) {
      this.rtype = rtype;
    }

    @Override
    List<FieldRef> getFields() {
      FieldMember[] fields = rtype.getLatestTypeDescriptor().getFields();
      List<FieldRef> refs = new ArrayList<FieldRef>(fields.length);
      for (FieldMember f : fields) {
        refs.add(fieldRef(rtype, f));
      }
      return refs;
    }

    private FieldRef fieldRef(ReloadableType rtype, FieldMember f) {
      CurrentLiveVersion clv = rtype.getLiveVersion();
      if (clv == null) {
        //Not yet reloaded... use original field (with fixed mods)
        try {
          Field jf = rtype.getClazz().getDeclaredField(f.getName());
          ReflectiveInterceptor.fixModifier(rtype.getLatestTypeDescriptor(), jf);
          return new JavaFieldRef(jf);
        } catch (Exception e) {
          throw new IllegalStateException(e);
        }
      } else {
        //Already reloaded
        return new ReloadedTypeFieldRef(rtype, f);
      }
    }

    @Override
    public boolean isInterface() {
      return rtype.getLatestTypeDescriptor().isInterface();
    }

    @Override
    public FieldProvider[] getInterfaces() {
      String[] superItfs = rtype.getLatestTypeDescriptor().getSuperinterfacesName();
      FieldProvider[] superProvs = new FieldProvider[superItfs.length];
      for (int i = 0; i < superItfs.length; i++) {
        superProvs[i] = FieldProvider.create(rtype.typeRegistry, superItfs[i]);
      }
      return superProvs;
    }

    @Override
    public FieldProvider getSuper() {
      String supr = rtype.getLatestTypeDescriptor().getSupertypeName();
      if (supr != null) {
        return FieldProvider.create(rtype.typeRegistry, supr);
      }
      return null;
    }
  }

}
TOP

Related Classes of org.springsource.loaded.ri.FieldLookup$JavaClassFieldProvider

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.