001 /*
002 * Licensed under the Apache License, Version 2.0 (the "License");
003 * you may not use this file except in compliance with the License.
004 * You may obtain a copy of the License at
005 *
006 * http://www.apache.org/licenses/LICENSE-2.0
007 *
008 * Unless required by applicable law or agreed to in writing, software
009 * distributed under the License is distributed on an "AS IS" BASIS,
010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011 * See the License for the specific language governing permissions and
012 * limitations under the License.
013 */
014 package org.apache.commons.classscan.builtin;
015
016 import java.io.InputStream;
017 import java.util.Collection;
018 import java.util.HashMap;
019 import java.util.Iterator;
020 import java.util.Map;
021
022 import org.apache.commons.classscan.ClassPathElement;
023 import org.apache.commons.classscan.ClassFile;
024 import org.apache.commons.classscan.model.MetaClass;
025 import org.apache.commons.classscan.spi.model.SpiMetaClass;
026 import org.apache.commons.classscan.spi.model.SpiMetaClassLoader;
027 import org.apache.commons.classscan.spi.model.SpiMetaClassPathElement;
028 import org.apache.commons.classscan.spi.model.SpiMetaRegistry;
029 import org.apache.commons.classscan.util.NameSet;
030 import org.slf4j.Logger;
031 import org.slf4j.LoggerFactory;
032
033 public class DefaultMetaClassPathElement implements SpiMetaClassPathElement {
034
035 private static final Logger logger = LoggerFactory.getLogger(DefaultMetaClassPathElement.class);
036
037 private final String baseUrl;
038 private Map<String, SpiMetaClass> workClasses = new HashMap<String, SpiMetaClass>();
039 private NameSet<SpiMetaClass> sealedClasses;
040
041 public DefaultMetaClassPathElement(SpiMetaRegistry metaRegistry, ClassPathElement classPathElement) {
042 this.baseUrl = classPathElement.getLocation();
043
044 for(ClassFile classPathFile : classPathElement) {
045 addFile(metaRegistry, classPathFile);
046 }
047 }
048
049 private void addFile(SpiMetaRegistry metaRegistry, ClassFile classPathFile) {
050 String className = classPathFile.getClassName();
051 try {
052 InputStream byteStream = classPathFile.getBytes();
053 try {
054 SpiMetaClass mc= metaRegistry.createMetaClass(this, className, byteStream);
055 addMetaClass(mc);
056 }
057 finally {
058 byteStream.close();
059 }
060 } catch (Exception e) {
061 logger.info("Exception while loading "+className, e);
062 }
063 }
064
065 void addMetaClass(SpiMetaClass mc) {
066 String name= mc.getName();
067 if (workClasses.containsKey(name)) {
068 return;
069 }
070 workClasses.put(name, mc);
071 }
072
073 @Override
074 public boolean resolve(SpiMetaClassLoader classLoader) {
075 if( workClasses.isEmpty() ) {
076 sealedClasses = NameSet.emptyNameSet();
077 }
078 else {
079 Iterator<Map.Entry<String, SpiMetaClass>> metaClasses = workClasses.entrySet().iterator();
080 while(metaClasses.hasNext()) {
081 Map.Entry<String, SpiMetaClass> entry = metaClasses.next();
082 if(!entry.getValue().resolve(classLoader)) {
083 logger.info("Could not resolve dependencies of "+entry.getKey());
084 metaClasses.remove();
085 }
086 }
087 sealedClasses = new NameSet<SpiMetaClass>(SpiMetaClass.class, workClasses.values());
088 }
089
090 workClasses = null;
091 if( sealedClasses.isEmpty() ) {
092 logger.info("No classes in "+baseUrl);
093 return false;
094 }
095 return true;
096 }
097
098 @Override
099 public MetaClass resolveMetaClass(SpiMetaClassLoader classLoader, String className) {
100 if(workClasses==null) {
101 return sealedClasses.getValue(className);
102 }
103 SpiMetaClass workClass = workClasses.get(className);
104 if( workClass != null && workClass.resolve(classLoader) ) {
105 return workClass;
106 }
107 return null;
108 }
109
110 @Override
111 public Collection<? extends MetaClass> getMetaClasses() {
112 return sealedClasses;
113 }
114
115 @Override
116 public MetaClass getMetaClass(String className) {
117 return sealedClasses.getValue(className);
118 }
119
120 @Override
121 public String getName() {
122 return baseUrl;
123 }
124 }