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 final Map<String, ApplicationHost> apps = new HashMap<>();
049
050    public ApplicationManager() {
051    }
052
053    public synchronized void start(BundleContext context) {
054        tracker = new BundleTracker(context, Bundle.ACTIVE | Bundle.STARTING | Bundle.RESOLVED, this);
055        tracker.open();
056    }
057
058    public synchronized void stop(BundleContext context) {
059        tracker.close();
060        tracker = null;
061        apps.clear();
062    }
063
064    public synchronized ApplicationHost getOrCreateApplication(String name) {
065        ApplicationHost host = apps.get(name);
066        if (host == null) {
067            host = new ApplicationHost(name);
068            apps.put(name, host);
069        }
070        return host;
071    }
072
073    public synchronized ApplicationHost[] getApplications() {
074        return apps.values().toArray(new ApplicationHost[apps.size()]);
075    }
076
077    public synchronized ApplicationHost getApplication(String name) {
078        return apps.get(name);
079    }
080
081    public synchronized ApplicationHost getApplication(ApplicationFragment fragment) {
082        String host = fragment.getHostName();
083        return apps.get(host);
084    }
085
086    @Override
087    public Object addingBundle(Bundle bundle, BundleEvent event) {
088        String v = (String) bundle.getHeaders().get("Nuxeo-WebModule");
089        if (v != null) {
090            String classRef;
091            Map<String, String> vars = new HashMap<>();
092            String varsStr = null;
093            int i = v.indexOf(';');
094            if (i > -1) {
095                classRef = v.substring(0, i).trim();
096                varsStr = v.substring(i + 1).trim();
097            } else {
098                classRef = v.trim();
099            }
100            if (varsStr != null) {
101                vars = parseAttrs(varsStr);
102            }
103            ApplicationFragment fragment = new ApplicationFragment(bundle, classRef, vars);
104            ApplicationHost app = getOrCreateApplication(fragment.getHostName());
105            app.add(fragment);
106            app.reload();
107            return fragment;
108        }
109        return null;
110    }
111
112    @Override
113    public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
114        // TODO not yet impl.
115        if (event.getType() == BundleEvent.UPDATED) {
116            ApplicationFragment fragment = (ApplicationFragment) object;
117            if (fragment != null) {
118                ApplicationHost app = getApplication(fragment);
119                if (app != null) {
120                    app.reload();
121                }
122            }
123        }
124    }
125
126    @Override
127    public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
128        ApplicationFragment fragment = (ApplicationFragment) object;
129        if (fragment != null) {
130            ApplicationHost app = getApplication(fragment);
131            if (app != null) {
132                app.remove(fragment);
133                app.reload();
134            }
135        }
136    }
137
138    protected Map<String, String> parseAttrs(String expr) {
139        Map<String, String> map = new HashMap<>();
140        String[] ar = StringUtils.split(expr, ';', true);
141        for (String a : ar) {
142            int i = a.indexOf('=');
143            if (i == -1) {
144                map.put(a, null);
145            } else {
146                String key = a.substring(0, i).trim();
147                String val = a.substring(i + 1).trim();
148                if (key.endsWith(":")) {
149                    key = key.substring(0, key.length() - 1).trim();
150                }
151                map.put(key, val);
152            }
153        }
154        return map;
155    }
156
157}