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 *     Nuxeo - initial API and implementation
011 *
012 * $Id$
013 */
014
015package org.nuxeo.runtime.model.impl;
016
017import java.io.ByteArrayInputStream;
018import java.io.IOException;
019import java.io.InputStream;
020import java.net.URL;
021import java.util.Hashtable;
022import java.util.Iterator;
023import java.util.Map;
024
025import org.apache.commons.logging.Log;
026import org.apache.commons.logging.LogFactory;
027import org.nuxeo.common.utils.FileUtils;
028import org.nuxeo.runtime.RuntimeService;
029import org.nuxeo.runtime.RuntimeServiceException;
030import org.nuxeo.runtime.api.Framework;
031import org.nuxeo.runtime.model.ComponentManager;
032import org.nuxeo.runtime.model.ComponentName;
033import org.nuxeo.runtime.model.RegistrationInfo;
034import org.nuxeo.runtime.model.RuntimeContext;
035import org.nuxeo.runtime.model.StreamRef;
036import org.nuxeo.runtime.model.URLStreamRef;
037import org.nuxeo.runtime.osgi.OSGiRuntimeActivator;
038import org.nuxeo.runtime.osgi.OSGiRuntimeContext;
039import org.osgi.framework.Bundle;
040
041/**
042 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
043 */
044public class DefaultRuntimeContext implements RuntimeContext {
045
046    private static final Log log = LogFactory.getLog(RuntimeContext.class);
047
048    private static final String UTF_8 = "UTF-8";
049
050    protected RuntimeService runtime;
051
052    protected final ComponentDescriptorReader reader;
053
054    protected final Map<String, ComponentName> deployedFiles;
055
056    public DefaultRuntimeContext() {
057        this(Framework.getRuntime());
058    }
059
060    public DefaultRuntimeContext(RuntimeService runtime) {
061        this.runtime = runtime;
062        reader = new ComponentDescriptorReader();
063        deployedFiles = new Hashtable<String, ComponentName>();
064    }
065
066    public void setRuntime(RuntimeService runtime) {
067        this.runtime = runtime;
068    }
069
070    @Override
071    public RuntimeService getRuntime() {
072        return runtime;
073    }
074
075    public Map<String, ComponentName> getDeployedFiles() {
076        return deployedFiles;
077    }
078
079    @Override
080    public URL getResource(String name) {
081        return Thread.currentThread().getContextClassLoader().getResource(name);
082    }
083
084    @Override
085    public URL getLocalResource(String name) {
086        return Thread.currentThread().getContextClassLoader().getResource(name);
087    }
088
089    @Override
090    public Class<?> loadClass(String className) throws ClassNotFoundException {
091        return Thread.currentThread().getContextClassLoader().loadClass(className);
092    }
093
094    @Override
095    public RegistrationInfo deploy(URL url) throws IOException {
096        return deploy(new URLStreamRef(url));
097    }
098
099    @Override
100    public RegistrationInfo deploy(StreamRef ref) throws IOException {
101        String name = ref.getId();
102        if (deployedFiles.containsKey(name)) {
103            return null;
104        }
105        RegistrationInfoImpl ri = createRegistrationInfo(ref);
106        if (ri == null || ri.name == null) {
107            // not parsed correctly, e.g., faces-config.xml
108            return null;
109        }
110        log.debug("Deploying component from url " + name);
111        ri.context = this;
112        ri.xmlFileUrl = ref.asURL();
113        if (ri.getBundle() != null) {
114            // this is an external component XML.
115            // should use the real owner bundle as the context.
116            Bundle bundle = OSGiRuntimeActivator.getInstance().getBundle(ri.getBundle());
117            if (bundle != null) {
118                ri.context = new OSGiRuntimeContext(bundle);
119            }
120        }
121        runtime.getComponentManager().register(ri);
122        deployedFiles.put(name, ri.getName());
123        return ri;
124    }
125
126    @Override
127    public void undeploy(URL url) {
128        ComponentName name = deployedFiles.remove(url.toString());
129        if (name == null) {
130            throw new IllegalArgumentException("not deployed " + url);
131        }
132        runtime.getComponentManager().unregister(name);
133    }
134
135    @Override
136    public void undeploy(StreamRef ref) {
137        ComponentName name = deployedFiles.remove(ref.getId());
138        if (name == null) {
139            throw new IllegalArgumentException("not deployed " + ref);
140        }
141        runtime.getComponentManager().unregister(name);
142    }
143
144    @Override
145    public boolean isDeployed(URL url) {
146        return deployedFiles.containsKey(url.toString());
147    }
148
149    @Override
150    public boolean isDeployed(StreamRef ref) {
151        return deployedFiles.containsKey(ref.getId());
152    }
153
154    @Override
155    public RegistrationInfo deploy(String location) {
156        URL url = getLocalResource(location);
157        if (url == null) {
158            throw new IllegalArgumentException("No local resources was found with this name: " + location);
159        }
160        try {
161            return deploy(url);
162        } catch (IOException e) {
163            throw new RuntimeServiceException("Cannot deploy: " + location, e);
164        }
165    }
166
167    @Override
168    public void undeploy(String location) {
169        URL url = getLocalResource(location);
170        if (url == null) {
171            throw new IllegalArgumentException("No local resources was found with this name: " + location);
172        }
173        undeploy(url);
174    }
175
176    @Override
177    public boolean isDeployed(String location) {
178        URL url = getLocalResource(location);
179        if (url != null) {
180            return isDeployed(url);
181        } else {
182            log.warn("No local resources was found with this name: " + location);
183            return false;
184        }
185    }
186
187    @Override
188    public void destroy() {
189        Iterator<ComponentName> it = deployedFiles.values().iterator();
190        ComponentManager mgr = runtime.getComponentManager();
191        while (it.hasNext()) {
192            ComponentName name = it.next();
193            it.remove();
194            mgr.unregister(name);
195        }
196    }
197
198    @Override
199    public Bundle getBundle() {
200        return null;
201    }
202
203    public RegistrationInfoImpl createRegistrationInfo(StreamRef ref) throws IOException {
204        String source = FileUtils.read(ref.getStream());
205        String expanded = Framework.expandVars(source);
206        try (InputStream in = new ByteArrayInputStream(expanded.getBytes(UTF_8))) {
207            return createRegistrationInfo(in);
208        }
209    }
210
211    public RegistrationInfoImpl createRegistrationInfo(InputStream in) throws IOException {
212        return reader.read(this, in);
213    }
214
215}