/** * 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 * <p/> * http://www.apache.org/licenses/LICENSE-2.0 * <p/> * 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.tomee; import org.apache.geronimo.osgi.locator.ProviderLocator; import org.apache.openejb.OpenEJBException; import org.apache.openejb.assembler.Deployer; import org.apache.openejb.assembler.DeployerEjb; import org.apache.openejb.client.EjbObjectInputStream; import org.apache.openejb.client.RemoteInitialContextFactory; import org.apache.openejb.config.RemoteServer; import org.apache.openejb.loader.IO; import org.apache.tomee.util.QuickServerXmlParser; import javax.ejb.EJBException; import javax.ejb.embeddable.EJBContainer; import javax.ejb.spi.EJBContainerProvider; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.validation.ValidationException; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import static java.lang.Thread.sleep; public class RemoteTomEEEJBContainer extends EJBContainer { private static RemoteTomEEEJBContainer instance; private RemoteServer container; private InitialContext context; @Override public void close() { instance.container.destroy(); instance.container = null; } @Override public Context getContext() { return context; } public static class Provider implements EJBContainerProvider { private static final List<String> CONTAINER_NAMES = Arrays.asList(RemoteTomEEEJBContainer.class.getName(), "tomee-remote", "remote-tomee"); @Override public EJBContainer createEJBContainer(final Map<?, ?> rawProperties) { final Map<?, ?> properties = rawProperties == null ? new HashMap<>() : rawProperties; final Object provider = properties.get(EJBContainer.PROVIDER); int ejbContainerProviders = 1; try { ejbContainerProviders = ProviderLocator.getServices(EJBContainerProvider.class.getName(), EJBContainer.class, Thread.currentThread().getContextClassLoader()).size(); } catch (final Exception e) { // no-op } if ((provider == null && ejbContainerProviders > 1) || (!RemoteTomEEEJBContainer.class.equals(provider) && !CONTAINER_NAMES.contains(String.valueOf(provider)))) { return null; } if (instance != null) { return instance; } final Object modules = properties.get(EJBContainer.MODULES); System.getProperties().putAll(properties); final File home = new File(System.getProperty("openejb.home", "doesn't exist")); if (!home.exists()) { throw new IllegalArgumentException("You need to set openejb.home"); } final QuickServerXmlParser parser = QuickServerXmlParser.parse(new File(home, "conf/server.xml")); final String remoteEjb = System.getProperty(Context.PROVIDER_URL, "http://" + parser.host() + ":" + parser.http() + "/tomee/ejb"); System.setProperty(RemoteServer.SERVER_SHUTDOWN_PORT, parser.stop()); final String blacklist = System.getProperty("tomee.serialization.class.blacklist"); if (blacklist == null) { System.setProperty("tomee.serialization.class.blacklist", "-"); EjbObjectInputStream.reloadResolverConfig(); } try { instance = new RemoteTomEEEJBContainer(); instance.container = new RemoteServer(); instance.container.setDebug("true".equalsIgnoreCase(String.valueOf(properties.get("debug")))); instance.container.setPortStartup(Integer.parseInt(parser.http())); try { instance.container.start(Arrays.asList( "-Dtomee.serialization.class.blacklist=" + System.getProperty("tomee.serialization.class.blacklist"), "-Dopenejb.system.apps=true", "-Dtomee.remote.support=true"), "start", true); } catch (final Exception e) { instance.container.destroy(); throw e; } instance.context = new InitialContext(new Properties() {{ setProperty(Context.INITIAL_CONTEXT_FACTORY, RemoteInitialContextFactory.class.getName()); setProperty(Context.PROVIDER_URL, String.valueOf(properties.containsKey(Context.PROVIDER_URL) ? properties.get(Context.PROVIDER_URL) : remoteEjb)); }}); Deployer deployer = null; for (int i = 0; i < (properties.containsKey("retries") ? Integer.parseInt(String.class.cast(properties.get("retries"))) : 4); i++) { try { deployer = Deployer.class.cast(instance.context.lookup("openejb/DeployerBusinessRemote")); if (deployer != null) { break; } } catch (final NamingException ne) { try { sleep(250); } catch (final InterruptedException ie) { Thread.interrupted(); break; } } } if (deployer == null) { throw new TomEERemoteEJBContainerException("Can't lookup deployer, eother increse retries or setup it correctly", new IllegalStateException()); } if (modules instanceof File) { final File file = File.class.cast(modules); deployFile(deployer, file); } else if (modules instanceof String) { final String path = String.class.cast(modules); final File file = new File(path); deployFile(deployer, file); } else if (modules instanceof String[]) { for (final String path : (String[]) modules) { deployFile(deployer, new File(path)); } } else if (modules instanceof File[]) { for (final File file : (File[]) modules) { deployFile(deployer, file); } } // else suppose already deployed return instance; } catch (final OpenEJBException | MalformedURLException e) { throw new EJBException(e); } catch (final ValidationException ve) { throw ve; } catch (final Exception e) { if (e instanceof EJBException) { throw (EJBException) e; } throw new TomEERemoteEJBContainerException("initialization exception", e); } finally { if (blacklist == null) { System.clearProperty("tomee.serialization.class.blacklist"); EjbObjectInputStream.reloadResolverConfig(); } } } } private static void deployFile(final Deployer deployer, final File file) throws IOException, OpenEJBException { if ("true".equalsIgnoreCase(System.getProperty(DeployerEjb.OPENEJB_USE_BINARIES, "false"))) { final Properties props = new Properties(); final byte[] slurpBinaries = IO.slurp(file).getBytes(); props.put(DeployerEjb.OPENEJB_VALUE_BINARIES, slurpBinaries); props.put(DeployerEjb.OPENEJB_PATH_BINARIES, file.getName()); deployer.deploy(file.getAbsolutePath(), props); } else { deployer.deploy(file.getAbsolutePath()); } } protected static class TomEERemoteEJBContainerException extends RuntimeException { protected TomEERemoteEJBContainerException(final String s, final Exception e) { super(s, e); } } }