poniedziałek, 20 września 2010

Powiadomienia SMS o zdarzeniach w kalendarzu Google

Google użytkownikom swojego kalendarza oferuje ciekawą funkcję powiadomień SMS o zdarzeniach.

Aby skorzystać z tej funkcji należy w ustawieniach kalendarza przejść do sekcji 'Konfiguracja telefonu komórkowego' i podać swój numer a następnie poddać go weryfikacji poprzez wpisanie otrzymanego smsem kodu.

Od tego momentu edytując szczegóły zdarzenia mamy możliwość wyboru przypomnienia SMS.
Dodatkowo można dość elastycznie określić czas, w którym to przypomnienie powinno nadejść.

Funkcja bardzo przydatna dla zapominalskich oraz dla tych, którzy nie lubią terminarzy w swoich telefonach :) A w połączeniu z opcją dodawania zdarzeń powtarzalnych okresowo sprawia, że już nigdy nie zapomnisz np o imieninach ciotki, wujka...

poniedziałek, 13 września 2010

Eclipse is running in a JRE, but a JDK is required

If you have message like this
Eclipse is running in a JRE, but a JDK is required

Folow this steps.
1. Install jdk
2. Set your JDK as a default Java environment in eclipse
3. Add vm jdk path to eclipse.ini

The solution is:
1. Install jdk if you don't have it
2. In Eclipse menu Window->Preferences -> Java -> Installed JREs add your JDK location
3. Edit eclipse.ini file
     Add  line like this:
-vm
C:\Program Files\Java\jdk1.6.0_18\bin\javaw.exe

On Windows Family systems be sure that two lines are not the last one.

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

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
    @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

czwartek, 21 stycznia 2010

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.

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

NIP IBAN GUID REGON PESEL ROT13 generators

Generators

NIP
IBAN
GUID
REGON
PESEL
Converter ROT13

source: http://bogus.ovh.org/generatory/

Polskie czcionki FOP

Polskie czcionki w dokumentach PDF generowanych przez aplikacjie Java z użyciem Apache FOP

Czynności do wykonania
1. Generacja metryk
2. Ustawienie konfiguracji czcionek
3. Załadowanie konfiguracji czcionek
4. Ustawienie w szablonie wartości family-font nazwą czcionki, dla której wygenerowano metryki

Realizacja:
1. W katalogu głownym FOPa wykonujemy przykładowe polecenia, w celu wygenerowania metryk dla czcionki Arial oraz jej odmian (pogrubiona, pochylona, itp)

java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging-1.0.4.jar;lib\commons-io-1.3.1.jar;lib\xmlgraphics-commons-1.3.1.jar org.apache.fop.fonts.apps.TTFReader C:\WINDOWS\Fonts\arial.TTF arial.xml

java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging-1.0.4.jar;lib\commons-io-1.3.1.jar;lib\xmlgraphics-commons-1.3.1.jar org.apache.fop.fonts.apps.TTFReader C:\WINDOWS\Fonts\ARIALBD.TTF ARIALBD.xml

java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging-1.0.4.jar;lib\commons-io-1.3.1.jar;lib\xmlgraphics-commons-1.3.1.jar org.apache.fop.fonts.apps.TTFReader C:\WINDOWS\Fonts\ARIALBI.TTF ARIALBI.xml

java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging-1.0.4.jar;lib\commons-io-1.3.1.jar;lib\xmlgraphics-commons-1.3.1.jar org.apache.fop.fonts.apps.TTFReader C:\WINDOWS\Fonts\ARIALI.TTF ARIALI.xml

 2. Utworzenie przykładowego pliku zkonfuguracją czcnioek (fonts.xsl)
 <?xml version="1.0"?>
<fop version="1.0">
  <base>.</base>
  <source-resolution>72</source-resolution>
  <target-resolution>72</target-resolution>
  <default-page-settings height="297mm" width="210mm"/>
  <renderers>

  <renderer mime="application/pdf">
  <filterList>
  <value>flate</value>
  </filterList>
  <fonts>

  <font metrics-url="C:/Documents and Settings/pkarpik/Pulpit/fop-0.95/arial.xml" kerning="yes" embed-url="C:/WINDOWS/Fonts/arial.TTF">
  <font-triplet name="arial" style="normal" weight="normal"/>
  </font>
 
  <font metrics-url="C:/Documents and Settings/pkarpik/Pulpit/fop-0.95/ARIALBD.xml" kerning="yes" embed-url="C:/WINDOWS/Fonts/ARIALBD.TTF">
  <font-triplet name="arial" style="normal" weight="bold"/>
  </font>
 
  <font metrics-url="C:/Documents and Settings/pkarpik/Pulpit/fop-0.95/ARIALBI.xml" kerning="yes" embed-url="C:/WINDOWS/Fonts/ARIALBI.TTF">
  <font-triplet name="arial" style="italic" weight="bold"/>
  </font>
 
  <font metrics-url="C:/Documents and Settings/pkarpik/Pulpit/fop-0.95/ARIALI.xml" kerning="yes" embed-url="C:/WINDOWS/Fonts/ARIALI.TTF">
  <font-triplet name="arial" style="italic" weight="normal"/>
  </font>
 
  </fonts>
  </renderer>

  <renderer mime="application/postscript">
  </renderer>

  <renderer mime="application/vnd.hp-PCL">
  </renderer>

  <renderer mime="image/svg+xml">
  <format type="paginated"/>
  <link value="true"/>
  <strokeText value="false"/>
  </renderer>

  <renderer mime="application/awt">
  </renderer>

  <renderer mime="image/png">
  </renderer>

  <renderer mime="image/tiff">
  </renderer>

  <renderer mime="text/xml">
  </renderer>

  <renderer mime="text/plain">
  <pageSize columns="80"/>
  </renderer>
  </renderers>
</fop>


3. Załadowanie konfiguracji czcionek
FopFactory fopFactory = FopFactory.newInstance();
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
File file = new File("C:/Documents and Settings/pkarpik/workspace/Fop/src/fop/tutorial/fon.xsl");
Configuration cfg = cfgBuilder.buildFromFile(file);
fopFactory.setUserConfig(cfg);



4. Ustawienie w szablonie wartości family-font nazwą czcionki, dla której wygenerowano metryki
 <fo:block font-family="arial"></fo:block>


Źródła:
http://xmlgraphics.apache.org/fop/0.94/fonts.html 
http://blog.dosiek.pl/?p=31
http://old.nabble.com/Embed-Fonts-in-PDF-using-Java-td26112969.html