blob: 5e4d9b08df8f15084c2e22b5b1b93f08ffa590de [file] [log] [blame]
/* Copyright 2004 The Apache Software Foundation
*
* Licensed 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.
*/
package org.apache.xmlbeans.impl.util;
import org.apache.xmlbeans.Filer;
import java.io.IOException;
import java.io.File;
import java.io.Writer;
import java.io.FileReader;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CodingErrorAction;
import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;
import org.apache.xmlbeans.impl.repackage.Repackager;
/**
* This implementation of Filer writes to disk.
*/
public class FilerImpl implements Filer
{
private File classdir;
private File srcdir;
private Repackager repackager;
private boolean verbose;
private List sourceFiles;
private boolean incrSrcGen;
private Set seenTypes;
private static final Charset CHARSET;
static
{
Charset temp = null;
try
{
temp = Charset.forName(System.getProperty("file.encoding"));
}
catch (Exception e) {}
CHARSET = temp;
}
public FilerImpl(File classdir, File srcdir, Repackager repackager, boolean verbose, boolean incrSrcGen)
{
this.classdir = classdir;
this.srcdir = srcdir;
this.repackager = repackager;
this.verbose = verbose;
this.sourceFiles = (sourceFiles != null ? sourceFiles : new ArrayList());
this.incrSrcGen = incrSrcGen;
if (this.incrSrcGen)
seenTypes = new HashSet();
}
/**
* Creates a new schema binary file (.xsb) and returns a stream for writing to it.
*
* @param typename fully qualified type name
* @return a stream to write the type to
* @throws java.io.IOException
*/
public OutputStream createBinaryFile(String typename) throws IOException
{
if (verbose)
System.err.println("created binary: " + typename);
// KHK: for now the typename will already be a relative filename for the binary
//String filename = typename.replace('.', File.separatorChar) + ".xsb";
File source = new File(classdir, typename);
source.getParentFile().mkdirs();
return new FileOutputStream( source );
}
/**
* Creates a new binding source file (.java) and returns a writer for it.
*
* @param typename fully qualified type name
* @return a stream to write the type to
* @throws java.io.IOException
*/
public Writer createSourceFile(String typename) throws IOException
{
if (incrSrcGen)
seenTypes.add(typename);
if (typename.indexOf('$') > 0)
{
typename =
typename.substring( 0, typename.lastIndexOf( '.' ) ) + "." +
typename.substring( typename.indexOf( '$' ) + 1 );
}
String filename = typename.replace('.', File.separatorChar) + ".java";
File sourcefile = new File(srcdir, filename);
sourcefile.getParentFile().mkdirs();
if (verbose)
System.err.println("created source: " + sourcefile.getAbsolutePath());
sourceFiles.add(sourcefile);
if (incrSrcGen && sourcefile.exists())
{
// Generate the file in a buffer and then compare it to the
// file already on disk
return new IncrFileWriter(sourcefile, repackager);
}
else
{
return repackager == null ?
(Writer) writerForFile( sourcefile ) :
(Writer) new RepackagingWriter( sourcefile, repackager );
}
}
public List getSourceFiles()
{
return new ArrayList(sourceFiles);
}
public Repackager getRepackager()
{
return repackager;
}
private static final Writer writerForFile(File f) throws IOException
{
if (CHARSET == null)
return new FileWriter(f);
FileOutputStream fileStream = new FileOutputStream(f);
CharsetEncoder ce = CHARSET.newEncoder();
ce.onUnmappableCharacter(CodingErrorAction.REPORT);
return new OutputStreamWriter(fileStream, ce);
}
static class IncrFileWriter extends StringWriter
{
private File _file;
private Repackager _repackager;
public IncrFileWriter(File file, Repackager repackager)
{
_file = file;
_repackager = repackager;
}
public void close() throws IOException
{
super.close();
// This is where all the real work happens
StringBuffer sb = _repackager != null ?
_repackager.repackage(getBuffer()) :
getBuffer();
String str = sb.toString();
List diffs = new ArrayList();
StringReader sReader = new StringReader(str);
FileReader fReader = new FileReader(_file);
try
{
Diff.readersAsText(sReader, "<generated>",
fReader, _file.getName(), diffs);
}
finally
{
sReader.close();
fReader.close();
}
if (diffs.size() > 0)
{
// Diffs encountered, replace the file on disk with text from
// the buffer
Writer fw = writerForFile(_file);
try
{ fw.write(str); }
finally
{ fw.close(); }
}
else
; // If no diffs, don't do anything
}
}
static class RepackagingWriter extends StringWriter
{
public RepackagingWriter ( File file, Repackager repackager )
{
_file = file;
_repackager = repackager;
}
public void close ( ) throws IOException
{
super.close();
Writer fw = writerForFile( _file );
try
{ fw.write( _repackager.repackage( getBuffer() ).toString() ); }
finally
{ fw.close(); }
}
private File _file;
private Repackager _repackager;
}
}