package act.app; /*- * #%L * ACT Framework * %% * Copyright (C) 2014 - 2017 ActFramework * %% * 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. * #L% */ import act.Act; import act.util.DestroyableBase; import org.osgl.$; import org.osgl.logging.LogManager; import org.osgl.logging.Logger; import org.osgl.util.C; import org.osgl.util.E; import javax.enterprise.context.ApplicationScoped; import java.util.Iterator; import java.util.Map; import static act.Destroyable.Util.tryDestroyAll; /** * Manage applications deployed on Act */ public class AppManager extends DestroyableBase { private static Logger logger = LogManager.get(AppManager.class); private Map<Integer, App> byPort = C.newMap(); private AppManager() { } @Override protected void releaseResources() { tryDestroyAll(byPort.values(), ApplicationScoped.class); byPort = null; } public AppManager scan() { Act.mode().appScanner().scan(null, _F.loadApp(this)); return this; } public AppManager loadSingleApp(String name) { AppScanner.SINGLE_APP_SCANNER.scan(name, _F.loadApp(this)); return this; } public void deploy(App app) { load(app); refresh(app); } public void refresh() { Iterator<App> itr = appIterator(); while (itr.hasNext()) { refresh(itr.next()); } } public void refresh(App app) { app.refresh(); } public void load(App app) { app.build(); app.refresh(); int port = app.config().httpPort(); E.invalidConfigurationIf(port < 0, "Invalid http.port configuration: %s", port); loadIntoPortMap(port, app); app.hook(); } public boolean unload(App app) { boolean b = unloadApp(app, byPort); if (byPort.isEmpty()) { Act.shutdown(); } return b; } private boolean unloadApp(App app, Map<?, App> map) { for (Map.Entry<?, App> entry : map.entrySet()) { if (app == entry.getValue()) { app.destroy(); map.remove(entry.getKey()); return true; } } return false; } private void loadIntoPortMap(int port, App app) { App app0 = byPort.get(port); if (null != app0) { E.invalidConfigurationIf(!app.equals(app0), "Another application has already been deployed using port %s", port); } else { byPort.put(port, app); } } private Iterator<App> appIterator() { final Iterator<App> itrByPort = byPort.values().iterator(); return new Iterator<App>() { boolean byPortFinished = !itrByPort.hasNext(); @Override public boolean hasNext() { if (!byPortFinished) { byPortFinished = !itrByPort.hasNext(); } return !byPortFinished; } @Override public App next() { return byPortFinished ? null : itrByPort.next(); } @Override public void remove() { E.unsupport(); } }; } public static AppManager create() { return new AppManager(); } private enum _F { ; static final $.F1<App, ?> loadApp(final AppManager mgr) { return new $.Visitor<App>() { @Override public void visit(App app) throws $.Break { try { mgr.load(app); } catch (RuntimeException e) { Act.shutdownApp(app); throw e; } } }; } } }