001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.jci.stores; 018 019 import org.apache.commons.jci.utils.ConversionUtils; 020 import org.apache.commons.logging.Log; 021 import org.apache.commons.logging.LogFactory; 022 023 024 /** 025 * A ClassLoader backed by an array of ResourceStores 026 * 027 * @author tcurdt 028 */ 029 public final class ResourceStoreClassLoader extends ClassLoader { 030 031 private final Log log = LogFactory.getLog(ResourceStoreClassLoader.class); 032 033 private final ResourceStore[] stores; 034 035 public ResourceStoreClassLoader( final ClassLoader pParent, final ResourceStore[] pStores ) { 036 super(pParent); 037 038 stores = new ResourceStore[pStores.length]; 039 System.arraycopy(pStores, 0, stores, 0, stores.length); 040 } 041 042 private Class<?> fastFindClass(final String name) { 043 044 if (stores != null) { 045 for (ResourceStore store : stores) { 046 final byte[] clazzBytes = store.read(ConversionUtils.convertClassToResourcePath(name)); 047 if (clazzBytes != null) { 048 log.debug(getId() + " found class: " + name + " (" + clazzBytes.length + " bytes)"); 049 return defineClass(name, clazzBytes, 0, clazzBytes.length); 050 } 051 } 052 } 053 054 return null; 055 } 056 057 @Override 058 protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { 059 // log.debug(getId() + " looking for: " + name); 060 Class<?> clazz = findLoadedClass(name); 061 062 if (clazz == null) { 063 clazz = fastFindClass(name); 064 065 if (clazz == null) { 066 067 final ClassLoader parent = getParent(); 068 if (parent != null) { 069 clazz = parent.loadClass(name); 070 // log.debug(getId() + " delegating loading to parent: " + name); 071 } else { 072 throw new ClassNotFoundException(name); 073 } 074 075 } else { 076 log.debug(getId() + " loaded from store: " + name); 077 } 078 } 079 080 if (resolve) { 081 resolveClass(clazz); 082 } 083 084 return clazz; 085 } 086 087 @Override 088 protected Class<?> findClass( final String name ) throws ClassNotFoundException { 089 final Class<?> clazz = fastFindClass(name); 090 if (clazz == null) { 091 throw new ClassNotFoundException(name); 092 } 093 return clazz; 094 } 095 096 private String getId() { 097 return "" + this + "[" + this.getClass().getClassLoader() + "]"; 098 } 099 }