/* * RHQ Management Platform * Copyright 2012, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.scripting.python; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.net.URI; import java.net.URISyntaxException; import org.python.core.Py; import org.python.core.PyObject; import org.python.core.imp; import org.rhq.scripting.ScriptSourceProvider; /** * This class translates the requests for modules in python using the import * statement into calls to RHQ's script source providers. * <p> * For a script to be downloadable using RHQ, one must add a path prefix to * <code>sys.path</code> so that RHQ is aware of the available locations it should * look into. * <p> * For example, if you have the RHQ repository script source provider available on * the classpath of the CLI, you can add the following to the <code>sys.path</code>: * <pre> * <code> * import sys * sys.path.append("__rhq__:rhq:/repositories/my_repository") * </code> * </pre> * and then you can import a module from that repository by the ordinary import statement: * <pre> * <code> * import my_module * </code> * </pre> * This will translate into a download of the script from the following location: * <code>rhq://repositories/my_repository/my_module.py</code>. * * @author Lukas Krejci */ public class PythonSourceProvider extends PyObject { private static final long serialVersionUID = 1L; private static final String RHQ_PATH_EXTENSION_PREFIX = "__rhq__:"; private ScriptSourceProvider scriptSourceProvider; private String currentPathPrefix; public PyObject __call__(PyObject args[], String keywords[]) { if (args[0].toString().startsWith(RHQ_PATH_EXTENSION_PREFIX)) { currentPathPrefix = args[0].toString().substring(RHQ_PATH_EXTENSION_PREFIX.length()); return this; } throw Py.ImportError("unable to handle"); } private static class ReaderInputStream extends InputStream { private Reader rdr; public ReaderInputStream(Reader rdr) { this.rdr = rdr; } @Override public int read() throws IOException { return rdr.read(); } } public class Loader extends PyObject { private static final long serialVersionUID = 1L; private String prefix; public Loader(String prefix) { this.prefix = prefix; } public PyObject load_module(String name) { try { URI uri = new URI(prefix + name + ".py"); Reader rdr = scriptSourceProvider.getScriptSource(uri); return imp.createFromSource(name, new ReaderInputStream(rdr), uri.toString()); } catch (URISyntaxException e) { return Py.None; } } } public PythonSourceProvider(ScriptSourceProvider scriptSourceProvider) { this.scriptSourceProvider = scriptSourceProvider; } public PyObject find_module(String name) { return find_module(name, Py.None); } public PyObject find_module(String name, PyObject path) { try { URI uri = new URI(currentPathPrefix + name + ".py"); return scriptSourceProvider.getScriptSource(uri) == null ? Py.None : new Loader(currentPathPrefix); } catch (URISyntaxException e) { return Py.None; } } @Override public String toString() { return getType().toString(); } }