001/*
002 * (C) Copyright 2006-2010 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     bstefanescu
016 */
017package org.nuxeo.ecm.webengine.jaxrs;
018
019import java.util.HashMap;
020import java.util.Map;
021
022import org.apache.commons.logging.Log;
023import org.apache.commons.logging.LogFactory;
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    private static final Log log = LogFactory.getLog(ApplicationManager.class);
037
038    public final static String HOST_ATTR = "host";
039
040    public final static String DEFAULT_HOST = "default";
041
042    private final static ApplicationManager instance = new ApplicationManager();
043
044    public static ApplicationManager getInstance() {
045        return instance;
046    }
047
048    protected BundleTracker tracker;
049
050    protected Map<String, ApplicationHost> apps;
051
052    public ApplicationManager() {
053    }
054
055    public synchronized void start(BundleContext context) {
056        apps = new HashMap<String, ApplicationHost>();
057        tracker = new BundleTracker(context, Bundle.ACTIVE | Bundle.STARTING | Bundle.RESOLVED, this);
058        tracker.open();
059    }
060
061    public synchronized void stop(BundleContext context) {
062        tracker.close();
063        tracker = null;
064        apps = null;
065    }
066
067    public synchronized ApplicationHost getOrCreateApplication(String name) {
068        ApplicationHost host = apps.get(name);
069        if (host == null) {
070            host = new ApplicationHost(name);
071            apps.put(name, host);
072        }
073        return host;
074    }
075
076    public synchronized ApplicationHost getApplication(String name) {
077        return apps.get(name);
078    }
079
080    public synchronized ApplicationHost getApplication(ApplicationFragment fragment) {
081        String host = fragment.getHostName();
082        return apps.get(host);
083    }
084
085    @Override
086    public Object addingBundle(Bundle bundle, BundleEvent event) {
087        String v = (String) bundle.getHeaders().get("Nuxeo-WebModule");
088        if (v != null) {
089            String classRef = null;
090            Map<String, String> vars = new HashMap<String, String>();
091            String varsStr = null;
092            int i = v.indexOf(';');
093            if (i > -1) {
094                classRef = v.substring(0, i).trim();
095                varsStr = v.substring(i + 1).trim();
096            } else {
097                classRef = v.trim();
098            }
099            if (varsStr != null) {
100                vars = parseAttrs(varsStr);
101            }
102            ApplicationFragment fragment = new ApplicationFragment(bundle, classRef, vars);
103            ApplicationHost app = getOrCreateApplication(fragment.getHostName());
104            app.add(fragment);
105            app.reload();
106            return fragment;
107        }
108        return null;
109    }
110
111    @Override
112    public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
113        // TODO not yet impl.
114        if (event.getType() == BundleEvent.UPDATED) {
115            ApplicationFragment fragment = (ApplicationFragment) object;
116            if (fragment != null) {
117                ApplicationHost app = getApplication(fragment);
118                if (app != null) {
119                    app.reload();
120                }
121            }
122        }
123    }
124
125    @Override
126    public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
127        ApplicationFragment fragment = (ApplicationFragment) object;
128        if (fragment != null) {
129            ApplicationHost app = getApplication(fragment);
130            if (app != null) {
131                app.remove(fragment);
132                app.reload();
133            }
134        }
135    }
136
137    protected Map<String, String> parseAttrs(String expr) {
138        Map<String, String> map = new HashMap<String, String>();
139        String[] ar = StringUtils.split(expr, ';', true);
140        for (String a : ar) {
141            int i = a.indexOf('=');
142            if (i == -1) {
143                map.put(a, null);
144            } else {
145                String key = a.substring(0, i).trim();
146                String val = a.substring(i + 1).trim();
147                if (key.endsWith(":")) {
148                    key = key.substring(0, key.length() - 1).trim();
149                }
150                map.put(key, val);
151            }
152        }
153        return map;
154    }
155
156}