blob: 60d4ddfdba6174860a21345c317ef161ba762dfe [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// DWB20: ThreadIO should check and reset IO if something (e.g. jetty) overrides
package org.apache.felix.gogo.runtime.threadio;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.logging.Logger;
import org.apache.felix.service.threadio.ThreadIO;
import org.osgi.annotation.bundle.Capability;
import org.osgi.namespace.service.ServiceNamespace;
@Capability(
namespace = ServiceNamespace.SERVICE_NAMESPACE,
attribute = "objectClass='org.apache.felix.service.threadio.ThreadIO'"
)
public class ThreadIOImpl implements ThreadIO
{
static private final Logger log = Logger.getLogger(ThreadIOImpl.class.getName());
final Marker defaultMarker = new Marker(System.in, System.out, System.err, null);
final ThreadPrintStream err = new ThreadPrintStream(this, System.err, true);
final ThreadPrintStream out = new ThreadPrintStream(this, System.out, false);
final ThreadInputStream in = new ThreadInputStream(this, System.in);
final ThreadLocal<Marker> current = new InheritableThreadLocal<Marker>()
{
@Override
protected Marker initialValue()
{
return defaultMarker;
}
};
public void start()
{
if (System.out instanceof ThreadPrintStream)
{
throw new IllegalStateException("Thread Print Stream already set");
}
System.setOut(out);
System.setIn(in);
System.setErr(err);
}
public void stop()
{
System.setErr(defaultMarker.err);
System.setOut(defaultMarker.out);
System.setIn(defaultMarker.in);
}
private void checkIO()
{ // derek
if (System.in != in)
{
log.fine("ThreadIO: eek! who's set System.in=" + System.in);
System.setIn(in);
}
if (System.out != out)
{
log.fine("ThreadIO: eek! who's set System.out=" + System.out);
System.setOut(out);
}
if (System.err != err)
{
log.fine("ThreadIO: eek! who's set System.err=" + System.err);
System.setErr(err);
}
}
Marker current()
{
Marker m = current.get();
if (m.deactivated)
{
while (m.deactivated)
{
m = m.previous;
}
current.set(m);
}
return m;
}
public void close()
{
checkIO(); // derek
Marker top = this.current.get();
if (top == null)
{
throw new IllegalStateException("No thread io active");
}
if (top != defaultMarker)
{
top.deactivate();
this.current.set(top.previous);
}
}
public void setStreams(InputStream in, PrintStream out, PrintStream err)
{
assert in != null;
assert out != null;
assert err != null;
checkIO(); // derek
Marker prev = current();
if (in == this.in) {
in = prev.getIn();
}
if (out == this.out) {
out = prev.getOut();
}
if (err == this.err) {
err = prev.getErr();
}
Marker marker = new Marker(in, out, err, prev);
this.current.set(marker);
}
}