org.xmlvm.proc.out.OutputFile Maven / Gradle / Ivy
Show all versions of dragome-bytecode-js-compiler Show documentation
/* Copyright (c) 2002-2011 by XMLVM.org
*
* Project Info: http://www.xmlvm.org
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package org.xmlvm.proc.out;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.xmlvm.Log;
import org.xmlvm.util.FileUtil;
import org.xmlvm.util.universalfile.UniversalFile;
import org.xmlvm.util.universalfile.UniversalFileCreator;
/**
* This class represents a file and its content, read to be written out to the
* file system.
*/
public class OutputFile
{
public static final String TAG_LIB_NAME= "lib-name";
/**
* Defines a data provider that can be used to de-couple the creation of the
* OutputFile from the time the data is produced. getData() is only called
* when the data is actually needed. It is also guaranteed that the method
* is only called once inside OutputFile.
*/
public static interface DelayedDataProvider
{
public UniversalFile getData();
}
private UniversalFile data;
private DelayedDataProvider provider;
private String location= "";
private String fileName= "";
private String origin= null;
private Map tags= new HashMap();
/**
* Create an empty output file. It is required to set data later
*/
public OutputFile()
{
}
public OutputFile(DelayedDataProvider provider)
{
this.provider= provider;
}
/**
* Create a new file with the given string content.
*/
public OutputFile(String data)
{
setData(data);
}
/**
* Create a new file with the given string content.
*/
public OutputFile(byte[] data)
{
setData(data, System.currentTimeMillis());
}
/**
* Create a new file with the given string content.
*/
public OutputFile(byte[] data, long lastModified)
{
setData(data, lastModified);
}
public OutputFile(UniversalFile file)
{
this.data= file;
}
/**
* Returns the contents of this file.
*/
public UniversalFile getData()
{
maybeLoadDelayedData();
if (data == null)
{
return null;
}
return data;
}
/**
* Returns the data as a byte array.
*
* Same as getData().getFileAsBytes();
*/
public byte[] getDataAsBytes()
{
maybeLoadDelayedData();
return data.getFileAsBytes();
}
/**
* Returns the data as a string.
*
* Same as getData().getFileAsString();
*/
public String getDataAsString()
{
maybeLoadDelayedData();
return data.getFileAsString();
}
/**
* Sets the content of this file.
*/
public final void setData(String data)
{
setData(data, System.currentTimeMillis());
}
/**
* Sets the content of this file.
*/
public final void setData(String data, long lastModified)
{
if (data == null)
{
this.data= null;
}
else
{
try
{
setData(data.getBytes("UTF-8"), lastModified);
}
catch (UnsupportedEncodingException ex)
{
Log.error(ex.getMessage());
}
}
}
/**
* Sets the content of this file.
*/
public final void setData(byte[] data, long lastModified)
{
this.data= UniversalFileCreator.createFile("", data, lastModified);
}
/**
* Sets the content of this file from an Input stream
*
* @param stream
* The InputStream to use - only UTF-8 streams are supported
* @return true, if everything was successful
*/
public boolean setDataFromStream(InputStream stream, long lastModified)
{
if (stream == null)
{
return false;
}
this.data= UniversalFileCreator.createFile("", stream, lastModified);
return true;
}
/**
* Sets the content of this file from a BufferReader
*
* @param in
* The BufferReader to use as input
* @return true, if everything was successful
*/
public boolean setDataFromReader(BufferedReader in)
{
if (in == null)
{
return false;
}
StringWriter out= new StringWriter();
if (FileUtil.copyReaders(in, out))
{
setData(out.toString());
}
return false;
}
/**
* Returns the output location of this file.
*/
public String getLocation()
{
return location;
}
/**
* Sets the output location of this file.
*/
public void setLocation(String location)
{
this.location= (new File(location)).getAbsolutePath();
}
/**
* Returns the name of this file (excluding the path).
*/
public String getFileName()
{
return fileName;
}
/**
* Sets the name of this file (excluding the path).
*/
public void setFileName(String fileName)
{
this.fileName= fileName;
}
/**
* Returns the path from which this resource originated from. Returns
* null
, if no origin can be assigned.
*
* The origin is used to cache resources generated from the original
* resource.
*/
public String getOrigin()
{
return origin;
}
/**
* Sets the origin of this file. This is typically a path to the original
* file from which this resource has been generated from and is typically
* used for caching.
*/
public void setOrigin(String origin)
{
this.origin= origin;
}
/**
* Get a list of the files affected by this OutputFile class
*
* If this OutputFile only contains a file, it will return itself as the
* only array element.
*
* @return Array of affected files.
*/
public ArrayList getAffectedSourceFiles()
{
maybeLoadDelayedData();
ArrayList result= new ArrayList();
if (data == null || data.isFile())
{
result.add(this);
}
else
{
UniversalFile[] files= data.listFilesRecursively();
int dataPathLength= data.getAbsolutePath().length();
for (UniversalFile file : files)
{
String relativePath= file.getAbsolutePath().substring(dataPathLength + 1);
OutputFile outputFile= new OutputFile(file);
String path= getFullPath();
if (!relativePath.isEmpty())
{
path+= relativePath;
}
String filelocation= path.substring(0, path.length() - file.getName().length());
outputFile.setLocation(filelocation);
outputFile.setFileName(file.getName());
result.add(outputFile);
}
}
return result;
}
/**
* Get the fill pathname of the output file
*
* @return The full pathname as String
*/
public String getFullPath()
{
return location + (location.endsWith(File.separator) ? "" : File.separator) + fileName;
}
/**
* Returns the path of this file relative to the given one.
*
*
* Example:
*
* Path of this file: /foo/bar/tar/file.txt
*
* Given basePath: /foo/bar
*
* Result: tar/file.txt
*
* @param basePath
* @return
*/
public String getRelativePath(String basePath)
{
String fullPath= getFullPath();
if (!fullPath.startsWith(basePath))
{
Log.error("'" + basePath + "' is not a base path of '" + fullPath);
return null;
}
String result= fullPath.substring(basePath.length());
if (result.startsWith(File.separator))
{
result= result.substring(1);
}
return result;
}
/**
* Write the given file to disk.
*
* @return Whether file was written successfully.
*/
public boolean write()
{
if (location.isEmpty())
{
Log.warn("Cannot write OutputFile with no location: " + getFullPath());
return false;
}
maybeLoadDelayedData();
if (isEmpty())
{
Log.warn("Ignoring empty or non-existent file: " + getFullPath());
return false;
}
String pathAndName= getFullPath();
return data.saveAs(pathAndName);
}
/**
* Returns whether the contents of this file is different from the
* destination. If the destination doesn't exist, this method returns
* true
.
*/
public boolean isDifferentFromExisting()
{
UniversalFile destination= UniversalFileCreator.createFile(new File(getFullPath()));
if (!destination.exists() || !destination.isFile())
{
return true;
}
maybeLoadDelayedData();
return data.isDifferentFromExisting(getFullPath());
}
/**
* Determines if the file is empty.
*
* @return Whether the file empty or not present.
*/
public boolean isEmpty()
{
maybeLoadDelayedData();
return data == null || data.isEmpty();
}
private void maybeLoadDelayedData()
{
if (provider != null)
{
data= provider.getData();
provider= null;
}
}
/**
* Returns the time stamp when the contents of this file have been changed
* the last time.
*/
public long getLastModified()
{
return data.getLastModified();
}
/**
* Sets a new or overrides an existing tag value.
*
* @param tagName
* The name of the tag.
* @param value
* The value of the tag.
*/
public void setTag(String tagName, String value)
{
tags.put(tagName, value);
}
/**
* Returns whether the tag with the given name exists on this file.
*/
public boolean hasTag(String tagName)
{
return tags.containsKey(tagName);
}
/**
* Returns the value of the tag with the given name.
*/
public String getTag(String tagName)
{
return tags.get(tagName);
}
}