001/*
002 * (C) Copyright 2006-2017 Nuxeo (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     bstefanescu
018 */
019package org.nuxeo.ecm.webengine.jaxrs;
020
021import java.util.HashMap;
022import java.util.Map;
023
024import org.nuxeo.common.utils.StringUtils;
025import org.osgi.framework.Bundle;
026import org.osgi.framework.BundleContext;
027import org.osgi.framework.BundleEvent;
028import org.osgi.util.tracker.BundleTracker;
029import org.osgi.util.tracker.BundleTrackerCustomizer;
030
031/**
032 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
033 */
034public class ApplicationManager implements BundleTrackerCustomizer {
035
036    public final static String HOST_ATTR = "host";
037
038    public final static String DEFAULT_HOST = "default";
039
040    private final static ApplicationManager instance = new ApplicationManager();
041
042    public static ApplicationManager getInstance() {
043        return instance;
044    }
045
046    protected BundleTracker tracker;
047
048    protected Map<String, ApplicationHost> apps;
049
050    public ApplicationManager() {
051    }
052
053    public synchronized void start(BundleContext context) {
054        apps = new HashMap<>();
055        tracker = new BundleTracker(context, Bundle.ACTIVE | Bundle.STARTING | Bundle.RESOLVED, this);
056        tracker.open();
057    }
058
059    public synchronized void stop(BundleContext context) {
060        tracker.close();
061        tracker = null;
062        apps = null;
063    }
064
065    public synchronized ApplicationHost getOrCreateApplication(String name) {
066        ApplicationHost host = apps.get(name);
067        if (host == null) {
068            host = new ApplicationHost(name);
069            apps.put(name, host);
070        }
071        return host;
072    }
073
074    public synchronized ApplicationHost[] getApplications() {
075        return apps.values().toArray(new ApplicationHost[apps.size()]);
076    }
077
078    public synchronized ApplicationHost getApplication(String name) {
079        return apps.get(name);
080    }
081
082    public synchronized ApplicationHost getApplication(ApplicationFragment fragment) {
083        String host = fragment.getHostName();
084        return apps.get(host);
085    }
086
087    @Override
088    public Object addingBundle(Bundle bundle, BundleEvent event) {
089        String v = (String) bundle.getHeaders().get("Nuxeo-WebModule");
090        if (v != null) {
091            String classRef;
092            Map<String, String> vars = new HashMap<>();
093            String varsStr = null;
094            int i = v.indexOf(';');
095            if (i > -1) {
096                classRef = v.substring(0, i).trim();
097                varsStr = v.substring(i + 1).trim();
098            } else {
099                classRef = v.trim();
100            }
101            if (varsStr != null) {
102                vars = parseAttrs(varsStr);
103            }
104            ApplicationFragment fragment = new ApplicationFragment(bundle, classRef, vars);
105            ApplicationHost app = getOrCreateApplication(fragment.getHostName());
106            app.add(fragment);
107            app.reload();
108            return fragment;
109        }
110        return null;
111    }
112
113    @Override
114    public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
115        // TODO not yet impl.
116        if (event.getType() == BundleEvent.UPDATED) {
117            ApplicationFragment fragment = (ApplicationFragment) object;
118            if (fragment != null) {
119                ApplicationHost app = getApplication(fragment);
120                if (app != null) {
121                    app.reload();
122                }
123            }
124        }
125    }
126
127    @Override
128    public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
129        ApplicationFragment fragment = (ApplicationFragment) object;
130        if (fragment != null) {
131            ApplicationHost app = getApplication(fragment);
132            if (app != null) {
133                app.remove(fragment);
134                app.reload();
135            }
136        }
137    }
138
139    protected Map<String, String> parseAttrs(String expr) {
140        Map<String, String> map = new HashMap<>();
141        String[] ar = StringUtils.split(expr, ';', true);
142        for (String a : ar) {
143            int i = a.indexOf('=');
144            if (i == -1) {
145                map.put(a, null);
146            } else {
147                String key = a.substring(0, i).trim();
148                String val = a.substring(i + 1).trim();
149                if (key.endsWith(":")) {
150                    key = key.substring(0, key.length() - 1).trim();
151                }
152                map.put(key, val);
153            }
154        }
155        return map;
156    }
157
158}