/** * 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.aries.ejb.modelling.impl; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.aries.application.modelling.ModellerException; import org.apache.aries.ejb.modelling.EJBLocator; import org.apache.aries.ejb.modelling.EJBRegistry; import org.apache.aries.util.filesystem.ICloseableDirectory; import org.apache.aries.util.filesystem.IDirectory; import org.apache.aries.util.filesystem.IFile; import org.apache.aries.util.manifest.BundleManifest; import org.apache.aries.util.manifest.ManifestHeaderProcessor; import org.apache.aries.util.manifest.ManifestHeaderProcessor.NameValuePair; import org.apache.openejb.config.AnnotationDeployer; import org.apache.openejb.config.AppModule; import org.apache.openejb.config.EjbModule; import org.apache.openejb.config.ReadDescriptors; import org.apache.openejb.jee.EjbJar; import org.apache.openejb.jee.EnterpriseBean; import org.apache.openejb.jee.SessionBean; import org.osgi.framework.Constants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An {@link EJBLocator} that uses OpenEJB to find EJBs * */ public class OpenEJBLocator implements EJBLocator { private static final Logger logger = LoggerFactory.getLogger(OpenEJBLocator.class); public class ClasspathIDirectory implements IDirectory { private final IDirectory parent; private final String entry; public ClasspathIDirectory(IDirectory parent, String name) { this.parent = parent; this.entry = (name.endsWith("/")) ? name : name + "/"; } public IDirectory convert() { return parent.convert(); } public IDirectory convertNested() { return parent.convertNested(); } public IFile getFile(String arg0) { return parent.getFile(entry + arg0); } public long getLastModified() { return parent.getLastModified(); } public String getName() { return parent.getName() + entry; } public IDirectory getParent() { return parent.getParent(); } public IDirectory getRoot() { return parent.getRoot(); } public long getSize() { return parent.getSize(); } public boolean isDirectory() { return parent.isDirectory(); } public boolean isFile() { return parent.isFile(); } public boolean isRoot() { return parent.isRoot(); } public Iterator<IFile> iterator() { return parent.iterator(); } public List<IFile> listAllFiles() { List<IFile> files = new ArrayList<IFile>(); for(IFile f : parent.listAllFiles()) { if(f.getName().startsWith(entry)) files.add(f); } return files; } public List<IFile> listFiles() { List<IFile> files = new ArrayList<IFile>(); for(IFile f : parent.listFiles()) { if(f.getName().startsWith(entry)) files.add(f); } return files; } public InputStream open() throws IOException, UnsupportedOperationException { return parent.open(); } public ICloseableDirectory toCloseable() { return parent.toCloseable(); } public URL toURL() throws MalformedURLException { return parent.toURL(); } } public void findEJBs(BundleManifest manifest, IDirectory bundle, EJBRegistry registry) throws ModellerException { logger.debug("Scanning " + manifest.getSymbolicName() + "_" + manifest.getManifestVersion() + " for EJBs"); String ejbJarLocation = (manifest.getRawAttributes().getValue( "Web-ContextPath") == null) ? "META-INF/ejb-jar.xml" : "WEB-INF/ejb-jar.xml"; try { //If we have an ejb-jar.xml then parse it IFile file = bundle.getFile(ejbJarLocation); EjbJar ejbJar = (file == null) ? new EjbJar() : ReadDescriptors.readEjbJar(file.toURL()); EjbModule module = new EjbModule(ejbJar); //We build our own because we can't trust anyone to get the classpath right otherwise! module.setFinder(new IDirectoryFinder(AnnotationDeployer.class.getClassLoader(), getClassPathLocations(manifest, bundle))); //Scan our app for annotated EJBs AppModule app = new AppModule(module); new AnnotationDeployer().deploy(app); //Register our session beans for(EnterpriseBean eb : ejbJar.getEnterpriseBeans()) { if(!!!(eb instanceof SessionBean)) continue; else registerSessionBean(registry, (SessionBean) eb); } } catch (Exception e) { throw new ModellerException(e); } } /** * Find the classpath entries for our bundle * * @param manifest * @param bundle * @return */ private List<IDirectory> getClassPathLocations(BundleManifest manifest, IDirectory bundle) { List<IDirectory> result = new ArrayList<IDirectory>(); String rawCp = manifest.getRawAttributes().getValue(Constants.BUNDLE_CLASSPATH); logger.debug("Classpath is " + rawCp); if(rawCp == null || rawCp.trim() == "") result.add(bundle); else { List<NameValuePair> splitCp = ManifestHeaderProcessor.parseExportString(rawCp); List<IFile> allFiles = null; for(NameValuePair nvp : splitCp) { String name = nvp.getName().trim(); if(".".equals(name)) { result.add(bundle); } else { IFile f = bundle.getFile(name); if(f==null) { //This possibly just means no directory entries in a //Zip. Check to make sure if(allFiles == null) allFiles = bundle.listAllFiles(); for(IFile file : allFiles) { if(file.getName().startsWith(name)) { result.add(new ClasspathIDirectory(bundle, name)); break; } } } else { IDirectory converted = f.convertNested(); if(converted != null) result.add(converted); } } } } return result; } /** * Register a located session bean with the {@link EJBRegistry} * @param registry * @param sb */ private void registerSessionBean(EJBRegistry registry, SessionBean sb) { String name = sb.getEjbName(); String type = sb.getSessionType().toString(); logger.debug("Found EJB " + name + " of type " + type); boolean added = false; for(String iface : sb.getBusinessLocal()) { added = true; registry.addEJBView(name, type, iface, false); } for(String iface : sb.getBusinessRemote()) { added = true; registry.addEJBView(name, type, iface, true); } if(sb.getLocal() != null) { added = true; registry.addEJBView(name, type, sb.getLocal(), false); } if(sb.getLocalHome() != null) { added = true; registry.addEJBView(name, type, sb.getLocalHome(), false); } if(sb.getRemote() != null) { added = true; registry.addEJBView(name, type, sb.getRemote(), true); } if(sb.getHome() != null) { added = true; registry.addEJBView(name, type, sb.getHome(), true); } //If not added elsewhere then we have a no-interface view if(!!!added) { registry.addEJBView(name, type, sb.getEjbClass(), false); } } }