piątek, 16 lipca 2010
czwartek, 15 lipca 2010
Archiwizacja logów
Ostatnio zaistniała u mnie potrzeba archiwizowania starych logów z jbossa, ponieważ ich rozmiar szybko narastał. Dodatkowo z archiwizowane starsze były potrzebne tylko do paru dni wstecz, zatem niepotrzebne stare logi powinny się same usuwać.
Pierwszym pomysłem było napisanie klasy rozszerzającej klasę DailyRollingFileAppender z org.apache.log4j. Pomysł okazał się dobry, ale nie możliwy do zrealizowania w prosty sposób, ponieważ metodę rollover(), którą chciałem przeciążyć nie miała określonego dostępu public ani protected.
W sieci można znaleźć źródła klasy DailyRollingFileAppender, kopiujemy kod i tworzymy tą klasę w swoim pakiecie. Następnie tworzymy swoją klasę rozszerzającą skopiowaną klasę, przeciążamy w niej metodę rollover i gotowe.
Dla niecierpliwych źródła: ZipFileAppender.zip
Oto rozwiązanie:
Klasa ZipFileAppender
Pierwszym pomysłem było napisanie klasy rozszerzającej klasę DailyRollingFileAppender z org.apache.log4j. Pomysł okazał się dobry, ale nie możliwy do zrealizowania w prosty sposób, ponieważ metodę rollover(), którą chciałem przeciążyć nie miała określonego dostępu public ani protected.
W sieci można znaleźć źródła klasy DailyRollingFileAppender, kopiujemy kod i tworzymy tą klasę w swoim pakiecie. Następnie tworzymy swoją klasę rozszerzającą skopiowaną klasę, przeciążamy w niej metodę rollover i gotowe.
Dla niecierpliwych źródła: ZipFileAppender.zip
Oto rozwiązanie:
Klasa ZipFileAppender
package pl.pkarpik.log4j;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* @author pkarpik
*
*/
public class ZipFileAppender extends DailyRollingFileAppender{
private String compressBackups = "false";
private String maxNumberOfBackups = "14";
@Override
void rollOver() throws IOException {
super.rollOver();
buckupsManagment();
}
public void buckupsManagment() {
final File file = new File(fileName);
int maxBackups=14;
try{
maxBackups=Integer.parseInt(getMaxNumberOfBackups());
}catch (Exception e) {
}
//zipowanie logow
File[] files = file.getParentFile().listFiles(getFileFilter(file));
for (int i = 0; i < files.length; i++) {
if (getCompressBackups().equalsIgnoreCase("YES") || getCompressBackups().equalsIgnoreCase("TRUE")) {
zipFile(files[i]);
}
}
//sortowanie logow
files = file.getParentFile().listFiles(getFileFilter(file));
Arrays.sort(files, new Comparator() {
@Override
public int compare(File o1, File o2) {
return o1.getName().compareToIgnoreCase(o2.getName());
}
});
//usuwanie plikow w przypadku przekroczenia maksymalnej liczby logow
for (int i = 0; i < files.length; i++) {
if (i < files.length - maxBackups) {
files[i].delete();
}
}
}
protected void zipFile(File file) {
if (!file.getName().endsWith(".zip")) {
try {
File zipFile = new File(file.getParent(), file.getName() + ".zip");
FileInputStream fis;
fis = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(zipFile);
ZipOutputStream zos = new ZipOutputStream(fos);
ZipEntry zipEntry = new ZipEntry(file.getName());
zos.putNextEntry(zipEntry);
byte[] buffer = new byte[4096];
while (true) {
int bytesRead = fis.read(buffer);
if (bytesRead == -1)
break;
else {
zos.write(buffer, 0, bytesRead);
}
}
zos.closeEntry();
fis.close();
zos.close();
file.delete();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
}
protected FileFilter getFileFilter(final File file){
return new FileFilter() {
@Override
public boolean accept(File pathname) {
if(pathname.isDirectory() || pathname.getName().toUpperCase().equals(file.getName().toUpperCase()))
return false;
return pathname.getName().toUpperCase().startsWith(file.getName().toUpperCase());
}
};
}
public String getCompressBackups() {
return compressBackups;
}
public void setCompressBackups(String compressBackups) {
this.compressBackups = compressBackups;
}
public String getMaxNumberOfBackups() {
return maxNumberOfBackups;
}
public void setMaxNumberOfBackups(String maxNumberOfBackups) {
this.maxNumberOfBackups = maxNumberOfBackups;
}
}
Klasa DailyRollingFileAppender - skopiowane zródła
package pl.pkarpik.log4j;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.LoggingEvent;
/**
*
*/
//Referenced classes of package org.apache.log4j:
//FileAppender, RollingCalendar, AppenderSkeleton, WriterAppender,
//Layout
/*
DECOMPILATION REPORT
Decompiled from: C:\Users\pkarpik\.m2\repository\log4j\log4j\1.2.13\log4j-1.2.13.jar
Total time: 758 ms
Jad reported messages/errors:
Exit status: 0
Caught exceptions:
*/
public class DailyRollingFileAppender extends FileAppender
{
public DailyRollingFileAppender()
{
datePattern = "'.'yyyy-MM-dd";
nextCheck = System.currentTimeMillis() - 1L;
now = new Date();
rc = new RollingCalendar();
checkPeriod = -1;
}
public DailyRollingFileAppender(Layout layout, String filename, String datePattern)
throws IOException
{
super(layout, filename, true);
this.datePattern = "'.'yyyy-MM-dd";
nextCheck = System.currentTimeMillis() - 1L;
now = new Date();
rc = new RollingCalendar();
checkPeriod = -1;
this.datePattern = datePattern;
activateOptions();
}
public void setDatePattern(String pattern)
{
datePattern = pattern;
}
public String getDatePattern()
{
return datePattern;
}
@Override
public void activateOptions()
{
super.activateOptions();
if(datePattern != null && super.fileName != null)
{
now.setTime(System.currentTimeMillis());
sdf = new SimpleDateFormat(datePattern);
int type = computeCheckPeriod();
printPeriodicity(type);
rc.setType(type);
File file = new File(super.fileName);
scheduledFilename = super.fileName + sdf.format(new Date(file.lastModified()));
} else
{
LogLog.error("Either File or DatePattern options are not set for appender [" + super.name + "].");
}
}
void printPeriodicity(int type)
{
switch(type)
{
case 0: // '\0'
LogLog.debug("Appender [" + super.name + "] to be rolled every minute.");
break;
case 1: // '\001'
LogLog.debug("Appender [" + super.name + "] to be rolled on top of every hour.");
break;
case 2: // '\002'
LogLog.debug("Appender [" + super.name + "] to be rolled at midday and midnight.");
break;
case 3: // '\003'
LogLog.debug("Appender [" + super.name + "] to be rolled at midnight.");
break;
case 4: // '\004'
LogLog.debug("Appender [" + super.name + "] to be rolled at start of week.");
break;
case 5: // '\005'
LogLog.debug("Appender [" + super.name + "] to be rolled at start of every month.");
break;
default:
LogLog.warn("Unknown periodicity for appender [" + super.name + "].");
break;
}
}
int computeCheckPeriod()
{
RollingCalendar rollingCalendar = new RollingCalendar(gmtTimeZone, Locale.ENGLISH);
Date epoch = new Date(0L);
if(datePattern != null)
{
for(int i = 0; i <= 5; i++)
{
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
simpleDateFormat.setTimeZone(gmtTimeZone);
String r0 = simpleDateFormat.format(epoch);
rollingCalendar.setType(i);
Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
String r1 = simpleDateFormat.format(next);
if(r0 != null && r1 != null && !r0.equals(r1))
return i;
}
}
return -1;
}
void rollOver()
throws IOException
{
if(datePattern == null)
{
super.errorHandler.error("Missing DatePattern option in rollOver().");
return;
}
String datedFilename = super.fileName + sdf.format(now);
if(scheduledFilename.equals(datedFilename))
return;
closeFile();
File target = new File(scheduledFilename);
if(target.exists())
target.delete();
File file = new File(super.fileName);
boolean result = file.renameTo(target);
if(result)
LogLog.debug(super.fileName + " -> " + scheduledFilename);
else
LogLog.error("Failed to rename [" + super.fileName + "] to [" + scheduledFilename + "].");
try
{
setFile(super.fileName, false, super.bufferedIO, super.bufferSize);
}
catch(IOException e)
{
super.errorHandler.error("setFile(" + super.fileName + ", false) call failed.");
}
scheduledFilename = datedFilename;
}
@Override
protected void subAppend(LoggingEvent event)
{
long n = System.currentTimeMillis();
if(n >= nextCheck)
{
now.setTime(n);
nextCheck = rc.getNextCheckMillis(now);
try
{
rollOver();
}
catch(IOException ioe)
{
LogLog.error("rollOver() failed.", ioe);
}
}
super.subAppend(event);
}
static final int TOP_OF_TROUBLE = -1;
static final int TOP_OF_MINUTE = 0;
static final int TOP_OF_HOUR = 1;
static final int HALF_DAY = 2;
static final int TOP_OF_DAY = 3;
static final int TOP_OF_WEEK = 4;
static final int TOP_OF_MONTH = 5;
private String datePattern;
private String scheduledFilename;
private long nextCheck;
Date now;
SimpleDateFormat sdf;
RollingCalendar rc;
int checkPeriod;
static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");
class RollingCalendar extends GregorianCalendar {
private static final long serialVersionUID = -3560331770601814177L;
int type = TOP_OF_TROUBLE;
RollingCalendar() {
super();
}
RollingCalendar(TimeZone tz, Locale locale) {
super(tz, locale);
}
void setType(int type) {
this.type = type;
}
public long getNextCheckMillis(Date now) {
return getNextCheckDate(now).getTime();
}
public Date getNextCheckDate(Date now) {
this.setTime(now);
switch (type) {
case TOP_OF_MINUTE:
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.MINUTE, 1);
break;
case TOP_OF_HOUR:
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.HOUR_OF_DAY, 1);
break;
case HALF_DAY:
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
int hour = get(Calendar.HOUR_OF_DAY);
if (hour < 12) {
this.set(Calendar.HOUR_OF_DAY, 12);
} else {
this.set(Calendar.HOUR_OF_DAY, 0);
this.add(Calendar.DAY_OF_MONTH, 1);
}
break;
case TOP_OF_DAY:
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.DATE, 1);
break;
case TOP_OF_WEEK:
this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek());
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.WEEK_OF_YEAR, 1);
break;
case TOP_OF_MONTH:
this.set(Calendar.DATE, 1);
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.MONTH, 1);
break;
default:
throw new IllegalStateException("Unknown periodicity type.");
}
return getTime();
}
}
}
Przykładowa konfiguracja w pliku jboss-log4j.xml
.. . . < param name="DatePattern" value="'.'yyyy-MM-dd-HH-mm" > < param name="CompressBackups" value="YES" > < param name="MaxNumberOfBackups" value="3" > . . .
poniedziałek, 25 stycznia 2010
Tapestry 4 Row Number
in java file
in html file
@Component(type = "contrib:TableView", id = "tableView")
public abstract TableView getTableWyniki();
@Component(type = "contrib:TablePages", id = "tablePages")
public abstract TablePages getTablePages();
@Component(type = "contrib:TableRows", id = "tableRows")
public abstract TableRows getTableRows();
public int getRowNo(){
return (getTablePages().getCurrentPage() - 1) *
getTableWyniki().getPageSize()
+ getTableRows().getTableIndex() + 1;
}
in html file
<table jwcid="tableView" source="ognl:users" columns="Row number, login"> <tr> <td> <span jwcid="tablePages" /> </td> </tr> <tr> <span jwcid="@contrib:TableColumns" /> </tr> <tr jwcid="tableRows" > <td > <span jwcid="@Insert" value="ognl:rowNo" /> </td> <td > <span jwcid="@Insert" value="ognl:components.tableRows.tableRow.login" /> </td> </tr> </table>
piątek, 22 stycznia 2010
Polskie imininy w kalendarzu Google
W celu dołączenia polskich imienin do swego kalendarza Google, wystarczy zaimportować do wybranego kalendarza plik z imieninami w formacie csv lub iCal (ics).
Polecam wcześniej utworzenie nowego kalendarza (np o nazwie imieniny) i zaimportowanie pliku właśnie do niego, na wypadek, gdybyśmy nie chcieli później oglądać tych imienin:)
Pobierz plik: imieniny.ics
Polecam wcześniej utworzenie nowego kalendarza (np o nazwie imieniny) i zaimportowanie pliku właśnie do niego, na wypadek, gdybyśmy nie chcieli później oglądać tych imienin:)
Pobierz plik: imieniny.ics
czwartek, 21 stycznia 2010
Tapestry 5 Demo
I found recently very interesting site with examples about Tapestry 5. Take a look.
http://lombok.demon.co.uk/tapestry5Demo/
http://lombok.demon.co.uk/tapestry5Demo/
piątek, 15 stycznia 2010
Generator i walidator numeru dowodu osobistego
Ostatnio potrzebowałem w pracy wprowadzić kilka danych testowych, ale aplikacja do wprowadzania tych danych wymagała m.in. wprowadzenia poprawnego numeru dowodu osobistego.
W dowodach osobistych cyfra kontrolna, to pierwsza cyfra w numerze dowodu (źródło), nie jak to się spodziewałem, że ostatnia.
Poniżej kod dwóch metod, do wygenerowania oraz do sprawdzenia numeru dowodu osobistego.
Poniżej kod dwóch metod, do wygenerowania oraz do sprawdzenia numeru dowodu osobistego.
Zobacz jak to działa.
String generateDO(){
String seria="", numer="";
Random random = new Random();
int suma=0;
int waga[]={7,3,1,7,3};
for(int i=0;i<3;i++){
seria+=(char) (random.nextInt('Z'-'A')+'A');
suma+=waga[i]*(seria.charAt(i)-'A'+10);
}
for(int i=0;i<5;i++){
numer+=(char)(random.nextInt('9'-'0')+'0');
suma+=waga[i]*(numer.charAt(i)-'0');
}
return seria+suma%10+numer;
}
public boolean validate(String numerDO){
int waga[]={7,3,1,0,7,3,1,7,3};
if(numerDO==null || numerDO.length()!=9)
return false;
int suma=0;
for(int i=0;i<9;i++){
if(Character.isLetter(numerDO.charAt(i)) && i<3){
suma+=waga[i]*(numerDO.charAt(i)-'A'+10);
}else if(Character.isDigit(numerDO.charAt(i)) &&i>=3){
suma+=waga[i]*(numerDO.charAt(i)-'0');
}else return false;
}
if(((suma%10)+'0')==numerDO.charAt(3))
return true;
return false;
}
czwartek, 7 stycznia 2010
Subskrybuj:
Posty (Atom)