How to access local files on server in JBoss application? - file-io

I am looking to access all files in a local directory in a JBoss application. I can put the directory anywhere in my war including WEB-INF if necessary. I then want to access each file in the directory sequentially. In a normal application if the directory was in the run location I could do something like:
File f = new File("myDir");
if(f.isDirectory && f.list().length != 0)
{
for(String fileName : f.list())
{
//do Read-Only stuff with fileName
}
}
I'm looking for a best-practices solution, so if I'm going about this wrong then please point me to the right way to access an unknown set of resources.

First thing to note: you're only going to get this to work if you have an exploded WAR, or possibly if the servlet container explodes the WAR for you.
With that caveat in mind, you could use ServletContext.getRealPath() as your starting point. You'd need to know the name of at least one file in the webapp's root directory, and go from there:
String knownFilePath = servletContext.getRealPath("knownFile");
File webAppRootDir = new File(knownFilePath).getParentFile();
// and then as per the question
File f = webAppRootDir ;
if(f.isDirectory && f.list().length != 0)
{
for(String fileName : f.list())
{
//do Read-Only stuff with fileName
}
}
Getting hold of ServletContext is left as an exercise for the reader.

Related

How to create a file in the resources folder in Kotlin, Gradle

In a completely fresh project, I want to create a single file myFile.json inside the src/main/resources/ folder at run time.
For reading a file, I need to do some config in the build.gradle.kts file, but I can't find anything on what to do for creating a file.
Assuming the directory src/main/resources/ exists:
val f = File("src/main/resources/myFile.json")
withContext(Dispatchers.IO) {
f.createNewFile() // This is the answer to the question
f.printWriter().use { out ->
out.println("{}")
}
}
#Endzeit has asked what have you tried so far. Please share the code.
Like #cyberbrain says - are you sure you want to write to resources folder?
Here is code that writes back to where the source resources folder is:
fun main(args: Array<String>) {
// Let's assume you want your project to be portable, so you don't
// want to use absolute file paths.
// Find out where your IDE will launch the project from. Normally this is
// the root folder of the whole project. Find out with this: the `canonicalPath` will help:
val workingFolder = File(".")
println("workingFolder=${workingFolder.canonicalPath}")
// Define the folder you want to write in to
// this will vary especially if you have a nested project structure
// IntelliJ under the Edit > Copy Path menu option will help you find the resources
// relative location
val parentFolder = File("src/main/resources")
println("parentFolder=${parentFolder.canonicalPath}")
require(parentFolder.exists())
val outFile = File(parentFolder, "test.txt")
outFile.printWriter(StandardCharsets.UTF_8).use {
it.println("Hello world")
}
println("Wrote to ${outFile.canonicalPath}")
}

How to access assets directory in a Gradle plugin

I am currently accessing the assets directory for a project as follows (where it has type Project):
SourceDirectorySet resources = it.sourceSets.main.resources
File file = resources.srcDirs.find { it.name == "assets" }
if (file != null) { ... }
Is this guaranteed to be correct? Or is there a better way (probably through android)?
In fact the code in the question doesn't work correctly. Instead I needed
it.android.sourceSets.main.assets

SSH Maverick : Looking for files on the remote machine

I am using a Maverick SSH library to connect to the remote machine. Then I am trying to find a file or a group of files in the specific directory based on the wild card : abc*.txt
I tried to use SFTPClient ls(String str) method, however it didn't work :
try{
String fileName = "/tmp/myDir/abc*.txt";
SftpFile[] files = sftp.ls(fileName);
if(files != null && files.length > 0)
retCode = true;
}
catch(Exception ex){
System.out.println("Exception : " + ex);
}
I am getting : No Such File exception.
Is there any way to find out whether the file/group of files exist on the remote machine?
Are you using this api https://www.sshtools.com/j2ssh-javadocs/com/sshtools/sftp/SftpClient.html?
As the javadoc states ls method takes a string path to a directory and not some sort of regular expression.
You can try programmatically listing each directory in your desired path and search the array of SftpFile(s) returned if that is what you need.

