Replace string in log4j2 filename in RollingFileAppender - regex

I am trying to replace a string in a environment variable that I use in the filename as shown below. But the output file is generated literally with '%replace'. Is it possible to do such a replacement? If not, any other options? Essentially, I want to replace 'abc' with blank in the environment variable ${current.env}
<RollingFile name="FileA"
fileName="${sys:file.path}/%replace{${sys:current.env}}{'abc'}{}-xyz.log"
filePattern="${sys:file.path}/%replace{${sys:current.env}}{'abc'}{}-xyz-%d{yyyyMMdd-HHmm}.log">
<PatternLayout>
<pattern>%m%n</pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy />
<TimeBasedTriggeringPolicy />
</Policies>
<DefaultRolloverStrategy max="5" />
</RollingFile>

Here is some sample code showing how to create a custom lookup that is able to replace strings within the lookup result.
First the class that generates the logging:
package example;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class SomeClass {
private static final Logger log = LogManager.getLogger();
public static void main(String[] args){
log.info("Here's some info!");
log.error("Some error happened!");
}
}
Next the class that defines the custom lookup:
package example;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.lookup.StrLookup;
#Plugin(name = "sysWithReplace", category = "Lookup")
public class SystemLookupWithReplace implements StrLookup{
/**
* Lookup the value for the key.
* #param key the key to be looked up, may be null
* #return The value for the key.
*/
public String lookup(String key) {
if(key == null){
return null;
}
if(!key.contains(";")){
return System.getProperty(key);
}
String[] params = key.split(";");
String value = System.getProperty(params[0]);
if(params.length >= 2 && value != null){
if(params.length < 3){
return value.replace(params[1], "");
}
return value.replace(params[1], params[2]);
}
return value;
}
/**
* Lookup the value for the key using the data in the LogEvent.
* #param event The current LogEvent.
* #param key the key to be looked up, may be null
* #return The value associated with the key.
*/
public String lookup(LogEvent event, String key) {
return lookup(key);
}
}
Here is a sample log4j2.xml config file that uses the custom lookup:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %c ${sysWithReplace:os.name;dows 10;doze} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console" level="info" />
</Root>
</Loggers>
</Configuration>
and finally the logging output (I'm running this on Windows 10 so it replaces the "dows 10" with "doze":
14:30:26.580 [main] INFO example.SomeClass Windoze - Here's some info!
14:30:26.581 [main] ERROR example.SomeClass Windoze - Some error happened!

Related

Monitor HTTP NetBeans

Firstly I had a problem with the antiJARLocking attribute that was showing an error in the console:
WARNING [http-nio-8084-exec-69] org.apache.catalina.startup.SetContextPropertiesRule.begin [SetContextPropertiesRule] {Context} Setting property 'antiJARLocking' to 'true' did not find a matching property.
But I commented this part and it does not appear anymore.
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/DivulgueAqui"/>
<!-- antiJARLocking="true" -->
Then got a bug with the netbeans monitor
Showing this error:
The request can not be recorded most likely because the NetBeans HTTP Monitor module is disabled.
But in my last tests to get this error and put here for you this did not happen!
When I'm trying to run the web service it returns me code 500.
The information is arriving in the method and insert but when it arrives in the dao.insert (u);
The service stops working
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Path("usuario/inserir")
public String insertUsuario(String json){
UsuarioDao dao = new UsuarioDao();
Usuario u = new Usuario();
JSONObject jsonObject = null;
JSONParser parser = new JSONParser();
String nome;
String email;
String senha;
try {
jsonObject = (JSONObject) parser.parse(json);
nome = (String) jsonObject.get("nome");
email = (String)jsonObject.get("email");
senha = (String) jsonObject.get("senha");
u.setNome(nome);
u.setEmail(email);
u.setSenha(senha);
dao.inserir(u);
} catch (ParseException ex) {
System.out.println("WS.webService.insertUsuario()" + ex);
Logger.getLogger(webService.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
My question is. How do I solve this problem?

pass xml variable into c# method in xslt

i have xslt transform where im using c# code to save input and output xml to database.
but it saves only the values of all tags.
but i want to save vhole xml.
<msxsl:script language="CSharp" implements-prefix="ConnectDatabase">
<msxsl:assembly name = "System.Data"/>
<msxsl:using namespace = "System.Data"/>
<msxsl:using namespace = "System.Data.SqlClient"/>
<msxsl:using namespace = "System.Collections.Generic"/>
<![CDATA[
public void LogINOUT(string inputxml, string outputxml)
{
SqlCommand cmd = null;
string command = "INSERT INTO dbo.XsltLog (InputXml,OutputXml) VALUES (#inputxmlpar,#outputxmlpar)";
string connectionString ="Data Source=MyConneCtionStiring;
SqlParameter inputxmlpar = new SqlParameter("#inputxmlpar", SqlDbType.NVarChar);
inputxmlpar.Value=inputxml;
SqlParameter outputxmlpar = new SqlParameter("#outputxmlpar", SqlDbType.NVarChar);
outputxmlpar.Value =outputxml;
using (SqlConnection connection = new SqlConnection(connectionString))
{
cmd = new SqlCommand(String.Format(command), connection);
cmd.Parameters.Add(inputxmlpar);
cmd.Parameters.Add(outputxmlpar);
connection.Open();
cmd.ExecuteScalar();
}
}
]]></msxsl:script>
then a call it <xsl:copy-of select ="ConnectDatabase:LogINOUT( $inputxml,$outputxml)" />
and outputxml in database is something like this:
TO_TESTY45000.0000000020
from this string i know nothing
i wont its
<Data>
<Result>TO_TEST</Result>
<IncludeInVolume>Y</IncludeInVolume>
<FinancedAmont>
<xsl:value-of select="/Contract/ContractCalculations/Calculation/CalculationStep[#Code='FinancedAmount']"/>
</FinancedAmont>
<NumberOfInstalments>
<xsl:value-of select="format-number(/Contract/ContractCalculations/Calculation/CalculationStep[#Code='InstalmentNumber'],'#')"/>
</NumberOfInstalments>
</Data>
the same problem its with inputxml
thanks for Help Dana

XslCompiledTransform.Transform replaces """ with real quotes

Doing something like this:
using (XmlWriter myMamlHelpWriter = XmlWriter.Create(myFileStream, XmlHelpExToMamlXslTransform.OutputSettings))
{
XmlHelpExToMamlXslTransform.Transform(myMsHelpExTopicFilePath, null, myMamlHelpWriter);
}
where
private static XslCompiledTransform XmlHelpExToMamlXslTransform
{
get
{
if (fMsHelpExToMamlXslTransform == null)
{
// Create the XslCompiledTransform and load the stylesheet.
fMsHelpExToMamlXslTransform = new XslCompiledTransform();
using (Stream myStream = typeof(XmlHelpBuilder).Assembly.GetManifestResourceStream(
typeof(XmlHelpBuilder),
MamlXmlTopicConsts.cMsHelpExToMamlTransformationResourceName))
{
XmlTextReader myReader = new XmlTextReader(myStream);
fMsHelpExToMamlXslTransform.Load(myReader, null, null);
}
}
return fMsHelpExToMamlXslTransform;
}
}
And every time the string """ is replaced with real quotes in the result file.
Cannot understand why this happens...
The reason is that in the XSLT's internal representation, " is exactly the same characer as ". They both represent the ascii code point 0x34. It would seem that when the XslCompiledTransform produces its output, it uses " where it's legal to do so. I would imagine that it would still output " inside an attribute value.
Is it a problem for you that " is produced as " in the output?
I just ran the following XSLT in Visual Studio using an arbitrary input file:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/*">
<xml>
<xsl:variable name="chars">"&apos;<>&</xsl:variable>
<node a='{$chars}' b="{$chars}">
<xsl:value-of select="$chars"/>
</node>
</xml>
</xsl:template>
</xsl:stylesheet>
The output was:
<xml>
<node a=""'<>&" b=""'<>&">"'<>&</node>
</xml>
As you can see, even though all five characters were represented as entities originally, the apostrophies are produced as ' everywhere, and quotation marks are produced as " in text nodes. Furthermore, the a attribute which had ' delimiters uses " delimiters in the output. As I said, as far as the XSLT cares, a quotation mark is just a quotation mark, and an attribute is just an attribute. How those are produced in the output is up to the XSLT processor.
Edit: The root cause of this behavior appears to be the behavior of the XmlWriter class. It looks like the general suggestion for those who want more customized escaping is to extend the XmlTextWriter class. This page has an implementation that looks fairly promising:
public class KeepEntityXmlTextWriter : XmlTextWriter
{
private static readonly string[] ENTITY_SUBS = new string[] { "&apos;", """ };
private static readonly char[] REPLACE_CHARS = new char[] { '\'', '"' };
public KeepEntityXmlTextWriter(string filename) : base(filename, null) { ; }
private void WriteStringWithReplace(string text)
{
string[] textSegments = text.Split(KeepEntityXmlTextWriter.REPLACE_CHARS);
if (textSegments.Length > 1)
{
for (int pos = -1, i = 0; i < textSegments.Length; ++i)
{
base.WriteString(textSegments[i]);
pos += textSegments[i].Length + 1;
// Assertion: Replace the following if-else when the number of
// replacement characters and substitute entities has grown
// greater than 2.
Debug.Assert(2 == KeepEntityXmlTextWriter.REPLACE_CHARS.Length);
if (pos != text.Length)
{
if (text[pos] == KeepEntityXmlTextWriter.REPLACE_CHARS[0])
base.WriteRaw(KeepEntityXmlTextWriter.ENTITY_SUBS[0]);
else
base.WriteRaw(KeepEntityXmlTextWriter.ENTITY_SUBS[1]);
}
}
}
else base.WriteString(text);
}
public override void WriteString( string text)
{
this.WriteStringWithReplace(text);
}
}
On the other hand, the MSDN documentation recommends using XmlWriter.Create() rather than instantiating XmlTextWriters directly.
In the .NET Framework 2.0 release, the recommended practice is to create XmlWriter instances using the XmlWriter.Create method and the XmlWriterSettings class. This allows you to take full advantage of all the new features introduced in this release. For more information, see Creating XML Writers.
One way around that would be to use the same logic as above, but put it in a class that wraps an XmlWriter. This page has a ready-made implementation of an XmlWrappingWriter, that you can modify as needed.
To use the above code with the XmlWrappingWriter, you would subclass the wrapping writer, like this:
public class KeepEntityWrapper : XmlWrappingWriter
{
public KeepEntityWrapper(XmlWriter baseWriter)
: base(baseWriter)
{
}
private static readonly string[] ENTITY_SUBS = new string[] { "&apos;", """ };
private static readonly char[] REPLACE_CHARS = new char[] { '\'', '"' };
private void WriteStringWithReplace(string text)
{
string[] textSegments = text.Split(REPLACE_CHARS);
if (textSegments.Length > 1)
{
for (int pos = -1, i = 0; i < textSegments.Length; ++i)
{
base.WriteString(textSegments[i]);
pos += textSegments[i].Length + 1;
// Assertion: Replace the following if-else when the number of
// replacement characters and substitute entities has grown
// greater than 2.
Debug.Assert(2 == REPLACE_CHARS.Length);
if (pos != text.Length)
{
if (text[pos] == REPLACE_CHARS[0])
base.WriteRaw(ENTITY_SUBS[0]);
else
base.WriteRaw(ENTITY_SUBS[1]);
}
}
}
else base.WriteString(text);
}
public override void WriteString(string text)
{
this.WriteStringWithReplace(text);
}
}
Note this essentially the same code as the KeepEntityXmlTextWriter, but using XmlWrappingWriter as the base class and with a different constructor.
I don't recognize the Guard that the XmlWrappingWriter code is using in two places, but given that you'll be consuming the code yourself, it should be pretty safe to delete the lines like this. They just ensure that a null value isn't passed to the constructor or the (in the above case inaccessible) BaseWriter property:
Guard.ArgumentNotNull(baseWriter, "baseWriter");
To create an instance of the XmlWrappingWriter, you would create an XmlWriter however you need to, and then use:
KeepEntityWrapper wrap = new KeepEntityWrapper(writer);
And then you'd use this wrap variable as the XmlWriter you pass to your XSL transform.
The XSLT processor doesn't know whether a character was represented by a character entity or not. This is because the XML parser substitutes any character entity with its code-value.
Therefore, the XSLT processor would see exactly the same character, regardless whether it was represented as " or as " or as " or as ".
What you want can be achieved in XSLT 2.0 by using the so called "character maps".
Here is the trick you wanted:
replace all & with &
perform XSLT
replace all & with &

Implicit Getters and Setters not created for me

I started playing with the new cfproperty stuff added in ColdFusion 9, but the primary piece that I want to use doesn't seem to work now in ColdFusion 10. I created the following CFC:
component displayName="Sources" {
/**
* #getter true
* #setter true
* #type numeric
* #default 1
**/
property sourceid;
/**
* #getter true
* #setter true
* #type numeric
* #default 1
**/
property sourcegroup;
public any function init () {
This.domainRegex = '\/\/(www\.)?(([A-Za-z0-9\-_]+\.?)+)';
return this;
}
}
When I dump the meta data for the CFC I can see the properties, but no methods created for them and I can't call getSourceId() or getSourceGroup()
try this:
component accessors="true" displayName="Sources" {
property name="sourceid" type="numeric" default="1";
property name="sourcegroup" type="numeric" default="1";
public any function init () {
this.domainRegex = '\/\/(www\.)?(([A-Za-z0-9\-_]+\.?)+)';
return this;
}
}
Try removing the second star in the closing comment, the CF examples all only have one.
Alternatively, use the other syntax:
property name="sourceid" type="numeric" default="1";
I'm not a fan of annotations in comments for anything other JavaDoc, it just doesn't feel right somehow.

null values for java.util.Date input/output in web service methods

I have a webservice created with jax-ws and netbeans 7's wizard (this is my first time) .
to use java.util.Date instead of XmlGregorianCalendar, I have modified the client's webservice with this xml :
<?xml version="1.0" encoding="UTF-8"?>
<jaxws:bindings node="wsdl:definitions/wsdl:types/xsd:schema"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<jaxb:globalBindings>
<jaxb:serializable/>
<jaxb:javaType name="java.util.Date" xmlType="xsd:dateTime"/>
</jaxb:globalBindings>
</jaxws:bindings>
Date is now used instead of XmlGregorianCalendar and an Adapter1 is generated :
public class Adapter1
extends XmlAdapter<String, Date>
{
public Date unmarshal(String value) {
return new Date(value);
}
public String marshal(Date value) {
if (value == null) {
return null;
}
return value.toString();
}
}
When i add a system.out.println in the adapter i see that the Date is received/sent to the server but if i use ws's methods i get always null on Date field/parameters .
Thanks .
The XmlAdapter that is generated is not going to perform the desired conversions. The default XmlAdapter expects the following to work:
Foo foo1 = new Foo(foo2.toString());
Which is not valid in this case:
Date date1 = new Date(date2.toString());
You will need to write some conversion code and reference it from an external bindings file:
<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1">
<jxb:bindings schemaLocation="format.xsd">
<jxb:bindings node="//xs:element[#name='my-date']">
<jxb:property>
<jxb:baseType>
<jxb:javaType name="java.util.Date"
parseMethod="org.example.DateFormatter.parseInt"
printMethod="org.example.DateFormatter.printInt" />
</jxb:baseType>
</jxb:property>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
For More Information
http://blog.bdoughan.com/2011/08/xml-schema-to-java-generating.html