/* * Copyright 2004-2015 the Seasar Foundation and the Others. * * 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.seasar.framework.jpa.util; import java.util.List; import java.util.Set; import org.seasar.framework.util.tiger.CollectionsUtil; /** * 未ロードのクラスを親クラスローダに委譲せずに自身でロードするクラスローダです。 * * @author taedium */ public class ChildFirstClassLoader extends AbstractClassLoader { /** {@link ClassLoaderListener}のリスト */ protected List<ClassLoaderListener> listeners = CollectionsUtil .newArrayList(); /** * インスタンスを構築します。 * <p> * コンテキストクラスローダからロードされるクラス及び、<code>java.</code>または<code>javax.</code>で始まるクラスを除いて * 親クラスローダに委譲せずに自身でロードするように構成します。 * </p> * */ public ChildFirstClassLoader() { this(Thread.currentThread().getContextClassLoader()); } /** * インスタンスを構築します。 * <p> * ブートストラップクラスローダからロードされるクラス及び、<code>java.</code>または<code>javax.</code>で始まるクラスを除いて * 親クラスローダに委譲せずに自身でロードするように構成します。 * </p> * * @param parent * 親クラスローダ */ public ChildFirstClassLoader(final ClassLoader parent) { super(parent); } /** * インスタンスを構築します。 * <p> * <code>includedNames</code>に含まれる名前のクラスのみ、 * 親クラスローダに委譲せずに自身でロードするように構成します。 ただし、ブートストラップクラスローダからロードされるクラス及び、 * <code>java.</code>または<code>javax.</code>で始まるクラスを除きます。 * </p> * * @param parent * 親クラスローダ * @param includedNames * 親より先にロードする対象となるクラス名のセット */ public ChildFirstClassLoader(final ClassLoader parent, final Set<String> includedNames) { super(parent, includedNames); } /** * このクラスローダから{@link ClassLoaderEvent クラスローダイベント}を受け取るために{@link ClassLoaderListener クラスローダリスナ}を追加します。 * * @param listener * リスナ */ public void addClassLoaderListener(final ClassLoaderListener listener) { listeners.add(listener); } /** * このクラスローダから{@link ClassLoaderEvent クラスローダイベント}を受け取らないために{@link ClassLoaderListener クラスローダリスナ}を削除します。 * * @param listener * リスナ */ public void removeClassLoaderListener(final ClassLoaderListener listener) { listeners.remove(listener); } /** * クラスが定義されたことを通知します。 * * @param className * 見つかったクラス名 * @param bytecode * バイトコードが納められたバイト配列 * @param definedClass * 定義されたクラス */ protected void fireClassDefinedEvent(final String className, final byte[] bytecode, final Class<?> definedClass) { final ClassLoaderEvent event = new ClassLoaderEvent(this, className, bytecode, definedClass); for (final ClassLoaderListener listener : listeners) { try { listener.classFinded(event); } catch (final Exception ignore) { } } } @Override protected Class<?> doDefineClass(String className, byte[] bytes) { final Class<?> definedClass = defineClass(className, bytes, 0, bytes.length); fireClassDefinedEvent(className, bytes, definedClass); return definedClass; } }