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.discovery.tools; 018 019 import org.apache.commons.discovery.ResourceClass; 020 import org.apache.commons.discovery.ResourceClassIterator; 021 import org.apache.commons.discovery.resource.classes.DiscoverClasses; 022 import org.apache.commons.discovery.resource.ClassLoaders; 023 024 /** 025 * Holder for a default class. 026 * 027 * Class may be specified by name (String) or class (Class). 028 * Using the holder complicates the users job, but minimized # of API's. 029 */ 030 public class DefaultClassHolder<T> { 031 032 private Class<? extends T> defaultClass; 033 034 private final String defaultName; 035 036 /** 037 * Creates a new holder implementation given 038 * the input SPI implementation/extension class. 039 * 040 * @param <S> Any type extends the SPI type 041 * @param defaultClass The hold class 042 */ 043 public <S extends T> DefaultClassHolder(Class<S> defaultClass) { 044 this.defaultClass = defaultClass; 045 this.defaultName = defaultClass.getName(); 046 } 047 048 /** 049 * Creates a new holder implementation given 050 * the input SPI implementation/extension class name. 051 * 052 * @param defaultName The hold class name 053 */ 054 public DefaultClassHolder(String defaultName) { 055 this.defaultClass = null; 056 this.defaultName = defaultName; 057 } 058 059 /** 060 * Returns the default class, loading it if necessary 061 * and verifying that it implements the SPI 062 * (this forces the check, no way out..). 063 * 064 * @param <S> Any type extends the SPI type 065 * @param spi non-null SPI 066 * @param loaders Used only if class needs to be loaded. 067 * @return The default Class. 068 */ 069 public <S extends T> Class<S> getDefaultClass(SPInterface<T> spi, ClassLoaders loaders) { 070 if (defaultClass == null) { 071 DiscoverClasses<T> classDiscovery = new DiscoverClasses<T>(loaders); 072 ResourceClassIterator<T> classes = classDiscovery.findResourceClasses(getDefaultName()); 073 if (classes.hasNext()) { 074 ResourceClass<T> info = classes.nextResourceClass(); 075 try { 076 defaultClass = info.loadClass(); 077 } catch (Exception e) { 078 // ignore 079 } 080 } 081 } 082 083 if (defaultClass != null) { 084 spi.verifyAncestory(defaultClass); 085 } 086 087 @SuppressWarnings("unchecked") // the SPInterface.verifyAncestory already asserted 088 Class<S> returned = (Class<S>) defaultClass; 089 return returned; 090 } 091 092 /** 093 * Returns the hold class name. 094 * 095 * @return The hold class name 096 */ 097 public String getDefaultName() { 098 return defaultName; 099 } 100 101 }