001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020package org.apache.isis.core.metamodel.specloader.classsubstitutor; 021 022import java.util.Set; 023 024import com.google.common.collect.Sets; 025 026import org.apache.isis.applib.DomainObjectContainer; 027import org.apache.isis.core.commons.lang.ClassUtil; 028 029public abstract class ClassSubstitutorAbstract implements ClassSubstitutor { 030 031 private final Set<Class<?>> classesToIgnore = Sets.newHashSet(); 032 private final Set<String> classNamesToIgnore = Sets.newHashSet(); 033 034 /** 035 * Will implicitly ignore the {@link DomainObjectContainer}. 036 */ 037 public ClassSubstitutorAbstract() { 038 ignore(DomainObjectContainer.class); 039 040 // ignore cglib 041 ignore("net.sf.cglib.proxy.Factory"); 042 ignore("net.sf.cglib.proxy.MethodProxy"); 043 ignore("net.sf.cglib.proxy.Callback"); 044 045 // ignore javassist 046 ignore("javassist.util.proxy.ProxyObject"); 047 ignore("javassist.util.proxy.MethodHandler"); 048 049 } 050 051 // ///////////////////////////////////////////////////////////////// 052 // init, shutdown 053 // ///////////////////////////////////////////////////////////////// 054 055 /** 056 * Default implementation does nothing. 057 */ 058 @Override 059 public void init() { 060 } 061 062 /** 063 * Default implementation does nothing. 064 */ 065 @Override 066 public void shutdown() { 067 } 068 069 // ///////////////////////////////////////////////////////////////// 070 // ClassSubstitutor impl. 071 // ///////////////////////////////////////////////////////////////// 072 073 /** 074 * Hook method for subclasses to override if required. 075 * 076 * <p> 077 * Default implementation will either return the class, unless has been 078 * registered as to be {@link #ignore(Class) ignore}d, in which case returns 079 * <tt>null</tt>. 080 */ 081 @Override 082 public Class<?> getClass(final Class<?> cls) { 083 if (shouldIgnore(cls)) { 084 return null; 085 } 086 final Class<?> superclass = cls.getSuperclass(); 087 if(superclass != null && superclass.isEnum()) { 088 return superclass; 089 } 090 if (ClassUtil.directlyImplements(cls, JavassistEnhanced.class)) { 091 return getClass(cls.getSuperclass()); 092 } 093 return cls; 094 } 095 096 097 private boolean shouldIgnore(final Class<?> cls) { 098 if (cls.isArray()) { 099 return shouldIgnore(cls.getComponentType()); 100 } 101 return classesToIgnore.contains(cls) || classNamesToIgnore.contains(cls.getCanonicalName()); 102 } 103 104 // //////////////////////////////////////////////////////////////////// 105 // ignoring 106 // //////////////////////////////////////////////////////////////////// 107 108 /** 109 * For any classes registered as ignored, {@link #getClass(Class)} will 110 * return <tt>null</tt>. 111 */ 112 protected boolean ignore(final Class<?> q) { 113 return classesToIgnore.add(q); 114 } 115 116 /** 117 * For any classes registered as ignored, {@link #getClass(Class)} will 118 * return <tt>null</tt>. 119 */ 120 protected boolean ignore(final String className) { 121 return classNamesToIgnore.add(className); 122 } 123 124 125 // //////////////////////////////////////////////////////////////////// 126 // injectInto 127 // //////////////////////////////////////////////////////////////////// 128 129 @Override 130 public void injectInto(final Object candidate) { 131 if (ClassSubstitutorAware.class.isAssignableFrom(candidate.getClass())) { 132 final ClassSubstitutorAware cast = ClassSubstitutorAware.class.cast(candidate); 133 cast.setClassSubstitutor(this); 134 } 135 } 136 137}