/* * Copyright 2010 Impetus Infotech. * * 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 com.impetus.annovention; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The Class ClasspathReader. * * @author animesh.kumar */ public class ClasspathDiscoverer extends Discoverer { private static final Logger log = LoggerFactory.getLogger(ClasspathDiscoverer.class); /** The filter. */ private Filter filter; /** * Instantiates a new classpath reader. */ public ClasspathDiscoverer() { filter = new FilterImpl(); } /** * Uses java.class.path system-property to fetch URLs * * @return the URL[] */ @Override public final URL[] findResources(ClassLoader cl) { List<URL> list = new ArrayList<URL>(); Enumeration<URL> resources = loadPersistenceFiles(cl); if(log.isTraceEnabled()) log.trace("about to log the jar resources here that contain nosql.Persistence.class..."); Set<URL> urlsToScan = new HashSet<URL>(); while(resources.hasMoreElements()) { URL url = resources.nextElement(); if(urlsToScan.contains(url)) continue; urlsToScan.add(url); if(log.isTraceEnabled()) log.trace("found url with nosql.Persistence.class so scanning enabled on this url="+url); } if(urlsToScan.size() == 0) throw new IllegalArgumentException("We did not fine the nosql.Persistence.class file on the classpath for any jar. This file needs to exist in the jars with @Entity objects and we will only scan those jars(or folders)"); //At this point, we have urls that point to NoSqlPersistence.class which may be in a jar or in //a folder. for(URL fileInJarOrFolderUrl : urlsToScan) { String protocol = fileInJarOrFolderUrl.getProtocol(); if("file".equals(protocol)) { processFile(fileInJarOrFolderUrl, list); } else if("jar".equals(protocol)) { processJar(fileInJarOrFolderUrl, list); } else if ("vfs".equals(protocol)) { processVfs(fileInJarOrFolderUrl, list); } else throw new RuntimeException("protocol of="+protocol+" is not supported for loading classfiles, let me know and I can fix that"); } return list.toArray(new URL[list.size()]); } private void processVfs(URL fileInJarOrFolderUrl, List<URL> list) { /* * URL is either * vfs:/C:/sw/jboss-eap-6.1/bin/content/EarTesting.war/WEB-INF/lib/playorm-1.7-SNAPSHOT.jar/nosql/Persistence.class in case of Jar * OR * vfs:/C:/sw/jboss-eap-6.1/bin/content/EarTesting.war/WEB-INF/classes/nosql/Persistence.class in case of a folder */ String file = fileInJarOrFolderUrl.getFile(); int fillength = file.length(); String s = "/nosql/Persistence.class"; int substringlength = s.length(); String ur = file.substring(0, (fillength - substringlength)); String prefix = "vfs:" + ur; URL url = createUrl(prefix); if (log.isInfoEnabled()) log.info("adding jar file for scanning=" + url); list.add(url); } private void processJar(URL fileInJarOrFolderUrl, List<URL> list) { String file = fileInJarOrFolderUrl.getFile(); //format of jar file is file:/Users/dhiller2/AAROOT/area1/fullSDI/restApi/lib/nosqlorm.jar!/nosql/Persistence.class //so we split on ! first nd get the first piece. String[] pieces = file.split("!"); String firstPiece = pieces[0]; //Now we have firstPiece = file:/Users/dhiller2/AAROOT/area1/fullSDI/restApi/lib/nosqlorm.jar String prefix = "jar:"+firstPiece+"!/"; URL url = createUrl(prefix); if (log.isInfoEnabled()) log.info("adding jar file for scanning="+url); list.add(url); } private URL createUrl(String prefix) { try { URL url = new URL(prefix); return url; } catch(MalformedURLException e) { throw new RuntimeException(e); } } private void processFile(URL fileInJarOrFolderUrl, List<URL> list) { String file = fileInJarOrFolderUrl.getFile(); File f = new File(file); File classFolder = f.getParentFile().getParentFile(); URL url = toUrl(classFolder); if (log.isInfoEnabled()) log.info("adding folder to scan="+url); list.add(url); } private URL toUrl(File f) { try { return f.toURI().toURL(); } catch (MalformedURLException e) { throw new RuntimeException("bug in converting file to url="+f.getAbsolutePath(), e); } } private Enumeration<URL> loadPersistenceFiles(ClassLoader cl) { try { Enumeration<URL> resources = cl.getResources("nosql/Persistence.class"); //grrrrr, temporary hack as ecipse can't take two Persistence.java one in src/main/java and one in src/main/test //while a JVM can do just fine with that. Enumeration<URL> xmlFiles = cl.getResources("nosql/Persistence2.class"); return new ProxyEnum(resources, xmlFiles); } catch(IOException e) { throw new RuntimeException("some kind of bug", e); } } private static class ProxyEnum implements Enumeration<URL> { private Enumeration<URL> resources; private Enumeration<URL> xmlFiles; public ProxyEnum(Enumeration<URL> resources, Enumeration<URL> xmlFiles) { this.resources = resources; this.xmlFiles = xmlFiles; } @Override public boolean hasMoreElements() { return resources.hasMoreElements() || xmlFiles.hasMoreElements(); } @Override public URL nextElement() { if(resources.hasMoreElements()) return resources.nextElement(); return xmlFiles.nextElement(); } } /* @see com.impetus.annovention.Discoverer#getFilter() */ public final Filter getFilter() { return filter; } /** * @param filter */ public final void setFilter(Filter filter) { this.filter = filter; } }