Where is |DataDirectory| defined?

This is a follow up question of Where is that file on my system?
Tons of questions and answers all over SO and the internet but I can't find any that gives an answer to this specific question.
All is default but I can't find the file itself,
IT'S NOT THERE.
Where/how gets |DataDirectory| defined?
Where is the file saved, does it even exist? If not, what is going on?
edit: The file isn't located at AppDomain.CurrentDomain.GetData("DataDirectory").ToString(); all (sqattered) answers tell me it should be. It must be somewhere as the debugger breaks nagging about the model unequals the table when I change the model. It's not there.
The |DataDirectory| isn't a file per se. A quote from a rather old MSDN article:
By default, the |DataDirectory| variable will be expanded as follow:
For applications placed in a directory on the user machine, this will be the app's (.exe) folder.
For apps running under ClickOnce, this will be a special data folder created by ClickOnce
For Web apps, this will be the App_Data folder
Under the hood, the value for |DataDirectory| simply comes from a property on the app domain. It is possible to change that value and override the default behavior by doing this:
AppDomain.CurrentDomain.SetData("DataDirectory", newpath)
A further quote regarding your schema inconsistencies:
One of the things to know when working with local database files is that they are treated as any other content files. For desktop projects, it means that by default, the database file will be copied to the output folder (aka bin) each time the project is built. After F5, here's what it would look like on disk
MyProject\Data.mdf
MyProject\MyApp.vb
MyProject\Bin\Debug\Data.mdf
MyProject\Bin\Debug\MyApp.exe
At design-time, MyProject\Data.mdf is used by the data tools. At run-time, the app will be using the database under the output folder. As a result of the copy, many people have the impression that the app did not save the data to the database file. In fact, this is simply because there are two copies of the data file involved. Same applies when looking at the schema/data through the database explorer. The tools are using the copy in the project, not the one in the bin folder.
The |datadirectory| algorithm is located in the System.Data.dll assembly, in the internal System.Data.Common.DbConnectionOptions class. Here it as displayed by ILSpy (note the source it's now available in the reference source repository: https://github.com/Microsoft/referencesource/blob/e458f8df6ded689323d4bd1a2a725ad32668aaec/System.Data.Entity/System/Data/EntityClient/DbConnectionOptions.cs):
internal static string ExpandDataDirectory(string keyword,
string value,
ref string datadir)
{
string text = null;
if (value != null &&
value.StartsWith("|datadirectory|", StringComparison.OrdinalIgnoreCase))
{
string text2 = datadir;
if (text2 == null)
{
// 1st step!
object data = AppDomain.CurrentDomain.GetData("DataDirectory");
text2 = (data as string);
if (data != null && text2 == null)
throw ADP.InvalidDataDirectory();
if (ADP.IsEmpty(text2))
{
// 2nd step!
text2 = AppDomain.CurrentDomain.BaseDirectory;
}
if (text2 == null)
{
text2 = "";
}
datadir = text2;
}
// 3rd step, checks and normalize
int length = "|datadirectory|".Length;
bool flag = 0 < text2.Length && text2[text2.Length - 1] == '\\';
bool flag2 = length < value.Length && value[length] == '\\';
if (!flag && !flag2)
{
text = text2 + '\\' + value.Substring(length);
}
else
{
if (flag && flag2)
{
text = text2 + value.Substring(length + 1);
}
else
{
text = text2 + value.Substring(length);
}
}
if (!ADP.GetFullPath(text).StartsWith(text2, StringComparison.Ordinal))
throw ADP.InvalidConnectionOptionValue(keyword);
}
return text;
}
So it looks in the current AppDomain data first (by default, there is no "DataDirectory" data defined I believe) and then gets to the current AppDomain base directory. The rest is mostly checks for path roots and paths normalization.
On the MSDN forum there is a similiar but simplified question about this, which says:
By default the |DataDirectory| points to your application folder (as you figured out yourself in the original question: to the App_Data).
Since is just a substitution path to your database, you can define the path yourself with the AppDomain.SetData.

When creating a T4 template, how can the app config and other file resources be utilized?

I have a T4 template that I am trying to create that will code gen lookup values from a database via Nhibernate. My problem is my data access layer uses the path of the Nhibernate configuration in order to compile the configuration upon startup (a static constructor).
I don't know how to make t4 "see" this file path so that when my code gen runs it can get this configuration file. Nor do I know how to make t4 "see" my configuration manager class; which contains the app setting that lists the path to the nhibernate xml file.
I have two configuration files, one for SQL Server and one for sqlite. The configuration file needs to be in the root directory of the executing assembly in order to nhibernate to compile the configuration.
It seems like my template won't be able to use the high level business layer to select the data from the database, rather I may have to copy all the nhibernate configuration code into the template as well (ugh).
My DB wrapper:
private class DBSingleton
{
static DBSingleton()
{
string path = ConfigurationManager.AppSettings["DBConfigFileFullPath"];
NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration().Configure(path);
cfg.AddInputStream(HbmSerializer.Default.Serialize(System.Reflection.Assembly.GetAssembly(typeof(Plan))));
instance = cfg.BuildSessionFactory();
}
internal static readonly ISessionFactory instance;
}
And my template:
<#
System.Diagnostics.Debugger.Launch();
string path = Host.ResolvePath(#"..\DB.UnitTest\App.config");
System.Configuration.ConfigurationManager.AppSettings.Add(
"DBConfigFileFullPath", path);
//System.Configuration.ConfigurationFileMap fileMap = new ConfigurationFileMap(path); //Path to your config file
//System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
ReferenceValueBL bl = new ReferenceValueBL();
List<ReferenceValue> refVals = bl.Select(); <- problem occurs here
foreach(ReferenceValue rv in refVals)
{
Write("Public ");
Write(rv.ReferenceValueCode.GetType().Name);
Write(" ");
Write(rv.ReferenceValueCode);
Write(" = ");
Write(rv.ReferenceValueCode);
}
#>
My problem occurs when the bl variable tries to call select(). That's when the DBSingleton is initialized. It throws an error saying the app setting is null. If I hard code the relative file path in the DB class to just be ./Dbconfig.xml it still throws an error because the executing assembly doesn't have that file in it's local directory.
How do other people handle getting t4 to use app/web config files without reading from the config file within the template and then injecting a connection string into the DAL? I don't have that luxury. The file has to be either placed in a readable location or t4 has to know to look somewhere.
How do other people handle getting t4 to use app/web config files without reading from the config file within the template and then injecting a connection string into the DAL?
You could perhaps convert your text template into runtime text template by setting Properties | Custom Tool to "TextTemplatingFilePreprocessor".
Afterwards the entire code generation process would be encapsulated within standard class which will have TransformText method which produces the resulting string - you can then write it into file of your liking.
Nice thing is that the template class is partial, so you can add implementation of some custom methods. Something like this perhaps:
public partial class RuntimeTextTemplate1
{
public string TransformText(string someParameter)
{
// Do something with someParameter, initialize class field
// with its value and later use this field in your t4 file.
// You also have access to ConfigurationManager.AppSettings here.
return TransformText();
}
}
Also, this:
foreach(ReferenceValue rv in refVals)
{
Write("Public ");
Write(rv.ReferenceValueCode.GetType().Name);
Write(" ");
Write(rv.ReferenceValueCode);
Write(" = ");
Write(rv.ReferenceValueCode);
}
Could be rewritten as:
foreach(ReferenceValue rv in refVals)
{
#>
Public <#= rv.ReferenceValueCode.GetType().Name #> <#= rv.ReferenceValueCode #> = <#= rv.ReferenceValueCode #>
<#+
}