What is the best way to load a .java file call the main method and execute the code. So for instance if I call C:/Test.java it should execute the code.
My code right now is the following:
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
final DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
final StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
final Iterable<<? extends JavaFileObject>compilationUnits = fileManager.getJavaFileObjectsFromStrings(Arrays.asList("C:/test.java"));
final JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits);
final boolean success = task.call();
try {
System.out.println("Compiled: " + success);
fileManager.close();
} catch (final IOException e) {
e.printStackTrace();
}
But it also generate a .class file in the folder which I don't want. Is this code good for java 14 or there is a better way?
First you can simplify the code a bit. You use the StandardJavaFileManager and it imports the interface Auto/Closeable. So you can use the try-with-resource:
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
final DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
try (final StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null)) {
final Iterable<<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromStrings(Arrays.asList("C:/test.java"));
final JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits);
final boolean success = task.call();
} catch (IOException e) {
e.printStackTrace();
}
Second you need the .class file to execute your java program. There exists a nice post. If you want to execute your test file and you use the command line, you should use the following commands:
javac Test.java
java Test
// or a little bit shorter
java Test.java
If you want to know more about compilation, I can recommend this post or this post.
By implementing JavaFileObject yourself and "patching" JavaFileManager you can keep the compiler in-memory, and then via exposing defineClass() of ClassLoader you can load the resulting byte array and launch main() via reflection.
Here is a condensed variant, it actually does what you asked for, loads source code from file (that's one line with Files.readString() anyway). However that's something what you can probably leave entirely to the patched JavaFileManager, just I focused on keeping even the source code in memory, that's why there is the commented String src = "..."; block.
import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import javax.lang.model.element.*;
import javax.tools.*;
public class SOCompileTestDense {
public static void main(String[] args) throws Exception {
String name="Test";
// String src="public class Test {\r\n" +
// " public static void main(String[] args) {\r\n" +
// " System.out.println(\"Hello \"+args[0]+\"!\");\r\n" +
// " }\r\n" +
// "}";
String src=Files.readString(Paths.get(name+".java"));
System.out.println(src);
List<JFO> sources=Arrays.asList(new JFO(name,src));
Map<String,JFO> files=new HashMap<>();
JavaCompiler jc=ToolProvider.getSystemJavaCompiler();
JavaCompiler.CompilationTask ct=jc.getTask(null, new JFM(jc.getStandardFileManager(null, null, null),files), null, null, null, sources);
System.out.println(ct.call());
Class<?> clazz=new CL().defineClass(name, files.get(name).baos.toByteArray());
clazz.getDeclaredMethod("main", String[].class).invoke(null, (Object)new String[] {"StackOverflow"});
}
static class JFO implements JavaFileObject {
final String name;
final String src;
JFO(String name,String src){
this.name=name;
this.src=src;
}
public URI toUri() {
try {
return new URI(name);
} catch(URISyntaxException use) {use.printStackTrace();};
return null;
}
public String getName() {
return name;
}
ByteArrayOutputStream baos;
public OutputStream openOutputStream() throws IOException {
baos=new ByteArrayOutputStream();
return baos;
}
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return src;
}
public Kind getKind() {
return Kind.SOURCE;
}
public boolean isNameCompatible(String simpleName, Kind kind) {
return name.equals(simpleName);
}
public InputStream openInputStream() throws IOException {return null;}
public Reader openReader(boolean ignoreEncodingErrors) throws IOException {return null;}
public Writer openWriter() throws IOException {return null;}
public long getLastModified() {return 0;}
public boolean delete() {return false;}
public NestingKind getNestingKind() {return null;}
public Modifier getAccessLevel() {return null;}
}
static class JFM implements JavaFileManager {
final JavaFileManager jfm;
final Map<String, JFO> files;
JFM(JavaFileManager jfm, Map<String, JFO> files){
this.jfm=jfm;
this.files=files;
}
public int isSupportedOption(String option) {
return jfm.isSupportedOption(option);
}
public ClassLoader getClassLoader(Location location) {
return jfm.getClassLoader(location);
}
public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
return jfm.list(location, packageName, kinds, recurse);
}
public String inferBinaryName(Location location, JavaFileObject file) {
return jfm.inferBinaryName(location, file);
}
public boolean handleOption(String current, Iterator<String> remaining) {
return jfm.handleOption(current, remaining);
}
public boolean hasLocation(Location location) {
return jfm.hasLocation(location);
}
public JavaFileObject getJavaFileForInput(Location location, String className, JavaFileObject.Kind kind) throws IOException {
return jfm.getJavaFileForInput(location, className, kind);
}
public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
JFO jfo=new JFO(className,null);
files.put(className, jfo);
return jfo;
}
public String inferModuleName(Location location) throws IOException {
return jfm.inferModuleName(location);
}
public Iterable<Set<Location>> listLocationsForModules(Location location) throws IOException {
return jfm.listLocationsForModules(location);
}
public boolean isSameFile(FileObject a, FileObject b) {return false;}
public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {return null;}
public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {return null;}
public void flush() throws IOException {}
public void close() throws IOException {}
}
static class CL extends ClassLoader {
public Class<?> defineClass(String name,byte array[]) {
return defineClass(name, array, 0, array.length);
}
}
}
And this is a tidy, short version, its output looks as follows:
public class Test {
public static void main(String[] args) {
System.out.println("Hello "+args[0]+"!");
}
}
true
Hello StackOverflow!
A much longer variant with verbose output is available on Ideone, https://ideone.com/DAXIlH, and if you download that one and remove the // in front of various System.out.println(); calls, it will display a lot more stuff, which were simply too much for Ideone.
Practically what I did was implementing all methods as throw new Error(); (see code on Ideone), and gradually filled them out with something meaningful whenever they got actually called. Actually it was pretty straigtforward, the only gotcha I ran into was a couple default methods of the JavaFileManager interface. As eclipse did not provide a stub implementation of those, it was a bit of surprise when code died without touching my throw new Error(); lines.
Related
I'm using the kubernetes-client to try copy a directory from a pod, but I'm doing something wrong with the input stream from stdout. I get a java.io.IOException: Pipe broken exception when it tries to read(). I'm pretty sure that no data flows at all. I'm half wondering if I need to read the InputStream on a separate thread or something?
The stream is created like this:
public InputStream copyFiles(String containerId,
String folderName) {
ExecWatch exec = client.pods().withName(containerId).redirectingOutput().exec("tar -C " + folderName + " -c");
// We need to wrap the InputStream so that when the stdout is closed, then the underlying ExecWatch is closed
// also. This will cleanup any Websockets connections.
ChainedCloseInputStreamWrapper inputStreamWrapper = new ChainedCloseInputStreamWrapper(exec.getOutput(), exec);
return inputStreamWrapper;
}
And the InputStream is processed in this function
void copyVideos(final String containerId) {
TarArchiveInputStream tarStream = new TarArchiveInputStream(containerClient.copyFiles(containerId, "/videos/"));
TarArchiveEntry entry;
boolean videoWasCopied = false;
try {
while ((entry = tarStream.getNextTarEntry()) != null) {
if (entry.isDirectory()) {
continue;
}
String fileExtension = entry.getName().substring(entry.getName().lastIndexOf('.'));
testInformation.setFileExtension(fileExtension);
File videoFile = new File(testInformation.getVideoFolderPath(), testInformation.getFileName());
File parent = videoFile.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
OutputStream outputStream = new FileOutputStream(videoFile);
IOUtils.copy(tarStream, outputStream);
outputStream.close();
videoWasCopied = true;
LOGGER.log(Level.INFO, "{0} Video file copied to: {1}/{2}", new Object[]{getId(),
testInformation.getVideoFolderPath(), testInformation.getFileName()});
}
} catch (IOException e) {
LOGGER.log(Level.WARNING, getId() + " Error while copying the video", e);
ga.trackException(e);
} finally {
if (!videoWasCopied) {
testInformation.setVideoRecorded(false);
}
}
}
The InputStream Wrapper class is just there to close the ExecWatch at the end once the InputStream is closed, it looks like this:
private static class ChainedCloseInputStreamWrapper extends InputStream {
private InputStream delegate;
private Closeable resourceToClose;
public ChainedCloseInputStreamWrapper(InputStream delegate, Closeable resourceToClose) {
this.delegate = delegate;
this.resourceToClose = resourceToClose;
}
#Override
public int read() throws IOException {
return delegate.read();
}
public int available() throws IOException {
return delegate.available();
}
public void close() throws IOException {
logger.info("Shutdown called!");
delegate.close();
// Close our dependent resource
resourceToClose.close();
}
public boolean equals(Object o) {
return delegate.equals(o);
}
public int hashCode() {
return delegate.hashCode();
}
public int read(byte[] array) throws IOException {
return delegate.read(array);
}
public int read(byte[] array,
int n,
int n2) throws IOException {
return delegate.read(array, n, n2);
}
public long skip(long n) throws IOException {
return delegate.skip(n);
}
public void mark(int n) {
delegate.mark(n);
}
public void reset() throws IOException {
delegate.reset();
}
public boolean markSupported() {
return delegate.markSupported();
}
public String toString() {
return delegate.toString();
}
}
Turns out I had the tar command wrong, so it was causing a failure and the stdout PipeInputStream was dead locking. I managed to find a workaround for the deadlock. But the main reason for the failure was that I forgot to tell tar to actually do something! I at least needed a "." to include the current directory.
I am compiling and loading classes in memory with JavaCompiler.
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
JavaCompiler.CompilationTask compile = compiler.getTask(null, inMemoryFileManager, diagnostics, null, annotationClasses, compilationUnits);
if (!compile.call()) {
diagnostics.getDiagnostics().forEach(System.err::println);
}
I am using a similar Filemanager and SimpleJavaObject as in this example. I modified it slightly to be able to handle multiple files. If you need my source code please let me know.
The code above runs fine as long as annotationClasses is null.
When I try to add classes to annotation processing however I get the following error:
Class names, '<classNames>', are only accepted if annotation processing is explicitly requested
For classNames I tried Main, Main.java, package.Main and package.Main.java. They all result in the same error.
I know this is a very specific scenario. Did anybody try to do something similar and can help me?
Edit:
/* Container for a Java compilation unit (ie Java source) in memory. */
private static class CompilationUnit extends SimpleJavaFileObject {
private final String source;
public CompilationUnit(String className, String source) {
super(URI.create("file:///" + className.replaceAll("\\.", "/") + ".java"), Kind.SOURCE);
this.source = source;
}
#Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return source;
}
#Override
public OutputStream openOutputStream() {
throw new IllegalStateException();
}
#Override
public InputStream openInputStream() {
return new ByteArrayInputStream(source.getBytes());
}
}
/* Container for Java byte code in memory. */
private static class ByteJavaFileObject extends SimpleJavaFileObject {
private ByteArrayOutputStream byteArrayOutputStream;
public ByteJavaFileObject(String className) {
super(URI.create("byte:///" + className.replaceAll("\\.", "/") + ".class"), Kind.CLASS);
}
#Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return null;
}
#Override
public OutputStream openOutputStream() {
byteArrayOutputStream = new ByteArrayOutputStream();
return byteArrayOutputStream;
}
#Override
public InputStream openInputStream() {
return null;
}
public byte[] getByteCode() {
return byteArrayOutputStream.toByteArray();
}
}
private static class InMemoryFileManager extends ForwardingJavaFileManager {
private final InMemoryClassLoader inMemoryClassLoader;
public InMemoryFileManager(JavaCompiler compiler, Map<String, ByteJavaFileObject> fileObjects) {
super(compiler.getStandardFileManager(null, null, null));
inMemoryClassLoader = new InMemoryClassLoader(fileObjects);
}
#Override
public JavaFileObject getJavaFileForOutput(Location notUsed, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
return inMemoryClassLoader.getFileObject(className);
}
#Override
public ClassLoader getClassLoader(Location location) {
return inMemoryClassLoader;
}
public InMemoryClassLoader getClassLoader() {
return inMemoryClassLoader;
}
}
private static class InMemoryClassLoader extends ClassLoader {
private final Map<String, ByteJavaFileObject> fileObjects;
public InMemoryClassLoader(Map<String, ByteJavaFileObject> fileObjects) {
this.fileObjects = fileObjects;
}
#Override
protected Class<?> findClass(String className) throws ClassNotFoundException {
ByteJavaFileObject fileObject = fileObjects.get(className);
return defineClass(className, fileObject.getByteCode(), 0, fileObject.getByteCode().length);
}
JavaFileObject getFileObject(String className) {
return fileObjects.get(className);
}
}
I have a problem with Zip File System Provider: If the zip file is on a remote drive (mapped or not seems to be irrelevant), the virtual file system is readonly, although the file itself is not. I wrote a minimal sample code:
public static void main(String[] args) throws IOException {
File workingDir = new File(args[0]);
File source = new File(workingDir, "in.zip");
File target = new File(workingDir, "out.zip");
Files.copy(source.toPath(), target.toPath(), StandardCopyOption.REPLACE_EXISTING);
try (FileSystem zipfs = FileSystems.newFileSystem(target.toPath(), null)) {
Path pathInZipfile = zipfs.getPath("test.xml");
System.out.println("zipfile writable: " + target.canWrite());
System.out.println("zipFS writable: " + !zipfs.isReadOnly());
Files.delete(pathInZipfile);
System.out.println("File successfully deleted");
} catch (IOException e) {
e.printStackTrace();
}
}
If workingDir is a local directory, everything works fine. However, if it is a (mapped) remote drive, i get:
zipfile writable: true
zipFS writable: false
Exception in thread "main" java.nio.file.ReadOnlyFileSystemException
at com.sun.nio.zipfs.ZipFileSystem.checkWritable(ZipFileSystem.java:155)
at com.sun.nio.zipfs.ZipFileSystem.deleteFile(ZipFileSystem.java:1335)
at com.sun.nio.zipfs.ZipPath.delete(ZipPath.java:655)
at com.sun.nio.zipfs.ZipFileSystemProvider.delete(ZipFileSystemProvider.java:206)
at java.nio.file.Files.delete(Unknown Source)
at zipfs.ZipFS.main(ZipFS.java:23)
Am I doing something wrong? Is it impossible? Is there a workaround?
I ran into the same thing and I looked at the JDK code.
Findings
In ZipFileSystem.java there are three relevant lines:
zfpath.getFileSystem().provider().checkAccess(zfpath, AccessMode.READ);
if (!Files.isWritable(zfpath))
this.readOnly = true;
zfPath is a Path object. Something in the Windows FileSystem provider blocks write access to a zip archive path. Doesn't seem like there is much to be done about that.
Workaround
What I used as a workaround was to:
Create the zip archive in a temp folder
Populate the zip archive
Copy the temp file to the original mapped drive location
As long as the mapped drive is writable in contexts outside of the zip FileSystem, this method works.
We run in exactly the same problem, and have deviced somewhat barbarian solution.
FileSystems.newFileSystem(Path) accepts Path interface, so it's possible to satisfy it wrapping real Path instance.
Here is the solution that implements required FileSysteProvider.checkAccess():
private static FileSystem createZip(Path zipPath)
throws Exception
{
var fileSystem = zipPath.getFileSystem();
var provider = fileSystem.provider();
return FileSystems.newFileSystem(
new Path()
{
private Path path(Path path)
{
return this == path ? zipPath : path;
}
#Override
public FileSystem getFileSystem()
{
return new FileSystem()
{
public Set<String> supportedFileAttributeViews()
{
return fileSystem.supportedFileAttributeViews();
}
#Override
public FileSystemProvider provider()
{
return new FileSystemProvider()
{
#Override
public void setAttribute(
Path path,
String attribute,
Object value,
LinkOption... options)
throws IOException
{
provider.setAttribute(path(path), attribute, value, options);
}
#Override
public Map<String, Object> readAttributes(
Path path,
String attributes,
LinkOption... options)
throws IOException
{
return provider.
readAttributes(path(path), attributes, options);
}
#Override
public <A extends BasicFileAttributes> A readAttributes(
Path path,
Class<A> type,
LinkOption... options)
throws IOException
{
return provider.readAttributes(path(path), type, options);
}
#Override
public FileSystem newFileSystem(URI uri, Map<String, ?> env)
throws IOException
{
return provider.newFileSystem(uri, env);
}
#Override
public DirectoryStream<Path> newDirectoryStream(
Path dir,
Filter<? super Path> filter)
throws IOException
{
return provider.newDirectoryStream(dir, filter);
}
#Override
public SeekableByteChannel newByteChannel(
Path path,
Set<? extends OpenOption> options,
FileAttribute<?>... attrs)
throws IOException
{
return provider.newByteChannel(path(path), options, attrs);
}
#Override
public void move(
Path source,
Path target,
CopyOption... options)
throws IOException
{
provider.move(path(source), path(target), options);
}
#Override
public boolean isSameFile(Path path, Path path2)
throws IOException
{
return provider.isSameFile(path(path), path(path2));
}
#Override
public boolean isHidden(Path path)
throws IOException
{
return provider.isHidden(path(path));
}
#Override
public String getScheme()
{
return provider.getScheme();
}
#Override
public Path getPath(URI uri)
{
return provider.getPath(uri);
}
#Override
public FileSystem getFileSystem(URI uri)
{
return provider.getFileSystem(uri);
}
#Override
public FileStore getFileStore(Path path)
throws IOException
{
return provider.getFileStore(path(path));
}
#Override
public <V extends FileAttributeView> V getFileAttributeView(
Path path,
Class<V> type,
LinkOption... options)
{
return provider.
getFileAttributeView(path(path), type, options);
}
#Override
public void delete(Path path)
throws IOException
{
provider.delete(path(path));
}
#Override
public void createDirectory(Path dir, FileAttribute<?>... attrs)
throws IOException
{
provider.createDirectory(path(dir), attrs);
}
#Override
public void copy(
Path source,
Path target,
CopyOption... options)
throws IOException
{
provider.copy(path(source), path(target), options);
}
#Override
public void checkAccess(Path path, AccessMode... modes)
throws IOException
{
if ((modes != null) &&
(modes.length == 1) &&
(modes[0] == AccessMode.WRITE))
{
return;
}
provider.checkAccess(path(path), modes);
}
};
}
#Override
public WatchService newWatchService()
throws IOException
{
return fileSystem.newWatchService();
}
#Override
public boolean isReadOnly()
{
return false;
}
#Override
public boolean isOpen()
{
return fileSystem.isOpen();
}
#Override
public UserPrincipalLookupService getUserPrincipalLookupService()
{
return fileSystem.getUserPrincipalLookupService();
}
#Override
public String getSeparator()
{
return fileSystem.getSeparator();
}
#Override
public Iterable<Path> getRootDirectories()
{
return fileSystem.getRootDirectories();
}
#Override
public PathMatcher getPathMatcher(String syntaxAndPattern)
{
return fileSystem.getPathMatcher(syntaxAndPattern);
}
#Override
public Path getPath(String first, String... more)
{
return fileSystem.getPath(first, more);
}
#Override
public Iterable<FileStore> getFileStores()
{
return fileSystem.getFileStores();
}
#Override
public void close() throws IOException
{
fileSystem.close();
}
};
}
#Override
public boolean isAbsolute()
{
return zipPath.isAbsolute();
}
#Override
public Path getRoot()
{
return zipPath.getRoot();
}
#Override
public Path getFileName()
{
return zipPath.getFileName();
}
#Override
public Path getParent()
{
return zipPath.getParent();
}
#Override
public int getNameCount()
{
return zipPath.getNameCount();
}
#Override
public Path getName(int index)
{
return zipPath.getName(index);
}
#Override
public Path subpath(int beginIndex, int endIndex)
{
return zipPath.subpath(beginIndex, endIndex);
}
#Override
public boolean startsWith(Path other)
{
return zipPath.startsWith(other);
}
#Override
public boolean endsWith(Path other)
{
return zipPath.endsWith(other);
}
#Override
public Path normalize()
{
return zipPath.normalize();
}
#Override
public Path resolve(Path other)
{
return zipPath.relativize(other);
}
#Override
public Path relativize(Path other)
{
return zipPath.relativize(other);
}
#Override
public URI toUri()
{
return zipPath.toUri();
}
#Override
public Path toAbsolutePath()
{
return zipPath.toAbsolutePath();
}
#Override
public Path toRealPath(LinkOption... options)
throws IOException
{
return zipPath.toRealPath(options);
}
#Override
public WatchKey register(
WatchService watcher,
Kind<?>[] events,
Modifier... modifiers)
throws IOException
{
return zipPath.register(watcher, events, modifiers);
}
#Override
public int compareTo(Path other)
{
return zipPath.compareTo(other);
}
},
Map.of("create", "true"));
}
This is more like a hack but we think it solves the bug in original ZipFileSystem
Try setting the private field readOnly in ZipFileSystem to false with reflection.
Hi I'm new in Blackberry app development i want to load HTML in browser field..
I'm able to load HTML for version 5 ,and 6 and more but it not loading in OS version 4
plz tell me how to load this HTML on Blackberry OS version4.6 i m using Eclipsed
to developing application on 5 and 6 works properly but in 4.6 not plz tell me how to write. Code for this or any specific change in code or we cant load HTML in OS version 4.6?
BrowserField mybroBrowserField=new BrowserField();
add(mybroBrowserField);
mybroBrowserField.displayContent(
"<html><body><h1>hello world! This blackbery apps</h1> </body></html>",
"http://localhost");
this code apply for 5 and more than 5 version but not work for OS version 4
You can show your html document in this way
BrowserSession session = Browser.getDefaultSession();
session.displayPage("cod://Name of your application code file/test.html");
If you are using BlackBerry Eclipse Plug-in to develop BB apps, you can import sample BlackBerry projects. In the list there is something like BlackBerry Browser Field Demo. Just import that and find out how this works. Insert this snippet to Utilities class
private static DataInputStream dataInput;
private static InputStream in;
static HttpConnection makeDummyConnection(String htmlData){
try {
in = new ByteArrayInputStream(htmlData.getBytes("UTF-8"));
dataInput = new DataInputStream(in);
} catch (Exception e) {
System.out.println("HttpConnectionImpl : Exception : " + e);
}
return new HttpConnection() {
public String getURL() {
return "";
}
public String getProtocol() {
return "";
}
public String getHost() {
return "";
}
public String getFile() {
return "";
}
public String getRef() {
return "";
}
public String getQuery() {
return "";
}
public int getPort() {
return 0;
}
public String getRequestMethod() {
return "";
}
public void setRequestMethod(String s) throws IOException {
}
public String getRequestProperty(String s) {
return "";
}
public void setRequestProperty(String s, String s1) throws IOException {
}
public int getResponseCode() throws IOException {
return 200;
}
public String getResponseMessage() throws IOException {
return "";
}
public long getExpiration() throws IOException {
return 0;
}
public long getDate() throws IOException {
return 0;
}
public long getLastModified() throws IOException {
return 0;
}
public String getHeaderField(String s) throws IOException {
return "";
}
public int getHeaderFieldInt(String s, int i) throws IOException {
return 0;
}
public long getHeaderFieldDate(String s, long l) throws IOException {
return 0;
}
public String getHeaderField(int i) throws IOException {
return "";
}
public String getHeaderFieldKey(int i) throws IOException {
return "";
}
public String getType() {
return "text/html";
}
public String getEncoding() {
return "text/html";
}
public long getLength() {
return 7000;
}
public InputStream openInputStream() throws IOException {
return in;
}
public DataInputStream openDataInputStream() throws IOException {
return dataInput;
}
public void close() throws IOException {
}
public OutputStream openOutputStream() throws IOException {
return new ByteArrayOutputStream();
}
public DataOutputStream openDataOutputStream() throws IOException {
return new DataOutputStream(new ByteArrayOutputStream());
}
};
}
and call this instead of makeConnection(String url, HttpHeaders requestHeaders, byte[] postData) method.
BrowserField exist only since BlackBerry API 5.0.0, but you can use this custom BrowserFieldRenderer class from LogicMail to solve your problem
Java Newbie question :
I need to capture the text being written to a printStream by a 3rd party component.
The PrintStream is defaulted to System.err, but can be changed to another PrintStream.
Looking through the docs, I couldn't find an easy way to direct the contents of a PrintStream to a string writer / buffer.
Can someone please assist?
PipedOutputStream pipeOut = new PipedOutputStream();
PipedInputStream pipeIn = new PipedInputStream(pipeOut);
System.setOut(new PrintStream(pipeOut));
// now read from pipeIn
import java.io.*;
public class Test {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("errors.txt");
} catch(IOException ioe) {
System.err.println("redirection not possible: "+ioe);
System.exit(-1);
}
PrintStream ps = new PrintStream(fos);
System.setErr(ps);
System.err.println("goes into file");
}
}
You can create a PrintStream around any other OutputStream.
The simplest way to create one that goes to a buffer in memory would be:
PrintStream p = new PrintStream( new ByteArrayOutputStream() )
Then you could read and reset the contents of the byte array at whatever points you like.
Another possibility would be to use pipes.
InputStream third_party_output = new PipedInputStream();
PrintStream p = new PrintStream( new PipedOutputStream( third_party_output ) );
Then you could read from the third_party_output stream to get the text written by the library.
Are you looking for something like this?
OutputStream redirect = System.err;
PrintStream myPrintStream = new PrintStream(redirect);
myPrintStream.println("hello redirect");
If you can pass myPrintStream to the 3rd party application, you can redirect it anywhere you want.
I use the following class to log System.out and System.err to a set of rotating files (where xxx-001.log is the most recent). It contains a few call to utility methods, which you will need to implement before it will compile - they should be self-explanatory.
import java.io.*;
import java.lang.reflect.*;
public class LoggerOutputStream
extends OutputStream
{
// *****************************************************************************
// INSTANCE PROPERTIES
// *****************************************************************************
private FileOutputStream log=null; // the base output stream
private String fnmBase,fnmExt; // filename base, file extension
private int fnmCount,fnmLast; // count for filename index, last filename used
private int logSize,totWritten; // max log size, current number of bytes written
// *****************************************************************************
// INSTANCE CONSTRUCTORS/INIT/CLOSE/FINALIZE
// *****************************************************************************
public LoggerOutputStream(String baseFilename) throws IOException {
this(baseFilename,".log",2,1024000);
}
public LoggerOutputStream(String baseFilename, String extension) throws IOException {
this(baseFilename,extension,2,1024000);
}
public LoggerOutputStream(String baseFilename, String extension, int numberOfFiles, int maxFileSize) throws IOException {
fnmBase=baseFilename;
if(Character.isLetterOrDigit(fnmBase.charAt(fnmBase.length()-1))) { fnmBase=(fnmBase+"-"); }
fnmExt=extension;
if(!fnmExt.startsWith(".")) { fnmExt=('.'+fnmExt); }
fnmCount=numberOfFiles;
logSize=maxFileSize;
if(fnmCount>MAXLOGS) { fnmCount=MAXLOGS; }
fnmLast=0;
for(int xa=1; xa<=MAXLOGS; xa++) {
if(!new File(constructFilename(xa)).exists()) {
while((--xa)>fnmCount) { IoUtil.deleteFile(constructFilename(xa)); }
fnmLast=xa;
break;
}
}
log=null;
openFile(false);
if(numberOfFiles>MAXLOGS) { System.out.println("** Log File Count Limited To "+MAXLOGS); }
}
public void close() throws IOException {
close(false);
}
private void openFile(boolean ovrflw) throws IOException {
close(true);
if (fnmLast< fnmCount) { fnmLast++; }
else if(fnmLast==fnmCount) { IoUtil.deleteFile(constructFilename(fnmCount)); }
for(int xa=fnmLast; xa>0; xa--) { IoUtil.renameFile(constructFilename(xa-1),constructFilename(xa)); }
log=new FileOutputStream(constructFilename(1));
totWritten=0;
}
private String constructFilename(int index) {
return constructFilename(fnmBase,index,fnmExt);
}
private synchronized void close(boolean ovrflw) throws IOException {
if(log!=null) {
log.flush();
log.close();
log=null;
}
}
// *****************************************************************************
// INSTANCE METHODS - ACCESSORS
// *****************************************************************************
public String getFilename() {
return constructFilename(1);
}
public String getFilename(int idx) {
return constructFilename(idx);
}
public synchronized void cycleLogFile() throws IOException {
openFile(true);
}
// *****************************************************************************
// INSTANCE METHODS
// *****************************************************************************
public synchronized void flush() throws IOException {
if(log!=null) {
log.flush();
}
}
public synchronized void write(int val) throws IOException {
if(log!=null) {
log.write(val);
totWritten++;
if(val=='\n') {
if(totWritten>logSize) { openFile(true); }
else { log.flush(); }
}
}
}
public synchronized void write(byte[] bytes) throws IOException {
if(log!=null) {
log.write(bytes);
totWritten+=bytes.length;
if(bytes.length>0 && bytes[bytes.length-1]=='\n') {
if(totWritten>logSize) { openFile(true); }
else { log.flush(); }
}
}
}
public synchronized void write(byte[] bytes, int str, int len) throws IOException {
if(log!=null) {
log.write(bytes,str,len);
totWritten+=len;
if(bytes.length>(str+len-1) && bytes[str+len-1]=='\n') {
if(totWritten>logSize) { openFile(true); }
else { log.flush(); }
}
}
}
// *****************************************************************************
// STATIC PROPERTIES
// *****************************************************************************
static public final int MAXLOGS=999; // maximum log files allowed
// *****************************************************************************
// STATIC METHODS
// *****************************************************************************
static public String constructFilename(String bas, int idx, String ext) {
if(!bas.endsWith("-") && !bas.endsWith("_") && !bas.endsWith(".")) { bas=(bas+"-"); }
if(!ext.startsWith(".") ) { ext=('.'+ext); }
return (bas+TextUtil.raZeros(idx,3)+ext);
}
} /* END PUBLIC CLASS */