středa 17. října 2007

Digitálně podepsané PDF

OpenOffice.org podporuje podepisování dokumentů, které jsou v jeho výchozím formátu (Open Document), ale nepodporuje digitální podpisy při exportu do PDF. Koumal jsem jak si s tím poradit a našel jsem možnost, udělat si utilitku v Javě pomocí knihovny iText. Nejlepší by asi bylo naimplementovat to přímo jako modul do OpenOffice.org, ale na to momentálně nemám čas. :-)

final KeyStore ks = KeyStore.getInstance("pkcs12");
ks.load(
  new FileInputStream(
    "exported_certificate.pfx"),
    "cert_password".toCharArray());

final String alias = (String) ks.aliases().nextElement();
final PrivateKey key = (PrivateKey) ks.getKey(alias,
  "cert_password".toCharArray());
final Certificate[] chain = ks.getCertificateChain(alias);
final PdfReader reader = new PdfReader("original.pdf");
final FileOutputStream fout = new FileOutputStream("signed.pdf");

final PdfStamper stp =
  PdfStamper.createSignature(reader, fout, '\0');
final PdfSignatureAppearance sap = stp.getSignatureAppearance();

sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
sap.setReason("I'm paranoid.");
sap.setLocation("Wien");

stp.close();

neděle 14. října 2007

AnyEdit pro Eclipse

Taky se vám často stane, že narazíte na něco, co vaše oblíbené vývojové prostředí neumí? Třeba takové tlačítko "Save all" v Eclipse... hledám, hledám a ono nikde. Ještě že existuje taková spousta plug-inů a Google. Tedy nejen kvůli zmíněnému tlačítku doporučuji vyzkoušet sadu "AnyEdit" od Andreje Loskutova. Co to umí navíc?

  • odstraňovat nadbytečné mezery v kódu (konce řádků, mezery na prázdných řádcích)
  • převádět začátky řádků na tabulátory nebo normální mezery při každém uložení
  • otevírat java soubor, který je referencován např. v XML-ku
  • atd.

A kde tento plugin roste? Najdete ho i s dalšími zajímavými pluginy na stránkách autora: http://andrei.gmxhome.de/eclipse.html chcete-li si hned nainstalovat nejnovější verzi, použijte menu Help-Software Updates-Find and install-Search for new features ... a zadejte adresu http://andrei.gmxhome.de/eclipse/

čtvrtek 11. října 2007

Rotace displeje v MIDP-1.0 (Java ME)

Nedávno jsem řešil problém jak rotovat zobrazení na displeji mobilního telefonu. U novějších mobilů s podporou MIDP-2.0 to není moc velký problém, slouží na to parametr transform metody Graphics.drawRegion(...). Může nabývat hodnot definovaných ve třídě Sprite např.

  • Sprite.TRANS_NONE
  • Sprite.TRANS_ROT90
  • Sprite.TRANS_MIRROR_ROT90
  • ...

U mobilů starších, které podporují pouze MIDP-1.0, je to složitější a vykreslování se musí provádět pixel po pixelu. Mé řešení je následovné:

//rotation of screen (270 degrees)
//assume: origImg.getWidth() == canvas.getHeigth()
// && origImg.getHeigth() == canvas.getWidth()
final Image rotatedImg =
  Image.createImage(origImg.getHeight(), origImg.getWidth());
final Graphics gr = rotatedImg.getGraphics();
for (int i = 0; i < rotatedImg.getWidth(); i++) {
  for (int j = 0; j < rotatedImg.getHeight(); j++) {
    gr.setClip(i, j, 1, 1);
    gr.drawImage(origImg, i - j, j + i - rotatedImg.getWidth(),
        Graphics.TOP | Graphics.LEFT);
  }
}

Zůstal jediný problém a tím je výkon. Na mém Siemensu CX75 trvá takováto rotace cca 15s a s tím se, vážení čtenáři, uživatelsky přítulný software dělat nedá. A řešení? MIDP-2.0.

středa 10. října 2007

java2html

Po krátkém hledání, jsem našel nástroje převod java kódu do HTML a hned jsem si funkčnost vyzkoušel na obarvení prvního příspěvku v blogu. Tady jsou:

  • java2html (.com) pracuje s celým adresářem ve kterém jsou java soubory. Hodí se pro generování klikacího kódu.
  • java2html (.de) převod jednotlivých souborů nebo částí kódu. Obsahuje i plug-in pro Eclipse, který asi využiju nejčastěji.

Výčtový typ pro starší Javu

Už několikrát jsem přemýšlel nad tím, že bych měl na stránky občas přidávat i věci týkající se mé práce, tedy hlavně javy. Ještě musím vymyslet, jak vkládat kód hezky s barvičkama, ale to přijde ;).

Včera se mě ptal jeden bývalý spolužák, jak udělat správně výčtový typ ve starší Javě. Tak jsem mu poslal následující příklad, který jsem okoukal v knize Java Efektivně.

Poté, co si kód prošel, prohlásil:

ty jo, zase jsem o neco chytrejsi
ted jsem se naucil, jak napsat vec, co jsme driv delali pomoci konstant na dva radky, tak jak ji napsat na radku 100!
uplne mam pocit, ze jsem postoupil do dalsiho levelu ;)
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
* Implementace vyctoveho typu v jave 1.4 a starsi.
* @author Josef Cacek
*/
public final class AppState implements Serializable {

  private static final long serialVersionUID = -4346433248901502211L;

  private String name;
  private static Map allStates = new HashMap();

  public static final AppState NEW = new AppState("NEW");
  public static final AppState ASSIGNED = new AppState("ASSIGNED");
  public static final AppState INPROGRESS = new AppState("INPROGRESS");
  public static final AppState CLOSED = new AppState("CLOSED");

  /**
   * vypnout default contructor
   */
  private AppState() {
    throw new IllegalStateException();
  }

  /**
   * Kontruktor, ktery potrebujem.
   * @param aName jmeno stavu
   */
  private AppState(final String aName) {
    if (aName==null) {
      throw new NullPointerException("State name can't be null.");
    }
    name = aName.toUpperCase();
    if (allStates.containsKey(name)) {
      //kdybychom se zapomneli
      //a pri copy paste nezmenili parametr konstruktoru
      throw new IllegalArgumentException("State with name '"
          + name + "' already exists.");
    }
    allStates.put(name, this);
  }

  /**
   * Vraci soucasny stav
   * @return stav jako String
   */
  public String getName() {
    return name;
  }

  /* (non-Javadoc)
   * @see java.lang.Object#toString()
   */
  public String toString() {
    return getName();
  }

  /**
   * Vraci stavovy objekt pro dane jmeno
   * @param aName jmeno stavu
   * @return stav
   */
  public static AppState valueOf(final String aName) {
    if (! isState(aName)) {
      throw new IllegalArgumentException("Wrong state name - '"
          + aName + "'.");
    }
    return (AppState) allStates.get(aName.toUpperCase());
  }

  /**
   * Vraci jmeno stavu v parametru
   * @param aState stav
   * @return jmeno stavu (nebo null, jestlize parametr je null)
   */
  public static String toString(final AppState aState) {
    return aState==null?null:aState.toString();
  }

  /**
   * Vraci true jestlize existuje stav s danym jmenem.
   * @param aName jmeno stavu
   * @return true, kdyz existuje stav s danym jmenem
   */
  public static boolean isState(final String aName) {
    return aName!=null && allStates.containsKey(aName.toUpperCase());
  }
}