/** * $Id$ * $Date$ * */ package org.xmlsh.core; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.Collection; import java.util.Stack; import javax.xml.transform.Source; import net.sf.saxon.s9api.SaxonApiException; import net.sf.saxon.s9api.XdmValue; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.xml.sax.InputSource; import org.xmlsh.sh.shell.SerializeOpts; import org.xmlsh.sh.shell.Shell; import org.xmlsh.util.AutoReleasePool; import org.xmlsh.util.IManagedObject; public class XEnvironment { @SuppressWarnings("unused") private static Logger mLogger = LogManager.getLogger( XEnvironment.class ); private Shell mShell; private XIOEnvironment mIO = new XIOEnvironment(); private Variables mVars; private Namespaces mNamespaces = null; private AutoReleasePool mAutoRelease = null; private Stack<XIOEnvironment> mSavedIO; /* (non-Javadoc) * @see java.lang.Object#finalize() */ @Override protected void finalize() throws Throwable { close(); } public XEnvironment(Shell shell, boolean bInitIO ) throws IOException { mShell = shell; mVars = new Variables(); if( bInitIO ) mIO.initStdio(); } private void addAutoRelease( IManagedObject obj ) { if( mAutoRelease == null ) mAutoRelease = new AutoReleasePool(); mAutoRelease.add(obj); } /* * Standard Varibles */ public XVariable getVar( String name ) { return mVars.get(name); } public void setVar( XVariable var, boolean local ) { /* * Special variables */ String name = var.getName(); if( name.startsWith("xmlns:")){ declareNamespace( name.substring(6),var.getValue().toString()); } else mVars.put(name , var, local ); } public void setVar( String name , XValue value, boolean local ) throws InvalidArgumentException { XVariable var = mVars.get(name); if( var == null ) var = new XVariable( name , value ); else var = var.clone(); var.setValue(value); setVar( var , local ); } /* * Append to a variable as a sequence */ public void appendVar(String name, XValue value, boolean local ) throws InvalidArgumentException { XVariable var = mVars.get(name); if( var == null ){ // If no existing variable then dont touch setVar(new XVariable( name , value ) , local ); return ; } var = var.clone(); XdmValue xvalue = value.asXdmValue(); if( xvalue == null ) return ; var.setValue( new XValue(var.getValue().asXdmValue().append(xvalue))); setVar( var , local); } public void setVar(String name, String value , boolean local ) throws InvalidArgumentException { setVar( name , new XValue(value),local); } public XEnvironment clone() { // TODO When cloning, only export marked for export vars // Add typeset command try { return clone( mShell ); } catch (IOException e) { mShell.printErr("Exception cloning shell", e); return null; } } /* * Clone an environment for use in a new thread * * @see java.lang.Object#clone() */ public XEnvironment clone(Shell shell) throws IOException { XEnvironment that = new XEnvironment(shell, false); that.mVars = new Variables(this.mVars); that.mIO = new XIOEnvironment(this.mIO); if( this.mNamespaces != null ) that.mNamespaces = new Namespaces( this.mNamespaces ); return that; } public void close() throws CoreException { if( this.mSavedIO != null && ! mSavedIO.isEmpty()) throw new CoreException("FIXME"); mIO.release(); if( mAutoRelease != null ){ mAutoRelease.close(); mAutoRelease = null; } } public Shell getShell() { return mShell; } public Variables getVars() { return mVars ; } public Collection<String> getVarNames() { return mVars.getVarNames(); } public String getVarString( String key ) { XVariable var = getVar(key); if( var== null ) return null ; return var.getValue().toString(); } /* * Save the environment by cloning it and pushing it to this * and return the OLD environment */ public void saveIO() throws CoreException { if( mSavedIO == null ) mSavedIO = new Stack<XIOEnvironment>(); mSavedIO.push(mIO); mIO = new XIOEnvironment(mIO); } public void restoreIO() { mIO.release(); mIO = mSavedIO.pop(); } /** * @param file * @param append * @return * @throws FileNotFoundException * @throws IOException * @see org.xmlsh.sh.shell.Shell#getOutputStream(java.lang.String, boolean) */ public OutputStream getOutputStream(String file, boolean append, SerializeOpts opts ) throws FileNotFoundException, IOException { return mShell.getOutputStream(file, append, opts ); } public OutputStream getOutputStream(File file, boolean append) throws FileNotFoundException { return mShell.getOutputStream(file, append); } /** * @param s * @param e * @see org.xmlsh.sh.shell.Shell#printErr(java.lang.String, java.lang.Exception) */ public void printErr(String s, Exception e) { mShell.printErr(s, e); } /** * @param s * @see org.xmlsh.sh.shell.Shell#printErr(java.lang.String) */ public void printErr(String s) { mShell.printErr(s); } /** * @return * @see org.xmlsh.sh.shell.Shell#getCurdir() */ public File getCurdir() { return mShell.getCurdir(); } /** * @param cd * @throws IOException * @see org.xmlsh.sh.shell.Shell#setCurdir(java.io.File) */ public void setCurdir(File cd) throws IOException { mShell.setCurdir(cd); } public XValue getVarValue(String name) { XVariable var = getVar(name); if( var == null ) return null ; else return var.getValue(); } public void unsetVar(String name ) { mVars.remove( name ); } public boolean isStdinRedirected() { return mIO.isStdinRedirected() ; } /** * @return * @throws IOException * @see org.xmlsh.core.XIOEnvironment#getStderr() */ public OutputPort getStderr() throws IOException { return mIO.getStderr(); } /** * @return * @throws IOException * @see org.xmlsh.core.XIOEnvironment#getStdin() */ public InputPort getStdin() { return mIO.getStdin(); } /** * @return * @throws IOException * @see org.xmlsh.core.XIOEnvironment#getStdout() */ public OutputPort getStdout() throws IOException { return mIO.getStdout(); } public OutputPort getOutput( XValue port, boolean append ) throws IOException { if( port == null ) return getStdout(); if( port.isAtomic()){ String name = port.toString().trim(); if( name.equals("-")) return getStdout(); return mShell.getOutputPort(name, append); } else { OutputPort p = new VariableOutputPort( new XVariable(null,port) ); return p; } } public OutputPort getOutput( String port , boolean append) throws IOException { return getOutput( new XValue(port) , append ); } public OutputPort getOutput( File file , boolean append ) throws IOException { return new FileOutputPort( file , append); } /** * @param stderr * @throws IOException * @throws InvalidArgumentException * @see org.xmlsh.core.XIOEnvironment#setStderr(java.io.OutputStream) */ public void setStderr(OutputStream stderr) throws CoreException { mIO.setStderr(stderr); } public void setStderr(OutputPort stderr) throws CoreException { mIO.setStderr(stderr); } /** * @param stdin * @throws IOException * @see org.xmlsh.core.XIOEnvironment#setStdin(java.io.InputStream) */ public void setStdin(InputStream in) throws CoreException { setInput(null, in ); } public void setStdin(XVariable variable) throws CoreException { setInput( null , variable ); } public void setStdin(InputPort in ) throws CoreException { setInput( null , in ); } public InputPort setInput(String name,InputStream in) throws CoreException { return mIO.setInput( name,new StreamInputPort(in,null)); } public InputPort setInput(String name, XVariable variable) throws CoreException { return mIO.setInput( name,new VariableInputPort(variable)); } public InputPort setInput( String name , InputPort in ) throws CoreException { return mIO.setInput( name , in ); } public void setStdout(OutputStream out) throws CoreException { setOutput( null , new StreamOutputPort(out)); } public void setStdout(OutputPort port) throws CoreException { setOutput( null , port ); } public void setStdout(XVariable xvar) throws CoreException { setOutput( null , new VariableOutputPort(xvar)); } public void setOutput(String name ,OutputStream out) throws CoreException { setOutput( name,new StreamOutputPort(out)); } public void setOutput(String name ,XVariable xvar) throws CoreException { setOutput( name,new VariableOutputPort(xvar)); } public void setOutput(String name , OutputPort out) throws CoreException { mIO.setOutput( name, out ); } public void declareNamespace(String ns ) { if( mNamespaces == null ) mNamespaces = new Namespaces(); mNamespaces.declare( ns ); } public void declareNamespace(String prefix, String uri) { if( mNamespaces == null ) mNamespaces = new Namespaces(); mNamespaces.declare(prefix, uri); } public Namespaces getNamespaces() { return mNamespaces; } public InputStream getInputStream(XValue file,SerializeOpts opts) throws CoreException{ return getInput(file).asInputStream(opts); } public Source getSource(XValue value,SerializeOpts opts) throws CoreException { return getInput(value).asSource(opts); } /* * Get an input by name or value * * If port is null return stdin * If port is a string * If port is a string * if equals to "-" return stdin * if looks like "scheme://path" return a port based on an input stream from UI * if looks like "name" return a port based on an input stream by filename * if port is a node return an anonymous port based on a value * */ public InputPort getInput(XValue port) throws CoreException { if( port == null ) return getStdin(); if( port.isAtomic()){ String name = port.toString().trim(); if( name.equals("-")) return getStdin(); InputPort p; try { p = mShell.getInputPort(name); } catch (IOException e) { throw new CoreException(e); } // Port is not managed, add to autorelease addAutoRelease( p ); return p; } else { InputPort p = new VariableInputPort( new XVariable(null,port) ); // Port is not managed, add to autorelease addAutoRelease(p); return p; } } /* * Get an input port explicitly by its name */ public InputPort getInputPort(String name) { return mIO.getInputPort(name); } public InputPort getInput( String name ) throws CoreException { return getInput( new XValue(name)); } public OutputPort getOutputPort(String name){ return mIO.getOutputPort(name); } public String getAbsoluteURI(String sysid) throws URISyntaxException { URI uri = new URI(sysid); if( uri.isAbsolute()) return sysid ; URI absolute = getBaseURI().resolve(sysid ); return absolute.toString(); } public URI getBaseURI() { return getCurdir().toURI(); } public PortList<InputPort> getInputPorts() { return mIO.getInputPorts(); } public PortList<OutputPort> getOutputPorts() { return mIO.getOutputPorts(); } public OutputPort getOutputPort(String portname, boolean append) { // TODO: Add append mode to output ports return mIO.getOutputPort(portname); } public InputSource getInputSource(XValue value, SerializeOpts opts) throws CoreException, FileNotFoundException, IOException { InputPort in = getInput(value); return in.asInputSource(opts); } public void tie(Shell shell, String varname, String expr) throws InvalidArgumentException, SaxonApiException { XVariable var = mVars.get(varname); if( var == null ) throw new InvalidArgumentException("Unknown variable: " + varname); var.tie(shell,expr); } public boolean isDefined(String name) { return mVars.containsKey(name); } public Variables pushLocalVars() { Variables current = mVars ; mVars = mVars.pushLocals(); return current ; } public void popLocalVars(Variables vars) { mVars = vars ; } /** * @return the savedIO */ public XIOEnvironment getSavedIO() { return mSavedIO.peek(); } } // // //Copyright (C) 2008-2014 David A. Lee. // //The contents of this file are subject to the "Simplified BSD License" (the "License"); //you may not use this file except in compliance with the License. You may obtain a copy of the //License at http://www.opensource.org/licenses/bsd-license.php // //Software distributed under the License is distributed on an "AS IS" basis, //WITHOUT WARRANTY OF ANY KIND, either express or implied. //See the License for the specific language governing rights and limitations under the License. // //The Original Code is: all this file. // //The Initial Developer of the Original Code is David A. Lee // //Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved. // //Contributor(s): none. //