A jelenleg javított sebezhetőséget felfedező és Oracle számára jelző Adam Gowdiak (Security Explorations) a Computerworld/IDG megkeresésére megemlítette, hogy a most kiadott Java 7 update 7 se ad okot a nyugalomra, mivel átgondolták a helyzetet és találtak egy újabb lehetséges sandbox gyengeséget, amely szintén kihasználható lehet:
"Once we found that our complete Java sandbox bypass codes stopped working after the update was applied, we looked again at POC codes and started to think about the possible ways of how to fully break the latest Java update again," Gowdiak said. "A new idea came, it was verified and it turned out that this was it."
A Gowdiak azt javasolja, hogy próbáljunk meg visszatérni a Java 6 kiadásra, amely biztonsági szempontból mégis csak jobb lehet, illetve távolítsuk el a Java futtató környezetet (JRE/JDK), ha arra nincs kifejezetten szükségünk:
Based on the experience of Security Explorations researchers with hunting for Java vulnerabilities so far, Java 6 has better security than Java 7. "Java 7 was surprisingly much easier for us to break," Gowdiak said. "For Java 6, we didn't manage to achieve a full sandbox compromise, except for the issue discovered in Apple Quicktime for Java software."
Gowdiak has echoed what many security researchers have said before: If you don't need Java, uninstall it from your system.
Mivel a hibák elsősorban a sandbox mechanizmust érintik, megfelelő védelem lehet a Java plugin alapértelmezett kikapcsolása, amelyet csak a szükséges esetekben kapcsolunk vissza.
Tegnap este megjelent a hírhedt Java 7 sebezhetőség javítása: http://www.oracle.com/technetwork/topics/security/alert-cve-2012-4681-1835715.html
Kis kutakodással a források között találunk egy érdekességet a ClassFinder.java osztály módosításai között:
--- a/src/share/classes/com/sun/beans/finder/ClassFinder.java Tue May 25 15:58:33 2010 -0700 +++ b/src/share/classes/com/sun/beans/finder/ClassFinder.java Tue Jun 19 21:04:48 2012 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,8 @@ * questions. */ package com.sun.beans.finder; + +import static sun.reflect.misc.ReflectUtil.checkPackageAccess; /** * This is utility class that provides {@code static} methods @@ -54,6 +56,7 @@ public final class ClassFinder { * @see Thread#getContextClassLoader() */ public static Class<?> findClass(String name) throws ClassNotFoundException { + checkPackageAccess(name); try { ClassLoader loader = Thread.currentThread().getContextClassLoader(); if (loader == null) { @@ -94,6 +97,7 @@ public final class ClassFinder { * @see Class#forName(String,boolean,ClassLoader) */ public static Class<?> findClass(String name, ClassLoader loader) throws ClassNotFoundException { + checkPackageAccess(name); if (loader != null) { try { return Class.forName(name, false, loader);
Egyszerűen a problémát okozó metódusok elé bekerült egy checkPackageAccess hívás a ReflectUtil osztályból, amely leellenőrzi, hogy az adott osztály betölthető-e:
public static void checkPackageAccess(String name) { SecurityManager s = System.getSecurityManager(); if (s != null) { String cname = name.replace('/', '.'); if (cname.startsWith("[")) { int b = cname.lastIndexOf('[') + 2; if (b > 1 && b < cname.length()) { cname = cname.substring(b); } } int i = cname.lastIndexOf('.'); if (i != -1) { s.checkPackageAccess(cname.substring(0, i)); } } }
Amint láthatjuk, a javítás június 19-én került a forrásokba, az előző Java 7 update 6 kiadás augusztus 14-én kerül ki, felmerül a kérdés, hogy egy ismert hiba javítása miért nem került bele ez utóbbi verzióba, amikor elegendő idő jutott volna a tesztelésére és javítására...
Oracle release policy
Ahogy a Wikipedia oldalon láthatjuk, az Oracle kiadási ciklusa szerint kéthavonta kerül ki egy frissítés, amelyek felváltva biztonsági és feature kiadások:
Release | Release Date | Highlights |
---|---|---|
Java SE 7[80] | 2011-07-28 | Initial release |
Java SE 7 Update 1[81] | 2011-10-18 | 20 security fixes, other bug fixes |
Java SE 7 Update 2[82] | 2011-12-12 | No security fixes; reliability and performance improvements; support for Solaris 11 and Firefox 5 and later; JavaFX included with Java SE JDK, improvements for web-deployed applications |
Java SE 7 Update 3[83] | 2012-02-14 | 14 security fixes[84] |
Java SE 7 Update 4[85] | 2012-04-26 | No security updates; JDK Support for Mac OS X; New JVM (Java HotSpot Virtual Machine, version 23) |
Java SE 7 Update 5[86] | 2012-06-12 | 14 security fixes[87] |
Java SE 7 Update 6[88] | 2012-08-14 | JavaFX and Java Access Bridge included in Java SE JDK and JRE installation, JDK and JRE Support for Mac OS X, JDK for Linux on ARM[89] |
Java SE 7 Update 7[90] | 2012-08-30 | Fixes security issues[60] |
Mivel a probléma biztonsági javítás és a júniusi csomagba már nem fért bele, ezért csak az októberi csomagba kerülhetett volna bele, s nem adták ki az augusztusi csomagban, de a súlyossága okán kiadásra került egy rendkívüli csomag.
A Red Hat idén bevásárlós kedvében van, az ESB és MQ megoldásokban utazó FuseSource megvétele után két hónappal egy BPM céget is magáévá tett, ahogy ezt a Polymita weboldalán jelenleg olvashatjuk:
A felvásárlás nagyjából megerősíti, hogy a Red Hat minden bizonnyal felhagy a jelenlegi JBossESB (SOA-P) platformjának további fejlesztgetésével, mivel ezen termékben a mediation flow alapját a jBPM adta, illetve a JBossESB/SOA-P tartalmazott egy Seam és jBPM alapú megoldást is.
A Polymita egyike azon BPM megoldásoknak, amely – ha nem is a jobb felső négyzetben, de szerepel a Gartner Magic Quadrant elemzésében, bár a vezető megoldásoktól még távol van (Pegasystems és Lombardi):
A Red Hat nem is titkolja, hogy a felvásárlás célja a BPM területen való megkapaszkodás, bár a vezető pozícióra való törekvés egyelőre erős kijelentésnek tűnik:
The acquired Polymita technology brings complementary BPM capabilities that are designed to improve the productivity of business users. The combination of JBoss Enterprise BRMS with Polymita technology helps position Red Hat as a leading vendor in the BPM marketplace.
Mit is tud a Polymita?
A napokban a blog.fireeye.com oldalon sikerült egy Java 7 sebezhetőséget találni, amelyet kihasználva egy Java applet képes kitörni a sandbox környezetéből. A hiba legvégén a Java 7 platformban megjelent ClassFinder osztály resolveClass metódusát találjuk, amely a sandbox előírásokat megkerülve képes betölteni bármilyen osztályt:
public static Class<?> resolveClass(String name, ClassLoader loader) throws ClassNotFoundException { Class<?> type = PrimitiveTypeMap.getType(name); return (type == null) ? findClass(name, loader) : type; }
A meghívott findClass metódus pedig megkeresi és visszaadja az adott osztályt:
public static Class<?> findClass(String name) throws ClassNotFoundException { try { ClassLoader loader = Thread.currentThread().getContextClassLoader(); if (loader == null) { // can be null in IE (see 6204697) loader = ClassLoader.getSystemClassLoader(); } if (loader != null) { return Class.forName(name, false, loader); } } catch (ClassNotFoundException exception) { // use current class loader instead } catch (SecurityException exception) { // use current class loader instead } return Class.forName(name); }
Mivel az átadott ClassLoader példány értéke lehet null, ezért ebben az esetben lekérdezésre kerül a SystemClassLoader, amely vissza fogja adni a kért osztályt. A hiba kihasználásában sokat nem számít, de az itt látható kód igen "szép":
- a catch ágakban el van nyelve a kapott ClassNotFoundException vagy SecurityException kivétel
- majd ezen hibák esetén a metódus végén a Class.forName meghívásra kerül
Ezt a ClassFinder osztályt nem tudja egy sandbox-ban futó applet meghívni, mivel a com.sun.beans.finder csomagban van, amelyet nem lehet elérni a sandbox környezetből, ám az Java 1.4 verzióban megjelenő java.beans.Expression osztályon keresztül igen:
new Expression(Class.class, "forName", new Object[] {"sun.awt.SunToolkit"}).invoke();
Az Expression.java osztály forrásában azt láthatjuk, hogy meghívja az ősosztályának a konstruktorát:
@ConstructorProperties({"target", "methodName", "arguments"}) public Expression(Object target, String methodName, Object[] arguments) { super(target, methodName, arguments); }
A Statement.java osztályban láthatjuk az AccessController ellenőrzése alatti invoke hívást:
try { return AccessController.doPrivileged( new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { return invokeInternal(); } }, acc ); } catch (PrivilegedActionException exception) { throw exception.getException(); }
Amely tartalmaz egy szép külön ágat arra az esetre, ha a Class.forName() kerülne meghívásra:
// Class.forName() won't load classes outside // of core from a class inside core. Special // case this method. if (target == Class.class && methodName.equals("forName")) { return ClassFinder.resolveClass((String)arguments[0], this.loader); }
Így viszont visszaadódik a kért osztály, mindenféle ellenőrzés nélkül, mert a ClassFinder bizony nem fog dobni PrivilegedActionException kivételt... ettől a ponttól már "triviális" a sandbox környezetből való kitörés, mivel a SunToolkit és a hozzá hasonló a belső használatú osztályok elvileg nem lennének betölthetőek a sandbox környezetben...
A Statement.java osztályban is van egy nagyon szép programozástechnikai hiba, amely közel két éve jelent meg a kódbázisban, és azóta is benne fekszik:
--- a/src/share/classes/java/beans/Statement.java Thu Jan 29 15:34:50 2009 +0300 +++ b/src/share/classes/java/beans/Statement.java Fri Jul 03 16:56:29 2009 +0400 @@ -66,6 +66,7 @@ public class Statement { Object target; String methodName; Object[] arguments; + ClassLoader loader; /** * Creates a new <code>Statement</code> object with a <code>target</code>, @@ -157,7 +158,7 @@ public class Statement { // of core from a class inside core. Special // case this method. if (target == Class.class && methodName.equals("forName")) { - return ClassFinder.resolveClass((String)arguments[0]); + return ClassFinder.resolveClass((String)arguments[0], this.loader); } Class[] argClasses = new Class[arguments.length]; for(int i = 0; i < arguments.length; i++) {
Noha a hibával nincs kapcsolatban, de belekerült a kódbázisba egy loader nevű példányváltozó, amelyet átadnak paraméterként a resolveClass metódus hívásánál, de sehol nem kap értéket. Elképesztő! Bármelyik statikus kódanalizáló program hangosan ugat egy ilyen hibára, amely két éve a Java egyik fontos osztályában fekszik...
Veszélyes?
A külföldi és hazai IT portálok igen kényes sebezhetőségként írták le ezt a problémát, de valószínűleg nagyobb a füstje, mint a lángja... szakmailag ugyanis nagyon érdekes egy ilyen hibát megtalálni, felfedni és a sebezhetőség okát kideríteni.. de a hitelesen aláírt Java appletek képesek a sandbox környezeten kívül is futni, és akik vissza szeretnének élni a helyzettel, azoknak nem okozhat nehézséget egy hamis, de érvényes és hiteles aláírás megszerzése... nem hiteles aláírással pedig csak egy felhasználói jóváhagyás kell, a felhasználó pedig jóvá fogja hagyni az applet futását...
...ennek ellenére tartsuk szárazon a puskaport és járjuk nyitott szemmel, de nem feltétlen szükséges a JRE/JDK eltávolítása a gépekről, ahogy azt több helyen is olvashatjuk, a helyzet kezelését rábízhatjuk a víruskereső szoftverekre, amelyeknek illene blokkolnia egy ilyen támadást, illetve legalább egy – akár false positive – figyelmeztetést küldeni a felhasználó felé, ha egy aláírás nélküli applet szeretne elindulni és benne van egy Expression hívás. A legbiztosabb megoldás az, ha letiltjuk a Java plugin futását a böngészőben és csak akkor engedélyezzük, ha arra kifejezetten szükségünk van.
Update
Van rá esély, hogy az OpenJDK 6 is érintett a sebezhetőségben, mivel ezen Java környezet forrásban úgy tűnik, hogy a fenti kódrészletek backportolásra kerültek, ugyanis mind az Oracle oldaláról letölthető OpenJDK 6 update 25 forrása, mind az online források között megtalálható a ClassFinder osztály, amely elvileg a Java 1.7 óta létezik:
(forrás: https://blogs.oracle.com/darcy/entry/openjdk_6_genealogy)
Javítócsomag
Megérkezett a patch a hibával kapcsolatban: http://www.oracle.com/technetwork/topics/security/alert-cve-2012-4681-1835715.html
A Liferay magyarországi képviselete szeptembertől elindítja a közösségi alkalmazásfejlesztési programjukat, ahol az önjelölt fejlesztőknek a Liferay dolgozók segítenek a portálhoz való plugin-ok fejlesztésében. A lehetőség főleg azoknak lehet hasznos, akik biztos Java tudással rendelkeznek, nagyjából ismerik a Liferay portálrendszert, ám nincs mély tapasztalatuk portletek (illetve Liferay plugin-ok) létrehozásában. A cég képviselője szerint egy-egy "projekt 1-2 hónapig tartana, hetente lennének meetingek – online is, ha úgy kényelmesebb – ahol az eddig elérteket és a fejlesztés közben felmerült kérdéseket vitathatnánk meg. Időközben a közösségi fórumot és az IRC csatornát lehetne használni erre a célra. Természetesen több projekt futhatna egy időben."
Bővebb információ a közösségi fórumban: http://www.liferay.com/community/forums/-/message_boards/message/15002191
Marketplace ismertető: http://ivsz.hu/hu/hirek-es-esemenyek/hirek/tagjaink-hirei/2012/08/liferay-maekwtplace-nagyv120808
...egy öt perces videóban: http://vimeo.com/fusesource/review/47076337/76f8a99fbc
A legújabb FuseESB kiadás: http://fusesource.com/products/fuse-esb-enterprise/
Egy hónapja került ki egy levél a java7u-dev listára, amely szerint változni fog a hash képzés algoritmusa a Java7u6 kiadással. Az új módszer a hash alapú tárolókat érinti, azokat is String típusú kulcsok esetén, mint például a HashMap, a Hashtable, a WeakHashMap, a LinkedHashMap, a ConcurrentHashMap, továbbá a Set implementációkat, mint a HashSet vagy a LinkedHashSet, illetve a járulékos osztályokat, mint a Properties.
Fontos tudni, hogy az alternatív hash algoritmus 512 elemszám felett lép működésbe (kivéve a ConcurrentHashMap, ahol csak ez az új algoritmus lesz), mivel a hash ütközések minimalizálása a cél és 512 elemszám alatt nem jellemző a hash ütközés. Alapvetően a hash algoritmus változása nem kellene befolyásolja egy szoftver működését, mivel ismert módon se a Map, se a Set, se a Properties nem garantálja sorrendet az iterációknál, ám a belső működés szerint a kulcsok alapján létrehozott hash értéke alapján került bejárásra a Map, így a sorrend valamilyen szinten garantált volt: és mivel garantált, így több helyen ki is használták ezt a programfejlesztők (nézzük át a saját fejlesztéseinket, hogy alapozunk-e sorrendiségre).
A lényeg: a Java7u6 kiadás megjelenésével figyeljük a potenciális hibákat, amelyek a fenti okokból következhetnek, ha megjelenik valami furcsaság, akkor a jdk.map.althashing.threshold átállításával még paraméterezni tudjuk az alternatív hash algoritmus küszöbét, ám Java8 esetén előfordulhat, hogy nem lesz kikapcsolható, mivel küszöbérték függetlenül az új algoritmust fogja használni.
Két hete írtam, hogy a Java EE 6 Cookbook viszonylag olcsón megszerezhető, a héten találtam egy igazi aranybányát: az Oracle Technology Network Member Discounts oldalát, ahol az ingyenes háttérképeken és megvásárolható Oracle szoftverekre adott engedményeken kívül különféle könyveket tudunk olcsóbban megvásárolni, mint OTN tagok (amelynek tagja, aki már töltött le bármilyen Sun és/vagy Oracle szoftvert).
A legtöbb könyv természetesen az Oracle adatbázis tevékenységével kapcsolatos, még nem sikerült átállniuk arra a pályára, hogy a Java is hozzájuk tartozik, de legalább adnak kedvezményt egy csomó Java könyvre:
- Java 7 JAX-WS Web Services
- Java EE 6 Cookbook for Securing, Tuning, and Extending Enterprise Applications
- Secure Java: For Web Application Development
- Java Applications Architecture
- Pro JavaFX 2
- The Well Grounded Java Developer
A legtöbb esetben elég egy kuponkódot megadnunk, amely az Oracle oldalán olvasható, és az akciók 2012. augusztus 31-ig szólnak.
Ha jól számolom, akkor a múlt héten a negyedik alkalommal tolódott a jövőbe a Java 6 end-of-life dátuma, ugyanis eredetileg 4 éves ciklusokban gondolkodtak a Sun döntéshozói, így a Java 6 2010 decemberében vonult volna nyugdíjba. A számításokat azonban keresztülhúzta a Sun eladása-felvásárlása és nyilván nem lehet nyugdíjba küldeni egy Java verziót, amikor még nincs kész az utód, a Java 7 ugyanis csak 2011 nyarán került ki, és ez volt az oka a második hosszabbításnak, amely során 2012 júliusig tolták ezt a határidőt, majd idén év elején továbbtolták 2012 novemberig, amelyet most meghosszabbítottak 2013 februárig.
A Sun válság előtti felébredésekor négy éves ciklusokban gondolkodtak, amely azt jelentette, hogy egy Java major verziót az átlagos halandók számára (ingyen) négy éven át támogatnak, és két évente adnak ki egy-egy újabb Java verziót, így mindig kettő major verzió van támogatva egy időszakban. Mint említettem volt, ezt felülírta a 2008 végén induló válság, amely jobban megviselte a Sun-t, mint a többi céget, így a részvényesek a cégből való kiszálláson kezdtek gondolkodni, így a vezetésnek nem maradt sok választása: el kellett adnia a céget. Mint tudjuk, az Oracle vette meg, és a kezdeti zűrzavarban nagyon sok kulcsember pattant meg, nagyon sok projektet lőttek le különféle okok miatt, így nem csoda, hogy a Java kiadások ütemezésével gondok voltak.
Különösen érdekes (vagy sajnálatos) ez a döntés annak tudatában, hogy a Java 8 vélhetően csúszni fog és a Jigsaw nem kerül bele, mert nincs olyan állapotban a projekt, amelyre építeni lehetne, remélhetőleg a többi fontos újítás bele tud kerülni a nyelvi elemek közé, ugyanis a teljes Java 8 featureset be volt ígérve a Java 7 kiadásba... de várnunk még legalább egy évet: a végleges Java 8 csak 2013 szeptember környékén kerül kiadásra, pedig ezt is hamarabb ígérték...
A Java7 megjelenését megelőzően nagy várakozás övezte a NIO.2 újdonságait, aztán elmúlt a hype. Ennek oka valószínűleg az lehet, hogy a Java jelenleg két erős területén – az Android és a Java EE platformon – nincs igazán szükség a fájlműveletek támogatására. Az Android esetén megtűrt dolognak számít a fájlrendszer, az SQLite alapú tárterület a támogatott; Java EE esetén pedig deklaráltan nem alapozunk a fájlrendszerre.
Nem mindenki lehet Android vagy Java EE fejlesztő – szükséges az IDE-k fejlesztése is :), ezért nézzük át, milyen előnyöket ad a NIO.2, amely alapvetően a Java eddigi fájlrendszer modelljét bővíti ki az alábbiakkal:
- Platform független fájlrendszer modell
- Fájlrendszer-fa feltérképezés
- Az állományműveletek atomi támogatása (másolás, törlés, mozgatás)
- Soft- és hard-link támogatás
- Fájl attribútumok kezelése
- Változás követés
- SPI támogatás
Nézzük ezeket egyenként...
Platform független fájlrendszer modell
A Java7 NIO.2 kapcsán került bevezetésre a Path osztály, amely az eddigi megoldások mellett lehetővé teszi az elérési útvonalak platformra való fordítását. Emlékezzünk: egy csomó problémánk volt abból, hogy Unix like rendszereken a fájlrendszer kiinduló pontja a / volt, míg Windows és Windows fájlkezelését emuláló rendszerek (emlékeim szerint például a Symbian) esetén voltak meghajtók, így több gyökere is volt a fájlrendszereknek, illetve az elérési útvonalon a szinteket elválasztó jel a / helyett a \ volt, így a multiplatformos programjaink tele voltak platformfüggő elágazásokkal, illetve File.separator összefűzésekkel. Nem beszélve a soft- és hard-link támogatásról, a valódi elérési út felderítéséről és a többi apróságról... Na, ennek végre vége...
Fájlrendszer-fa feltérképezés
A fájlrendszer-fa feltérképezése azon igények egyike, amelyre eddig még nem volt szükségem, de örülök, hogy a NIO.2 ezt már támogatja, az alkalmazás szerverek, illetve a különféle szerver oldali Java megoldások fejlesztői nyilván örülnek egy ilyen lehetőségnek. A módszer a Visitor minta alapján épül fel, ezért hozzunk létre egy saját Visitor-t, amely egyszerűen csak kiírja a kapott Path példányt:
public class FileVisitor extends SimpleFileVisitor<Path> { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { System.out.println(file); return FileVisitResult.CONTINUE; } }
Ezek után már csak meg kell hívnunk:
Path basePath = Paths.get("."); try { Files.walkFileTree(basePath, new FileVisitor()); } catch (IOException ex) { Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex); }
Az eredmény nem marad el:
./pom.xml ./src/test/java/hu/javaforum/testproject/AppTest.java ./src/main/java/hu/javaforum/testproject/App.java ./target/classes/hu/javaforum/testproject/App$FileVisitor.class ./target/classes/hu/javaforum/testproject/App$1.class ./target/classes/hu/javaforum/testproject/App.class
Az állományműveletek atomi támogatása
Sajnos a Java hetes verzióig kellett várnunk arra, hogy egy fájlt át tudjunk mozgatni vagy akár csak átnevezni... ez is már a múlté...
> ls -l /tmp/test* -rw-r--r-- 1 auth.gabor users 5 aug 12 12.30 /tmp/test
Tekintsük a fenti egy darab állományt, amelyet szeretnénk átmásolni test2 névre, majd átnevezni test3 névre:
Path srcFile = Paths.get("/tmp/test"); Path dstFile = Paths.get("/tmp/test2"); Path moveFile = Paths.get("/tmp/test3"); Files.copy(srcFile, dstFile, StandardCopyOption.COPY_ATTRIBUTES); Files.move(srcFile, moveFile, StandardCopyOption.ATOMIC_MOVE);
És az eredmény nem marad el:
> ls -l /tmp/test* -rw-r--r-- 1 auth.gabor users 5 aug 12 12.30 /tmp/test2 -rw-r--r-- 1 auth.gabor users 5 aug 12 12.30 /tmp/test3
Ez Java7 előtt egy több tucat soros varázslatra volt szükség egy ilyen igény teljesítéséhez.
Soft- és hard-link támogatás
A NIO.2 előtt erre nem volt lehetőség, nem lehetett megállapítani egy elérési útról, hogy az tartalmaz-e linkeket vagy sem, most már vannak eszközeink.
> ls -l /tmp/test* -rw-r--r-- 1 auth.gabor users 5 aug 12 12.30 /tmp/test
Hozzunk létre egy soft- (symbolic-) és egy hard-linket:
Path srcFile = Paths.get("/tmp/test"); Path softLinkFile = Paths.get("/tmp/test2"); Path hardLinkFile = Paths.get("/tmp/test3"); Files.createSymbolicLink(softLinkFile, srcFile); Files.createLink(hardLinkFile, srcFile); System.out.println("isSymbolicLink:"); System.out.println(srcFile + ": " + Files.isSymbolicLink(srcFile)); System.out.println(softLinkFile + ": " + Files.isSymbolicLink(softLinkFile)); System.out.println(hardLinkFile + ": " + Files.isSymbolicLink(hardLinkFile));
Az eredmény nem marad el:
isSymbolicLink: /tmp/test: false /tmp/test2: true /tmp/test3: false
A fájlrendszernél is látszik az átlinkelés, illetve a link számláló a hard-link esetén:
> ls -l /tmp/test* -rw-r--r-- 2 auth.gabor users 5 aug 12 12.30 /tmp/test lrwxrwxrwx 1 auth.gabor users 9 aug 12 12.44 /tmp/test2 -> /tmp/test -rw-r--r-- 2 auth.gabor users 5 aug 12 12.30 /tmp/test3
Fájl attribútumok kezelése
Ha le szeretnénk kérdezni egy adott fájl attribútumait, akkor a legtöbb példában megemlítésre kerül a JNI vagy a széttárt kéz, mivel erre túl sok eszközünk nem volt a Java platformot tekintve, s sajnos a megfelelő megoldásra egészen a Java7 megjelenéséig várnunk kellett. A fentiekhez hasonlóan a megoldás egyszerű, csak azt kell eldöntenünk, hogy milyen attribútumokat szeretnénk kiolvasni (a teljesség igénye nélkül):
- BasicFileAttributeView
- DosFileAttributeView
- PosixFileAttributeView
- UserDefinedFileAttributeView
- AclFileAttributeView
- FileOwnerAttributeView
Fogjunk egy megfelelő áldozatot és vallassuk ki:
BasicFileAttributes bfa = Files.readAttributes(srcFile, BasicFileAttributes.class); DosFileAttributes dfa = Files.readAttributes(srcFile, DosFileAttributes.class); PosixFileAttributes pfa = Files.readAttributes(srcFile, PosixFileAttributes.class); AclFileAttributeView afa = Files.getFileAttributeView(srcFile, AclFileAttributeView.class); FileOwnerAttributeView foa = Files.getFileAttributeView(srcFile, FileOwnerAttributeView.class); System.out.println("BasicFileAttributes:"); System.out.println(srcFile + ":creationTime " + bfa.creationTime()); System.out.println(srcFile + ":isDirectory " + bfa.isDirectory()); System.out.println(srcFile + ":isOther " + bfa.isOther()); System.out.println(srcFile + ":isRegularFile " + bfa.isRegularFile()); System.out.println(srcFile + ":isSymbolicLink " + bfa.isSymbolicLink()); System.out.println(srcFile + ":lastAccessTime " + bfa.lastAccessTime()); System.out.println(srcFile + ":lastModifiedTime " + bfa.lastModifiedTime()); System.out.println(srcFile + ":size " + bfa.size()); System.out.println("DosFileAttributes:"); System.out.println(srcFile + ":isArchive " + dfa.isArchive()); System.out.println(srcFile + ":isHidden " + dfa.isHidden()); System.out.println(srcFile + ":isReadOnly " + dfa.isReadOnly()); System.out.println(srcFile + ":isSystem " + dfa.isSystem()); System.out.println("PosixFileAttributes:"); System.out.println(srcFile + ":group " + pfa.group()); System.out.println(srcFile + ":owner " + pfa.owner()); System.out.println(srcFile + ":permissions " + pfa.permissions()); System.out.println("AclFileAttributeView:"); if (afa != null) { System.out.println(srcFile + ":getAcl " + afa.getAcl()); } System.out.println("FileOwnerAttributeView:"); if (foa != null) { System.out.println(srcFile + ":getOwner " + foa.getOwner()); }
Majd nézzük meg, mit mesélt magáról:
BasicFileAttributes: /tmp/test:creationTime 2012-08-12T10:30:39Z /tmp/test:isDirectory false /tmp/test:isOther false /tmp/test:isRegularFile true /tmp/test:isSymbolicLink false /tmp/test:lastAccessTime 2012-08-12T10:33:09Z /tmp/test:lastModifiedTime 2012-08-12T10:30:39Z /tmp/test:size 5 DosFileAttributes: /tmp/test:isArchive false /tmp/test:isHidden false /tmp/test:isReadOnly false /tmp/test:isSystem false PosixFileAttributes: /tmp/test:group users /tmp/test:owner auth.gabor /tmp/test:permissions [GROUP_READ, OTHERS_READ, OWNER_WRITE, OWNER_READ] AclFileAttributeView: FileOwnerAttributeView: /tmp/test:getOwner auth.gabor
Változás követés
A fájlrendszerben történt változások figyelése fontos feladat, gondoljunk csak a kedvenc fejlesztőkörnyezetünkre, amely szeretne értesülni arról, hogy a háta mögött módosítunk egy állományt. A Java7 előtt erre különféle praktikákra volt szükség, de ez is a múlté...
Tegyük fel, hogy szeretnénk figyelni a /tmp/nio.2/ könyvtár tartalmában beálló módosulásokat:
Path tmpDir = Paths.get("/tmp/nio.2/"); WatchService watcher = FileSystems.getDefault().newWatchService(); tmpDir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); while (true) { WatchKey key = null; try { key = watcher.take(); } catch (InterruptedException ex) { Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex); } for (WatchEvent event : key.pollEvents()) { System.out.println(event.context() + ": " + event.kind()); } key.reset(); }
A fenti program szerkezete viszonylag egyszerű, megmondjuk, hogy mit szeretnénk figyelni, regisztráljuk a figyelő szolgáltatásba, majd egy végtelen ciklusban figyeljük az események bekövetkeztét. Próbáljuk ki:
> touch /tmp/nio.2/test > rm /tmp/nio.2/test > touch /tmp/nio.2/test2 > echo "abc" >/tmp/nio.2/test2 > rm /tmp/nio.2/test2
Ezzel egy időben az alábbit kell lássuk a programunk kimenetén:
test: ENTRY_CREATE test: ENTRY_MODIFY test: ENTRY_DELETE test2: ENTRY_CREATE test2: ENTRY_MODIFY test2: ENTRY_MODIFY test2: ENTRY_DELETE
Úgy gondolom, hogy sok Java fejlesztő nem fogja használni a fenti megoldásokat, mivel ahhoz az kellene, hogy a Java platform desktop környezetben is terjedjen el, de jelenleg nem tudunk túl sok példát mondani multiplatformos programra.
A héten nézelődtem az Amazon kínálatában Java EE 6 könyvek között, és megakadt a szemem a címben említett művön, amelyet a Packt Publishing adott ki 2012 júniusában, nyomtatott és természetesen e-book formában is. Érdemes odafigyelni, hogy hol veszi meg az ember, mivel érdekes, ám többnyire megszokott jelenséggel szembesülhetünk – a könyv ára nem tükrözi a pénznemek közötti értékbeli különbséget ($1 ~ €1 ~ £1):
- Amazon USA: $15.23 ~ 3.400Ft
- Packt Publishing: €16.14 ~ 4.400Ft
- Amazon UK: £15.44 ~ 5.400Ft
A tartalomból
Üres óráimban átlapoztam a Kindle alkalmazásba letöltődő könyvet, és úgy találtam, hogy a mintaként olvasott pár oldal jól reprezentálja a könyv további tartalmát:
- Java EE 6 újdonságokról általánosságban: mi avult el, mik az újdonságok
- JPA2.0 újdonságok
- Az Java EE 6 biztonsági modellje
- Tesztelés, EJB, JPA, JSF tesztelési lehetőségek (Mock osztályok, Selenium, DBUnit, stb)
- Groovy, Jython, Scala, AspectJ és CDI újdonságok, Java EE 6 integráció
- Mobil (szerveroldali) keretrendszer, mobil eszközökkel való kommunikáció
- Deployment és konfigurációs eszközök (CDI, Groovy, JRebel, JMX, VisualVM, stb)
- Teljesítményhangolás és hibakeresés (VisualVM, VisualGC, Netstat, TCPMon, HTTP Debugger)
A véleményem
A könyv olvasásához szükséges egy biztos Java tudás, illetve némi Java EE tudás se árt, de hiányos Java ismeretekkel is olvasmányos, bár néhol túlzsúfolt forráskód részletekkel, parancssori utasításokkal és képernyőfotókkal.
Ajánlom mindenkinek, aki szeretné megérteni, hogy milyen újdonságok vannak a Java EE 6 kiadásban, illetve szeretne néhány kurrens eszközt és technológiát megismerni (főképp a tesztelés és hibakeresés témakörében), a $15 dollár nem olyan hatalmas összeg, úgy vélem, hogy a könyv írója megérdemel ennyit...