/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.webbeans.corespi.scanner;
import org.apache.webbeans.config.OWBLogConst;
import org.apache.webbeans.config.OpenWebBeansConfiguration;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.corespi.scanner.xbean.CdiArchive;
import org.apache.webbeans.exception.WebBeansConfigurationException;
import org.apache.webbeans.exception.WebBeansDeploymentException;
import org.apache.webbeans.logger.WebBeansLoggerFacade;
import org.apache.webbeans.spi.BDABeansXmlScanner;
import org.apache.webbeans.spi.ScannerService;
import org.apache.webbeans.util.ClassUtil;
import org.apache.webbeans.util.UrlSet;
import org.apache.webbeans.util.WebBeansUtil;
import org.apache.xbean.finder.AnnotationFinder;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
public abstract class AbstractMetaDataDiscovery implements ScannerService
{
protected static final Logger logger = WebBeansLoggerFacade.getLogger(AbstractMetaDataDiscovery.class);
public static final String META_INF_BEANS_XML = "META-INF/beans.xml";
/** Location of the beans.xml files. */
private final UrlSet webBeansXmlLocations = new UrlSet();
//private Map<String, InputStream> EJB_XML_LOCATIONS = new HashMap<String, InputStream>();
protected ClassLoader loader;
protected CdiArchive archive;
protected AnnotationFinder finder;
protected boolean isBDAScannerEnabled = false;
protected BDABeansXmlScanner bdaBeansXmlScanner;
protected AnnotationFinder initFinder()
{
if (finder != null)
{
return finder;
}
final Collection<URL> trimmedUrls = new ArrayList<URL>();
for (final URL url : getUrls())
{
try
{
String file = url.getFile();
if (file.endsWith(META_INF_BEANS_XML))
{
file = file.substring(0, file.length() - META_INF_BEANS_XML.length());
}
else if (file.endsWith("WEB-INF/beans.xml"))
{
file = file.substring(0, file.length() - "WEB-INF/beans.xml".length());
}
trimmedUrls.add(new URL(url.getProtocol(), url.getHost(), url.getPort(), file));
}
catch (MalformedURLException e)
{
throw new WebBeansConfigurationException("Can't trim url " + url.toExternalForm());
}
}
archive = new CdiArchive(WebBeansUtil.getCurrentClassLoader(), trimmedUrls);
finder = new AnnotationFinder(archive);
return finder;
}
protected Iterable<URL> getUrls()
{
return webBeansXmlLocations;
}
/**
* Configure the Web Beans Container with deployment information and fills
* annotation database and beans.xml stream database.
*
* @throws org.apache.webbeans.exception.WebBeansConfigurationException if any run time exception occurs
*/
@Override
public void scan() throws WebBeansDeploymentException
{
try
{
configure();
initFinder();
}
catch (Exception e)
{
throw new WebBeansDeploymentException(e);
}
}
@Override
public void release()
{
finder = null;
archive = null;
loader = null;
}
abstract protected void configure();
/**
* Find the base paths of all available resources with the given
* resourceName in the classpath.
* The returned Strings will <i>NOT</i> contain the resourceName itself!
*
* @param resourceName the name of the resource, e.g. 'META-INF/beans.xml'
* @param loader the ClassLoader which should be used
* @return array of Strings with the URL path to the resources.
*/
protected String[] findBeansXmlBases(String resourceName, ClassLoader loader)
{
this.loader = loader;
ArrayList<String> list = new ArrayList<String>();
try
{
Enumeration<URL> urls = loader.getResources(resourceName);
while (urls.hasMoreElements())
{
URL url = urls.nextElement();
addWebBeansXmlLocation(url);
String urlString = url.toString();
int idx = urlString.lastIndexOf(resourceName);
urlString = urlString.substring(0, idx);
list.add(urlString);
}
}
catch (IOException e)
{
throw new RuntimeException(e);
}
return list.toArray(new String[list.size()]);
}
@Override
public void init(Object object)
{
// set per BDA beans.xml flag here because setting it in constructor
// occurs before
// properties are loaded.
String usage = WebBeansContext.currentInstance().getOpenWebBeansConfiguration().getProperty(OpenWebBeansConfiguration.USE_BDA_BEANSXML_SCANNER);
isBDAScannerEnabled = Boolean.parseBoolean(usage);
}
public Set<String> getAllAnnotations(String className)
{
throw new UnsupportedOperationException();
}
/**
* add the given beans.xml path to the locations list
* @param beansXmlUrl location path
*/
protected void addWebBeansXmlLocation(URL beansXmlUrl)
{
if(logger.isLoggable(Level.INFO))
{
logger.info("added beans.xml marker: " + beansXmlUrl.toExternalForm());
}
webBeansXmlLocations.add(beansXmlUrl);
}
/* (non-Javadoc)
* @see org.apache.webbeans.corespi.ScannerService#getBeanClasses()
*/
@Override
public Set<Class<?>> getBeanClasses()
{
final Set<Class<?>> classSet = new HashSet<Class<?>>();
for(String str : archive.getClasses())
{
try
{
Class<?> clazz = ClassUtil.getClassFromName(str);
if (clazz != null)
{
// try to provoke a NoClassDefFoundError exception which is thrown
// if some dependencies of the class are missing
clazz.getDeclaredFields();
clazz.getDeclaredMethods();
// we can add this class cause it has been loaded completely
classSet.add(clazz);
}
}
catch (NoClassDefFoundError e)
{
if (logger.isLoggable(Level.WARNING))
{
logger.log(Level.WARNING, OWBLogConst.WARN_0018, new Object[] { str, e.toString() });
}
}
}
return classSet;
}
/* (non-Javadoc)
* @see org.apache.webbeans.corespi.ScannerService#getBeanXmls()
*/
@Override
public Set<URL> getBeanXmls()
{
return Collections.unmodifiableSet(webBeansXmlLocations);
}
@Override
public BDABeansXmlScanner getBDABeansXmlScanner()
{
return bdaBeansXmlScanner;
}
@Override
public boolean isBDABeansXmlScanningEnabled()
{
return isBDAScannerEnabled;
}
}