001/*
002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     bstefanescu
011 */
012package org.nuxeo.ecm.webengine.jaxrs;
013
014import java.io.IOException;
015import java.util.HashMap;
016import java.util.Map;
017import java.util.Set;
018
019import javax.ws.rs.core.Application;
020
021import org.osgi.framework.Bundle;
022
023/**
024 * A wrapper for a JAX-RS application fragment declared in manifest. The fragment application will be added to the
025 * target host application.
026 *
027 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
028 */
029public class ApplicationFragment extends Application {
030
031    protected final String hostName;
032
033    protected final Bundle bundle;
034
035    protected final Map<String, String> attrs;
036
037    protected String appClass;
038
039    private volatile Application app;
040
041    public static Map<String, String> createAttributes(String hostName) {
042        HashMap<String, String> attrs = new HashMap<String, String>();
043        if (hostName != null) {
044            attrs.put("host", hostName);
045        }
046        return attrs;
047    }
048
049    public ApplicationFragment(Bundle bundle, String appClass) {
050        this(bundle, appClass, (String) null);
051    }
052
053    public ApplicationFragment(Bundle bundle, String appClass, String host) {
054        this(bundle, appClass, createAttributes(host));
055    }
056
057    public ApplicationFragment(Bundle bundle, String appClass, Map<String, String> attrs) {
058        this.bundle = bundle;
059        this.appClass = appClass;
060        this.attrs = attrs;
061        String host = attrs.get("host");
062        this.hostName = host == null ? "default" : host;
063    }
064
065    protected synchronized void createApp() {
066        try {
067            Object obj = bundle.loadClass(appClass).newInstance();
068            if (obj instanceof ApplicationFactory) {
069                app = ((ApplicationFactory) obj).getApplication(bundle, attrs);
070            } else if (obj instanceof Application) {
071                app = (Application) obj;
072            } else {
073                throw new IllegalArgumentException("Expecting an Application or ApplicationFactory class: " + appClass);
074            }
075        } catch (ReflectiveOperationException | IOException e) {
076            String msg = "Cannot instantiate JAX-RS application " + appClass + " from bundle "
077                    + bundle.getSymbolicName();
078            throw new RuntimeException(msg, e);
079        }
080    }
081
082    public synchronized void reload() {
083        app = null;
084    }
085
086    public Bundle getBundle() {
087        return bundle;
088    }
089
090    public Map<String, String> getAttrs() {
091        return attrs;
092    }
093
094    public String getHostName() {
095        return hostName;
096    }
097
098    public Application get() {
099        if (app == null) {
100            createApp();
101        }
102        return app;
103    }
104
105    @Override
106    public Set<Class<?>> getClasses() {
107        return get().getClasses();
108    }
109
110    @Override
111    public Set<Object> getSingletons() {
112        return get().getSingletons();
113    }
114
115}