tag:blogger.com,1999:blog-62738186848314543062024-03-18T11:48:25.542+02:00cat **/*Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.comBlogger62125tag:blogger.com,1999:blog-6273818684831454306.post-6840217451346353832014-03-08T14:37:00.000+02:002014-03-08T14:41:18.395+02:00Setting up direct access to a block device from VM in Xen XCP (Debian 7.4 (wheezy))There is no good documentation for XCP at the moment. Amount of documentation for such a complicated project is close to nothing when it comes to XCP on Debian (project Kronos). Citrix XenServer has a better support but I don't use XenServer, I use Debian. Therefore almost any simple task starts with "hours" of search in internet.<br />
Normally you don't need direct access to a block device from a virtual machine, but in some cases it is very to convenient to use one. One of such cases is a file/backup server which needs access to a raid or just a huge hard disk with an existing file system.<br />
Here is what should be done in order to make it work. <br />
1. Create a directory which will contain links to the block devices visible in XEN. <br />
<pre>mkdir /srv/xen-devices</pre>
<br />
2. Create storage repository for the block devices<br />
<pre>xe sr-create name-label="Block devices" name-description="Block devices which we want to use directly in XEN" type=udev content-type=disk device-config:location=/srv/xen-devices</pre>
assign displayed <i>uuid</i> to shell variable <i>SR</i><br />
<br />
3. [Optional] If step 2 fails with the error message:<br />
<i>The SR could not be connected because the driver was not recognised.<br />driver: udev</i><br />
then you need to fix it. Do the following:<br />
<pre>cd /usr/lib/xcp/sm/
ln -s udevSR.py udevSR
/usr/lib/xcp/bin/xe-toolstack-restart</pre>
And then try again step 2.<br />
<br />
4. Find a device you want to make visible in the Xen, for example, like this:<br />
<pre>ls -l /dev/disk/by-path</pre>
<br />
Link it <br />
<pre>ln -s /dev/disk/by-id/ata-some-device /srv/xen-devices/some-device</pre>
<br />
5. Rescan our storage repository<br />
<pre>xe sr-scan uuid=$SR</pre>
<br />
6. List VDIs of the storage repository and spot the one with "Unrecognised bus type"<br />
<pre>xe vdi-list sr-uuid=$SR</pre>
<br />
assign VDI¨s <i>uuid</i> to the VDI variable in shell.<br />
<br />
7. Set name and label for the VDI to whatever you like:<br />
<pre>xe vdi-param-set uuid=$VDI name-description="A real disk"
xe vdi-param-set uuid=$VDI name-label="R-disk"</pre>
<br />
8. Create VBD which assign the VDI to the VM<br />
<pre>xe vbd-create device=1 vm-uuid=$VM vdi-uuid=$VDI bootable=false mode=RW type=Disk</pre>
assign display <i>uuid</i> to the VBD variable<br />
<br />
9. Attach it to the VM<br />
<pre>xe vbd-plug uuid=$VBD</pre>
<br />
That's all. Now you can log into the virtual machine and check with 'dmesg' that a new device is available.<br />
<br />
<br /><ad></ad>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com4tag:blogger.com,1999:blog-6273818684831454306.post-16200335429200235272012-09-11T21:41:00.001+03:002012-09-11T21:41:48.322+03:00Full (de)serialization for Play Json using general purpose macrosI've released a new version of <a href="https://github.com/akshaal/akmacros">akmacros</a> library for Scala 2.10.
The release includes a new macro called 'factory'. Thanks to the new macro it is possible to construct a class
with a public default constructor just passing a function to the generated factory of the class. The function
receives symbol of an argument of the constructor and returns value for this argument. If function returns None, then
default value for the argument is evaluated (provided that it is defined for the given argument). Here is the example:
<pre>
scala> <span style="color: #00ffff;">import</span> info.akshaal.clazz._
import info.akshaal.clazz._
scala> <span style="color: #00ffff;">case</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Record</span> (<span style="color: #13ff12;">name</span>: <span style="color: #98fb98;">String</span>, <span style="color: #13ff12;">twitter</span>: <span style="color: #98fb98;">Option[String]</span> = None)
defined class Record
scala> <span style="color: #00ffff;">val</span> <span style="color: #13ff12;">recordFactory</span> = <span style="color: #24BEE3;">factory</span>[<span style="color: #98fb98;">Any</span>, <span style="color: #98fb98;">Record</span>]('castValue)
recordFactory: (Symbol => Option[Any]) => Record = <function1>
scala> <span style="color: #00ffff;">val</span> <span style="color: #13ff12;">args</span> = <span style="color: #13ff12;">Map</span>('name -> <span style="color: #ffa07a;">"Evgeny"</span>)
args: scala.collection.immutable.Map[Symbol,String] = Map('name -> Evgeny)
scala> recordFactory(args.<span style="color: #24BEE3;">get</span>)
res0: Record = Record(Evgeny,None)
</pre>
<h3>Writing less boilerplate code for Play Json</h3>
Just to demonstrate the way macro functions can simplify your code I've created <a href="https://github.com/akshaal/akmacros-json">a small project on github</a>.
The project includes Json library from the Play2.0 framework mostly as-is. The only changes I did are related to making it work on scala 2.10
(upgraded it to patched jerkson and so on).
You might be interested in <a href="https://github.com/akshaal/akmacros-json/blob/master/src/main/scala/info/akshaal/play.scala">this file</a>.
It is the only file that I implemented in that project in order to add support for macros to the Play Json.
Following the same pattern, you can easily use almost any other Json library like this.<BR/><BR/>
Lets look what it gives you without any reflections.. Lets start with something simple:
<pre>
scala> <span style="color: #00ffff;">import</span> info.akshaal.json.play._
import info.akshaal.json.play._
scala> <span style="color: #00ffff;">import</span> play.api.libs.json._
import play.api.libs.json._
scala> <span style="color: #00ffff;">case</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Simple</span>(<span style="color: #13ff12;">str</span>: <span style="color: #98fb98;">String</span>, <span style="color: #13ff12;">num</span>: <span style="color: #98fb98;">Int </span>= <span style="color: #00ffff;">new</span> Random().nextInt())
defined class Simple
scala> <span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">simpleJsFactory</span> = <span style="color: #24BEE3;">factory</span>[<span style="color: #98fb98;">Simple</span>]('fromJson)
simpleJsFactory: (Symbol => Option[play.api.libs.json.JsValue]) => Simple = <function1>
scala> <span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">simpleJsFields</span> = <span style="color: #24BEE3;">allFields</span>[<span style="color: #98fb98;">Simple</span>]('jsonate)
simpleJsFields: List[info.akshaal.clazz.Field[Simple,play.api.libs.json.JsValue,None.type]] = List(Field(str,<function1>,None), Field(num,<function1>,None))
</pre>
We can serialize and then deserialize:
<pre>
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">obj</span> = <span style="color: #00ffff;">new</span> <span style="color: #98fb98;">Simple</span>(<span style="color: #ffa07a;">"123"</span>, 5)
obj: Simple = Simple(123,5)
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">objJs</span> = Json.<span style="color: #24BEE3;">toJson</span>(<span style="color: #73ff73;">obj</span>)
objJs: play.api.libs.json.JsValue = {<span style="color: #ffa07a;">"str"</span>:<span style="color: #ffa07a;">"123"</span>,<span style="color: #ffa07a;">"num"</span><span style="color: #b0c4de;">:5</span>}
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">obj2</span> = Json.<span style="color: #24BEE3;">fromJson</span>[Simple](<span style="color: #73ff73;">objJs</span>)
obj2: Simple = Simple(123,5)
</pre>
That was easy. Now lets try to leverage default value feature of the case class:
<pre>
scala> <span style="color: #00ffff;">val</span> <span style="color: #13ff12;">halfObjJs</span> = Json.<span style="color: #24BEE3;">parse</span>(<span style="color: #ffa07a;">""" {"str":"test"} """</span>)
halfObjJs: play.api.libs.json.JsValue = {<span style="color: #ffa07a;">"str"</span>:<span style="color: #ffa07a;">"test"</span>}
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">halfObj</span> = Json.<span style="color: #24BEE3;">fromJson</span>[Simple](<span style="color: #73ff73;">halfObjJs</span>)
halfObj: Simple = Simple(test,-813663852)
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">halfObj</span> = Json.<span style="color: #24BEE3;">fromJson</span>[Simple](<span style="color: #73ff73;">halfObjJs</span>)
halfObj: Simple = Simple(test,-948806581)
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">halfObj</span> = Json.<span style="color: #24BEE3;">fromJson</span>[Simple](<span style="color: #73ff73;">halfObjJs</span>)
halfObj: Simple = Simple(test,428745442)
</pre>
Note that we parsed halfObjJs three times. And 'num' was always different. That is because value for 'num' is missing in the halfObjJs and so the expression for default
value was used (which is Random().nextInt, see defintion of Simple class). How about parametrized classes? Lets try:
<pre>
scala> <span style="color: #00ffff;">case</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Event</span>[<span style="color: #98fb98;">T</span>](<span style="color: #13ff12;">kind</span>: <span style="color: #98fb98;">String</span>, <span style="color: #13ff12;">payloads</span>: <span style="color: #026DF7;">T</span>)
defined class Event
scala> <span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">eventJsFields</span>[<span style="color: #98fb98;">T</span><span style="color: #084EA8;">: Writes</span><span style="color: #ffff70;">] </span>= allFields[Event[<span style="color: #ffff70;">T</span>]]('jsonate)
eventJsFields: [T](implicit evidence$1: play.api.libs.json.Writes[T])List[info.akshaal.clazz.Field[Event[T],play.api.libs.json.JsValue,None.type]]
scala> <span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">eventJsFactory</span>[<span style="color: #98fb98;">T</span><span style="color: #084EA8;">: Reads</span><span style="color: #ffff70;">] =</span> factory[Event[<span style="color: #ffff70;">T</span>]]('fromJson)
eventJsFactory: [T](implicit evidence$1: play.api.libs.json.Reads[T])(Symbol => Option[play.api.libs.json.JsValue]) => Event[T]
</pre>
And test:
<pre>
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">event</span> = <span style="color: #026DF7;">Event</span>(kind = <span style="color: #ffa07a;">"strange"</span>, payloads = <span style="color: #73ff73;">obj</span>)
event: Event[Simple] = Event(strange,Simple(123,5))
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">eventJs</span> = <span style="color: #026DF7;">Json</span>.<span style="color: #24BEE3;">toJson</span>(<span style="color: #73ff73;">event</span>)
eventJs: play.api.libs.json.JsValue = {<span style="color: #ffa07a;">"kind"</span>:<span style="color: #ffa07a;">"strange"</span>,<span style="color: #ffa07a;">"payloads"</span>:{<span style="color: #ffa07a;">"str"</span>:<span style="color: #ffa07a;">"123"</span>,<span style="color: #ffa07a;">"num"</span><span style="color: #b0c4de;">:5</span>}}
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">event3</span> = <span style="color: #026DF7;">Json</span>.<span style="color: #24BEE3;">fromJson</span>[<span style="color: #98fb98;">Event[Simple]</span>](<span style="color: #73ff73;">eventJs</span>)
event3: Event[Simple] = Event(strange,Simple(123,5))
</pre>
In the real world it is unlikely that you will use completely unrestricted types (like T in the example above) in your case classes with json.
It is more likely that there will be a (sealed) trait and some set of its subtypes. Lets see how it works. First, we will define some more case classes:
<pre>
<span style="color: #00ffff;">sealed</span> <span style="color: #00ffff;">trait</span> <span style="color: #98fb98;">Message</span>
<span style="color: #00ffff;">case</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">QuitMessage</span>(<span style="color: #13ff12;">msg</span>: <span style="color: #98fb98;">String</span>) <span style="color: #00ffff;">extends</span> <span style="color: #084EA8;">Message</span>
<span style="color: #00ffff;">case</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Heartbeat</span>(<span style="color: #13ff12;">id</span>: <span style="color: #98fb98;">Int</span>) <span style="color: #00ffff;">extends</span> <span style="color: #084EA8;">Message</span>
<span style="color: #00ffff;">case</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Messages</span>(<span style="color: #13ff12;">userId</span>: <span style="color: #98fb98;">Int</span>, <span style="color: #13ff12;">messages</span>: <span style="color: #98fb98;">List[Message]</span> = List.empty)
</pre>
Now, lets define how to serialize our new case classes:
<pre>
<span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">messageWrites</span> = <span style="color: #24BEE3;">matchingWrites</span>[<span style="color: #084EA8;">Message</span>] {
<span style="color: #00ffff;">case</span> <span style="color: #eedd82;">m</span>: <span style="color: #98fb98;">QuitMessage => </span><span style="color: #24BEE3;">quitMessageJsFields</span><span style="color: #98fb98;">.</span><span style="color: #24BEE3;">toWrites</span><span style="color: #98fb98;">.</span><span style="color: #24BEE3;">writes</span>(<span style="color: #eedd82;">m</span>)
<span style="color: #00ffff;">case</span> <span style="color: #eedd82;">m</span>: <span style="color: #98fb98;">Heartbeat => </span><span style="color: #24BEE3;">heartbeatJsFields</span><span style="color: #98fb98;">.</span><span style="color: #24BEE3;">toWrites</span><span style="color: #98fb98;">.</span><span style="color: #24BEE3;">writes</span>(<span style="color: #eedd82;">m</span>)
}
<span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">quitMessageJsFields</span> = allFields[QuitMessage]('jsonate)
<span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">heartbeatJsFields</span> = allFields[Heartbeat]('jsonate)
<span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">messagesJsFields</span> = allFields[Messages]('jsonate)
</pre>
And if deserialization is needed, lets define how to do it:
<pre>
<span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">quitMessageJsFactory</span> = factory[QuitMessage]('fromJson)
<span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">heartbeatJsFactory</span> = factory[Heartbeat]('fromJson)
<span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">messagesJsFactory</span> = factory[Messages]('fromJson)
<span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">messageReads</span>: <span style="color: #084EA8;">Reads[Message]</span> =
<span style="color: #24BEE3;">predicatedReads</span>[<span style="color: #084EA8;">Message</span>](
<span style="color: #24BEE3;">jsHas</span>('msg) -> <span style="color: #24BEE3;">quitMessageJsFactory</span>,
<span style="color: #24BEE3;">jsHas</span>('id) -> <span style="color: #24BEE3;">heartbeatJsFactory</span>
)
</pre>
Finally, lets try it:
<pre>
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">event5</span> =
<span style="color: #026DF7;">Event</span>(kind = <span style="color: #ffa07a;">"t1"</span>,
payloads = <span style="color: #026DF7;">Messages</span>(userId = 4, messages = List(<span style="color: #026DF7;">Heartbeat</span>(5), <span style="color: #026DF7;">QuitMessage</span>(<span style="color: #ffa07a;">"bye!"</span>))))
event5: Event[Messages] = Event(t1,Messages(4,List(Heartbeat(5), QuitMessage(bye!))))
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">event5Js</span> = <span style="color: #026DF7;">Json</span>.<span style="color: #24BEE3;">toJson</span>(<span style="color: #73ff73;">event5</span>)
event5Js: play.api.libs.json.JsValue = {<span style="color: #ffa07a;">"kind"</span>:<span style="color: #ffa07a;">"t1"</span>,<span style="color: #ffa07a;">"payloads"</span>:{<span style="color: #ffa07a;">"userId"</span><span style="color: #b0c4de;">:4</span>,<span style="color: #ffa07a;">"messages"</span>:[{<span style="color: #ffa07a;">"id"</span><span style="color: #b0c4de;">:5</span>},{<span style="color: #ffa07a;">"msg"</span>:<span style="color: #ffa07a;">"bye!"</span>}]}}
</pre>
Pay attention, that Json for QuitMessage and Heartbeat classes has no type information or anything! It's just plain json with domain fields only.
That's why messageReads has those jsHas occurances in its implementation, that is a little help for identifying which json object is what subtype of Message.
Lets see that reading from json still works:
<pre>
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">event6</span> = Json.<span style="color: #24BEE3;">fromJson</span>[Event[Messages]](<span style="color: #73ff73;">event5Js</span>)
even6: Event[Messages] = Event(t1,Messages(4,List(Heartbeat(5), QuitMessage(bye!))))
</pre>
Actually there is another way to do the same. You can inject an extra field into json object when serializing one of subtypes of an abstract type and use it
as a guidance for reconstructing objects from json. It is really easy. Lets modify messageReads and messageWrites like this:
<pre>
<span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">messageWrites</span> = <span style="color: #24BEE3;">matchingWrites</span>[<span style="color: #084EA8;">Message</span>] {
<span style="color: #00ffff;">case</span> <span style="color: #eedd82;">m</span>: <span style="color: #98fb98;">QuitMessage => </span><span style="color: #24BEE3;">quitMessageJsFields</span><span style="color: #98fb98;">.</span><span style="color: #24BEE3;">extra</span>(<span style="color: #eedd82;">'</span><span style="color: #00ffff;">type</span> <span style="color: #24BEE3;">-></span> <span style="color: #eedd82;">'quit</span>)<span style="color: #eedd82;">.</span><span style="color: #24BEE3;">toWrites</span><span style="color: #eedd82;">.</span><span style="color: #24BEE3;">writes</span>(<span style="color: #eedd82;">m</span>)
<span style="color: #00ffff;">case</span> <span style="color: #eedd82;">m</span>: <span style="color: #98fb98;">Heartbeat => </span><span style="color: #24BEE3;">heartbeatJsFields</span><span style="color: #98fb98;">.</span><span style="color: #24BEE3;">extra</span>(<span style="color: #eedd82;">'</span><span style="color: #00ffff;">type</span> <span style="color: #24BEE3;">-></span> <span style="color: #eedd82;">'heart</span>)<span style="color: #eedd82;">.</span><span style="color: #24BEE3;">toWrites</span><span style="color: #eedd82;">.</span><span style="color: #24BEE3;">writes</span>(<span style="color: #eedd82;">m</span>)
}
<span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">messageReads</span>: <span style="color: #084EA8;">Reads[Message]</span> =
<span style="color: #24BEE3;">predicatedReads</span>[<span style="color: #084EA8;">Message</span>](
<span style="color: #24BEE3;">jsHas</span>('<span style="color: #00ffff;">type</span> <span style="color: #98fb98;">-></span> 'quit) -> <span style="color: #24BEE3;">quitMessageJsFactory</span>,
<span style="color: #24BEE3;">jsHas</span>('<span style="color: #00ffff;">type</span> <span style="color: #98fb98;">-></span> 'heart) -> <span style="color: #24BEE3;">heartbeatJsFactory</span>
)
</pre>
Now we test the new implementation.
<pre>
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">messages</span> = List(<span style="color: #026DF7;">Heartbeat</span>(1), <span style="color: #026DF7;">QuitMessage</span>(<span style="color: #ffa07a;">"Hello"</span>), <span style="color: #026DF7;">Heartbeat</span>(99))
messages: List[Product with Serializable with Message] = List(Heartbeat(1), QuitMessage(Hello), Heartbeat(99))
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">messagesJs</span> = <span style="color: #026DF7;">Json</span>.<span style="color: #24BEE3;">toJson</span>(<span style="color: #73ff73;">messages</span>)
messagesJs: play.api.libs.json.JsValue = [{<span style="color: #ffa07a;">"type"</span>:<span style="color: #ffa07a;">"heart"</span>,<span style="color: #ffa07a;">"id"</span><span style="color: #b0c4de;">:1</span>},{<span style="color: #ffa07a;">"type"</span>:<span style="color: #ffa07a;">"quit"</span>,<span style="color: #ffa07a;">"msg"</span>:<span style="color: #ffa07a;">"Hello"</span>},{<span style="color: #ffa07a;">"type"</span>:<span style="color: #ffa07a;">"heart"</span>,<span style="color: #ffa07a;">"id"</span><span style="color: #b0c4de;">:99</span>}]
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">messages2</span> = <span style="color: #026DF7;">Json</span>.<span style="color: #24BEE3;">fromJson</span>[<span style="color: #98fb98;">List[Message]</span>](<span style="color: #73ff73;">messagesJs</span>)
messages2: List[Message] = List(Heartbeat(1), QuitMessage(Hello), Heartbeat(99))
</pre>
That's not all. What if there is an information in a case class you don't want to reveal in JSON? Consider the following case class.
I will annotate fields that are safe to export by Ok annotation:
<pre>
@annotation.meta.getter
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Ok</span> <span style="color: #00ffff;">extends</span> <span style="color: #084EA8;">annotation.StaticAnnotation</span>
<span style="color: #00ffff;">case</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">User</span>(<span style="color: #13ff12;">@Ok</span> <span style="color: #eedd82;">login</span>: <span style="color: #98fb98;">String</span>,
<span style="color: #13ff12;">@Ok</span> <span style="color: #eedd82;">fullName</span>: <span style="color: #98fb98;">String</span>,
<span style="color: #13ff12;">@Ok</span> <span style="color: #eedd82;">messages</span>: <span style="color: #98fb98;">Int</span> = 0,
<span style="color: #eedd82;">passwordHash</span>: <span style="color: #98fb98;">Option[String]</span> = None)
</pre>
Now it's quite natural to define json fields like this:
<pre>
<span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">userJsFields</span> = <span style="color: #24BEE3;">annotatedFields</span>[<span style="color: #98fb98;">User</span>, <span style="color: #98fb98;">Ok</span>]('jsonate)
</pre>
Let see it in action:
<pre>
scala>
| <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">user</span> = <span style="color: #026DF7;">User</span>(login = <span style="color: #ffa07a;">"akshaal"</span>,
| fullName = <span style="color: #ffa07a;">"Evgeny Chukreev"</span>,
| messages = 10,
| passwordHash = <span style="color: #026DF7;">Some</span>(<span style="color: #ffa07a;">"4d18758602c08243d7c08f8c9e4463b0"</span>))
user: User = User(akshaal,Evgeny Chukreev,10,Some(4d18758602c08243d7c08f8c9e4463b0))
scala> <span style="color: #00ffff;">val</span> <span style="color: #73ff73;">userJs</span> = <span style="color: #026DF7;">Json</span>.<span style="color: #24BEE3;">toJson</span>(<span style="color: #73ff73;">user</span>)
userJs: play.api.libs.json.JsValue = {<span style="color: #ffa07a;">"login"</span>:<span style="color: #ffa07a;">"akshaal"</span>,<span style="color: #ffa07a;">"fullName"</span>:<span style="color: #ffa07a;">"Evgeny Chukreev"</span>,<span style="color: #ffa07a;">"messages"</span><span style="color: #b0c4de;">:10</span>}
</pre>
It works.. But you can do more. Recall (if you looked at the implementation) that jsonate function was defined like this:
<pre>
<span style="color: #00ffff;">def</span> <span style="color: #87cefa;">jsonate</span>[<span style="color: #98fb98;">T</span><span style="color: #084EA8;">: Writes</span><span style="color: #ffff70;">](t</span>: <span style="color: #026DF7;">T</span>, <span style="color: #ffff70;">args</span>: <span style="color: #98fb98;">Any</span>): <span style="color: #084EA8;">JsValue</span> = <span style="color: #026DF7;">Json</span>.<span style="color: #24BEE3;">toJson</span>(<span style="color: #ffff70;">t</span>)
</pre>
The function is used to make a json value out of field's value. It is applied to each field.
So you can define your our function that does post-processing (pre-processing?) and use it with a macro. The second argument (args) might be a parameter set given to annotation,
this gives you even more power for writing complex json serialization easily.<BR/><BR/>
And not only JSON. Using the same approach you can (de)serialize object from/to XML...
<h3>Pros of akmacros-json</h3>
<ul>
<li>Domain classes are separated from any notion of JSON</li>
<li>Full control over serialization/deserialization</li>
<li>Easy to use</li>
<li>Easy to extend or implement your own</li>
<li>No runtime reflections used</li>
</ul>
<h3>Cons of akmacros-json</h3>
<ul>
<li>Depends on Jerkson which is officially unavailable for Scala 2.10 (you need to build it from <a href="https://github.com/akshaal/jerkson">my fork</a>
(in order to build it you will need also <a href="https://github.com/akshaal/simplespec">this forked project</a>))
</li>
<li>Includes a copy of Play Json</li>
<li>Scala 2.10-M7 has many bugs related to implicits, value classes... so implementation as you might have noticed is not perfect in terms
of performance (defs are used instead of vals)
</li>
</ul>
I hope things will change really soon with the release of Scala 2.10.
<h3>About general purpose macros</h3>
This tiny macros addition is built on top of Play JSON (which is built on top of Jerkson (which is built on top of Jackson))
and akmacros (which doesn't have dependencies).
Checkout 78 lines long implementation <a href="https://github.com/akshaal/akmacros-json/blob/master/src/main/scala/info/akshaal/play.scala">here</a>.
See <a href="https://github.com/akshaal/akmacros">https://github.com/akshaal/akmacros</a> for a bit more
information about using akmacros with sbt.
Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6273818684831454306.post-46254767033143447892012-09-05T00:46:00.000+03:002012-09-10T21:59:19.427+03:00Easily implementing Json serialization for Play using macro. Function by symbol (lisp-like)lI liked the idea of using <a href="http://www.akshaal.info/2012/08/scala-210-annotated-fields-macro.html">fields macro</a> in scala so much so I created a dedicated project for this macro to start reusing it in the different projects I did. <a href="https://github.com/akshaal/akmacros">Here it is</a>.
<h3>Few words about implementation of this macro</h3>
The code has been reworked and now it is possible to transform field value using a supplied function. It means that Field and Fields types, and fields macro signatures are changed. In addition, there is a new convenient macro called allFields. I.e.:
<pre>
<span style="color: #00ffff;">case</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Field</span>[<span style="color: #98fb98;">-I <: </span><span style="color: #026DF7;">AnyRef</span>, <span style="color: #98fb98;">+R</span>, <span style="color: #98fb98;">+A <: </span><span style="color: #026DF7;">Product</span>](<span style="color: #13ff12;">name</span>: <span style="color: #98fb98;">String</span>, <span style="color: #13ff12;">get</span>: <span style="color: #084EA8;">I => R</span>, <span style="color: #13ff12;">args</span>: <span style="color: #026DF7;">A</span>)
<span style="color: #00ffff;">type</span> <span style="color: #98fb98;">Fields</span>[-I <: <span style="color: #026DF7;">AnyRef</span>, +R, +A <: <span style="color: #026DF7;">Product</span>] = <span style="color: #98fb98;">List[Field[I, R, A]]</span>
<span style="color: #00ffff;">def</span> <span style="color: #87cefa;">fields</span>[<span style="color: #98fb98;">Ann</span>, <span style="color: #98fb98;">I <: </span><span style="color: #026DF7;">AnyRef</span>, <span style="color: #98fb98;">R</span>, <span style="color: #98fb98;">Args <: </span><span style="color: #026DF7;">Product</span>](<span style="color: #ffff70;">apply</span>: <span style="color: #98fb98;">Symbol</span>) = macro <span style="color: #24BEE3;">fieldsImpl</span>[<span style="color: #026DF7;">Ann</span>, <span style="color: #026DF7;">I</span>, <span style="color: #026DF7;">R</span>, <span style="color: #026DF7;">Args</span>]
<span style="color: #00ffff;">def</span> <span style="color: #87cefa;">allFields</span>[<span style="color: #98fb98;">I <: </span><span style="color: #026DF7;">AnyRef</span>, <span style="color: #98fb98;">R</span>](<span style="color: #ffff70;">apply</span>: <span style="color: #98fb98;">Symbol</span>) = macro <span style="color: #24BEE3;">fieldsImpl</span>[<span style="color: #98fb98;">Any</span>, <span style="color: #026DF7;">I</span>, <span style="color: #026DF7;">R</span>, <span style="color: #98fb98;">None.type</span>]
</pre>
allFields is the new function that lists all public value members enclosed in the given type regardless of annotations.
R in a Field(s) type stands for RETURN and represents type of a value returned by the field getter transformed using the supplied function. Value transformer function is passed into the macro using its symbol. You might wonder why aren't we just using something like <span style="color: #eedd82;">f</span> : <span style="color: #98fb98;">T => R </span><span style="color: #00ffff;">forSome</span> { <span style="color: #00ffff;">type</span> <span style="color: #98fb98;">T</span> } ? That's because you can't pass the following function that way:
<pre>
<span style="color: #00ffff;">def</span> <span style="color: #87cefa;">trans</span>[<span style="color: #98fb98;">T</span> : <span style="color: #98fb98;">TypeClass</span>](x : T) : Int = ???
</pre>
(which is just a sweet way of saving some keystrokes by not writing this:)
<pre>
<span style="color: #00ffff;">def</span> <span style="color: #87cefa;">trans</span>[<span style="color: #98fb98;">T</span>](<span style="color: #eedd82;">x</span> : <span style="color: #98fb98;">T</span>)(<span style="color: #00ffff;">implicit</span> <span style="color: #eedd82;">tc</span> : <span style="color: #98fb98;">TypeClass[T]</span>) : <span style="color: #98fb98;">Int </span>= ???
</pre>
i.e. you can't pass function with TWO parameters (one of which is implicit parameter) where a ONE parameter function is expected. That is quite obvious but anyway.. So we use Symbol (in the spirit of Lisp). As you might guess by looking at the snippet below, it is expected that the symbol is constructed directly and not passed by reference:
<pre>
<span style="color: #00ffff;">val</span> <span style="color: #73ff73;">applyFunName</span> =
<span style="color: #ffff70;">apply</span>.<span style="color: #24BEE3;">tree</span> <span style="color: #00ffff;">match</span> {
<span style="color: #00ffff;">case</span> <span style="color: #98fb98;">Apply</span>(<span style="color: #eedd82;">_</span>, <span style="color: #98fb98;">List</span>(<span style="color: #98fb98;">Literal</span>(<span style="color: #98fb98;">Constant</span>(<span style="color: #eedd82;">s</span>)))) => <span style="color: #73ff73;">s</span>.<span style="color: #24BEE3;">toString</span>
<span style="color: #00ffff;">case</span> <span style="color: #eedd82;">_</span> =>
<span style="color: #ffff70;">c</span>.<span style="color: #24BEE3;">abort</span>(<span style="color: #ffff70;">apply</span>.<span style="color: #24BEE3;">tree</span>.<span style="color: #24BEE3;">pos</span>,
<span style="color: #ffa07a;">"fields macro is expected to be used with symbol literal like 'nothing or 'myFunction</span><span style="color: #ffa07a;">"</span>)
}
</pre>
Almost everything in the macro implementation remains more-less same, except part that constructs expression for getting field value out of object. Now it looks like this:
<pre>
<span style="color: #00ffff;">val</span> <span style="color: #eedd82;">applyFunTree</span> = c.parse(applyFunName)
<span style="color: #00ffff;">val</span> <span style="color: #eedd82;">getFunArgTree</span> = ValDef(Modifiers(), newTermName(<span style="color: #ffa07a;">"x"</span>), TypeTree(instanceT), EmptyTree)
<span style="color: #00ffff;">val</span> <span style="color: #eedd82;">getFunBodyTree</span> =
treeBuild.mkMethodCall(applyFunTree,
List(Select(Ident(newTermName(<span style="color: #ffa07a;">"x"</span>)), newTermName(name)),
argsTree))
</pre>
getFunBodyTree illustrates what signature is really expected for the transformer function: in addition to field value, all arguments of the annotation are passed into the function (or None if no annotation used or annotation has no arguments). For example, you can't use Predef.identity function, instead, you should use valueIdentity which is (already) defined like this:
<pre>
<span style="color: #00ffff;">def</span> <span style="color: #87cefa;">valueIdentity</span>[<span style="color: #98fb98;">X</span>] (<span style="color: #ffff70;">value</span> : <span style="color: #026DF7;">X</span>, <span style="color: #ffff70;">annotationArgs</span> : <span style="color: #98fb98;">Any</span>) : <span style="color: #026DF7;">X</span><span style="color: #98fb98;"> </span>= <span style="color: #ffff70;">value</span>
</pre>
Having annotation arguments provided for the currently processing field gives you possibility for further customization of how the value is transformed. Now lets do an example.
<h3>Real-world example</h3>
Suppose you want to serialize your custom classes into JSON with no boilerplate code what so ever. That is how you can do it with this only (general-purpose) macro. Lets define some generic Writes typeclase provider:
<pre>
<span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">writesForFields</span>[<span style="color: #98fb98;">T <: </span><span style="color: #026DF7;">AnyRef</span>](<span style="color: #00ffff;">implicit</span> <span style="color: #ffff70;">fields</span>: <span style="color: #98fb98;">clazz.Fields[T, JsValue, _]</span>): <span style="color: #084EA8;">Writes[T]</span> = {
<span style="color: #00ffff;">new</span> <span style="color: #084EA8;">Writes[T]</span> {
<span style="color: #00ffff;">def</span> <span style="color: #87cefa;">writes</span>(<span style="color: #ffff70;">t</span>: <span style="color: #026DF7;">T</span>): <span style="color: #084EA8;">JsValue</span><span style="color: #98fb98;"> </span>= {
<span style="color: #026DF7;">JsObject</span>(<span style="color: #ffff70;">fields</span> <span style="color: #24BEE3;">map</span> {
(<span style="color: #ffff70;">field</span>: <span style="color: #98fb98;">clazz.Field[T, JsValue, _]</span>) =>
<span style="color: #ffff70;">field</span>.<span style="color: #13ff12;">name</span> -> <span style="color: #ffff70;">field</span>.<span style="color: #13ff12;">get</span>(<span style="color: #ffff70;">t</span>: <span style="color: #026DF7;">T</span>)
})
}
}
}
</pre>
The function shown above implicitly creates Writes for any type T which has an implicit instance of type Fields[T, JsValue, _] (read it like <i>"List of fields of class T along with function to get value of type JsValue for each field"</i>). Now lets define the transformer function, it will be used for serialization of field values:
<pre>
<span style="color: #00ffff;">def</span> <span style="color: #87cefa;">asJsValue</span>[<span style="color: #98fb98;">T : Writes</span>](<span style="color: #eedd82;">v</span> : <span style="color: #98fb98;">T</span>, <span style="color: #eedd82;">annArgs</span> : <span style="color: #98fb98;">Any</span>) : <span style="color: #98fb98;">JsValue </span>= Json.toJson(v)
</pre>
That was the only code needed to bootstrap your mini-serialization framework. Now you can use it. Lets assume you have declarations:
<pre>
<span style="color: #00ffff;">case</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">JquerySocketEvent</span>[<span style="color: #98fb98;">T</span>](<span style="color: #13ff12;">id:</span> <span style="color: #98fb98;">Int</span>, <span style="color: #13ff12;">data:</span> <span style="color: #026DF7;">T</span>, <span style="color: #13ff12;">`type</span><span style="color: #eedd82;">`:</span> <span style="color: #98fb98;">String</span> = <span style="color: #ffa07a;">"message"</span>, <span style="color: #13ff12;">reply:</span> <span style="color: #98fb98;">Boolean</span> = <span style="color: #7fffd4;">false</span>)
<span style="color: #00ffff;">case</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">ChatMessage</span>(<span style="color: #13ff12;">user</span>: <span style="color: #98fb98;">String</span>, <span style="color: #13ff12;">text</span>: <span style="color: #98fb98;">String</span>)
<span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">jquerySocketEventJsFields</span>[<span style="color: #98fb98;">T</span><span style="color: #084EA8;">: Writes</span><span style="color: #ffff70;">]</span> = clazz.allFields[JquerySocketEvent[T], JsValue]('asJsValue)
<span style="color: #00ffff;">implicit</span> <span style="color: #00ffff;">val</span> <span style="color: #87cefa;">chatMessageJsFields</span> = clazz.allFields[ChatMessage, JsValue]('asJsValue)
</pre>
That's it. ... some fun:
<pre>
<span style="color: #00ffff;">val</span> <span style="color: #73ff73;">event</span> = <span style="color: #026DF7;">JquerySocketEvent</span>(id = 1, data = <span style="color: #026DF7;">ChatMessage</span>(<span style="color: #ffa07a;">"Fluttershy"</span>, <span style="color: #ffa07a;">"</span><span style="color: #cdad00; font-weight: bold; text-decoration: underline;"><a href="http://t.co/wZqXBxKn">Yay</a></span><span style="color: #ffa07a;">!"</span>))
<span style="color: #24BEE3;">println</span> (<span style="color: #026DF7;">Json</span>.<span style="color: #24BEE3;">toJson</span>(<span style="color: #73ff73;">event</span>))
</pre>
... prints:
<pre>
{"id":1,"data":{"user":"Fluttershy","text":"<a href="http://t.co/wZqXBxKn">Yay</a>!"},"type":"message","reply":false}
</pre>
That was easy enough. Feel free to use it, re-implement it or implement a more powerful stuff. Macros FTW!
Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com7tag:blogger.com,1999:blog-6273818684831454306.post-553312670084831092012-08-25T17:45:00.001+03:002012-09-04T22:49:45.507+03:00Kiama & macroHere is a quick and dirty example of using <a href="http://code.google.com/p/kiama/">kiama</a> along with <a href="http://www.akshaal.info/2012/08/scala-210-annotated-fields-macro.html">the fields macro</a>.
<pre>
<span style="color: #00ffff;">import</span> annotated.{ Field => AnnField, Fields => AnnFields }
<span style="color: #00ffff;">object</span> <span style="color: #eedd82;">pp</span> {
<span style="color: #00ffff;">private</span> <span style="color: #00ffff;">object</span> <span style="color: #eedd82;">kpp</span> <span style="color: #00ffff;">extends</span> <span style="color: #084EA8;">org.kiama.output.PrettyPrinter</span>
<span style="color: #00ffff;">import</span> kpp._
<span style="color: #00ffff;">private</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">anyToDoc</span>(<span style="color: #ffff70;">any</span> : <span style="color: #98fb98;">Any</span>) : <span style="color: #98fb98;">Doc </span>=
<span style="color: #ffff70;">any</span> <span style="color: #00ffff;">match</span> {
<span style="color: #00ffff;">case</span> <span style="color: #eedd82;">song</span> : <span style="color: #026DF7;">Song</span><span style="color: #98fb98;"> => </span><span style="color: #24BEE3;">annotatedToDoc</span>(<span style="color: #ffa07a;">"Song"</span>, <span style="color: #73ff73;">song</span>, <span style="color: #73ff73;">songFields</span>)
<span style="color: #00ffff;">case</span> <span style="color: #eedd82;">artist</span> : <span style="color: #026DF7;">Artist</span><span style="color: #98fb98;"> => </span><span style="color: #24BEE3;">annotatedToDoc</span>(<span style="color: #ffa07a;">"Artist"</span>, <span style="color: #73ff73;">artist</span>, <span style="color: #73ff73;">artistFields</span>)
<span style="color: #00ffff;">case</span> <span style="color: #eedd82;">comp</span> : <span style="color: #026DF7;">Compilation</span><span style="color: #98fb98;"> => </span><span style="color: #24BEE3;">annotatedToDoc</span>(<span style="color: #ffa07a;">"Compilation"</span>, <span style="color: #73ff73;">comp</span>, <span style="color: #73ff73;">compilationFields</span>)
<span style="color: #00ffff;">case</span> <span style="color: #eedd82;">job</span> : <span style="color: #026DF7;">UploaderJob</span><span style="color: #98fb98;"> => </span><span style="color: #24BEE3;">annotatedToDoc</span>(<span style="color: #ffa07a;">"Job"</span>, <span style="color: #73ff73;">job</span>, <span style="color: #73ff73;">uploaderJobFields</span>)
<span style="color: #00ffff;">case</span> <span style="color: #eedd82;">map</span> : <span style="color: #084EA8;">Map[_, _]</span><span style="color: #98fb98;"> =></span>
<span style="color: #24BEE3;">list</span>(<span style="color: #73ff73;">map</span>.<span style="color: #24BEE3;">iterator</span>.<span style="color: #24BEE3;">toList</span>,
prefix = <span style="color: #ffa07a;">"Map"</span>,
elemToDoc = {
(<span style="color: #ffff70;">pair</span> : <span style="color: #98fb98;">(Any, Any)</span>) =>
<span style="color: #24BEE3;">anyToDoc</span>(<span style="color: #ffff70;">pair</span>.<span style="color: #13ff12;">_1</span>) <> <span style="color: #ffa07a;">" -> "</span> <> <span style="color: #24BEE3;">nest</span>(<span style="color: #24BEE3;">anyToDoc</span>(<span style="color: #ffff70;">pair</span>.<span style="color: #13ff12;">_2</span>))
})
<span style="color: #00ffff;">case</span> <span style="color: #eedd82;">seq</span> : <span style="color: #084EA8;">Seq[_]</span><span style="color: #98fb98;"> =></span>
<span style="color: #24BEE3;">list</span>(<span style="color: #73ff73;">seq</span>.<span style="color: #24BEE3;">toList</span>, prefix = <span style="color: #ffa07a;">"Sequence"</span>, elemToDoc = anyToDoc)
<span style="color: #00ffff;">case</span> <span style="color: #eedd82;">_</span> => <span style="color: #24BEE3;">value</span>(<span style="color: #ffff70;">any</span>)
}
<span style="color: #00ffff;">private</span> <span style="color: #00ffff;">def</span> <span style="color: #87cefa;">annotatedToDoc</span>[<span style="color: #98fb98;">T <: </span><span style="color: #026DF7;">AnyRef</span>](<span style="color: #ffff70;">name</span> : <span style="color: #98fb98;">String</span>, <span style="color: #ffff70;">t</span> : <span style="color: #026DF7;">T</span>, <span style="color: #ffff70;">fields</span> : <span style="color: #98fb98;">AnnFields[T, FieldArgs]</span>) : <span style="color: #98fb98;">Doc </span>= {
<span style="color: #24BEE3;">list</span>(<span style="color: #ffff70;">fields</span>,
prefix = <span style="color: #ffff70;">name</span>,
elemToDoc = {
(<span style="color: #ffff70;">f</span> : <span style="color: #98fb98;">AnnField[T, FieldArgs]</span>) =>
<span style="color: #ffff70;">f</span>.<span style="color: #13ff12;">name</span> <> <span style="color: #ffa07a;">" = "</span> <> <span style="color: #24BEE3;">anyToDoc</span>(<span style="color: #ffff70;">f</span>.<span style="color: #13ff12;">get</span>(<span style="color: #ffff70;">t</span>))
})
}
<span style="color: #00ffff;">def</span> <span style="color: #87cefa;">apply</span>(<span style="color: #ffff70;">any</span> : <span style="color: #98fb98;">Any</span>) : <span style="color: #98fb98;">String </span>= <span style="color: #24BEE3;">pretty</span>(<span style="color: #24BEE3;">anyToDoc</span>(<span style="color: #ffff70;">any</span>))
}
</pre>
pp (uploaderJob) easily prints data like this:
<pre>
Job(
artistMap = Map(
KeyRef(1x) -> Artist(
handle = Tester2,
marks = Set(),
id = None,
name = None,
website = None,
country = None,
location = None),
KeyRef(2u) -> Artist(
handle = Tester,
marks = Set(),
id = None,
name = None,
website = None,
country = None,
location = None)),
songMap = Map(
KeyRef(6t) -> Song(
relativePath = Path(test7.mp3),
title = test7,
artistRefs = Set(KeyRef(2u)),
tags = Set(),
id = None,
sourceId = None,
mixSongId = None,
year = Some(1999)),
KeyRef(5c) -> Song(
relativePath = Path(test6.mp3),
title = test6,
artistRefs = Set(KeyRef(2u)),
tags = Set(),
id = None,
sourceId = None,
mixSongId = None,
year = Some(1999)),
KeyRef(9i) -> Song(
relativePath = Path(test3.mp3),
title = test3,
artistRefs = Set(KeyRef(1x)),
tags = Set(),
id = None,
sourceId = Some(4),
mixSongId = None,
year = None),
KeyRef(3w) -> Song(
relativePath = Path(test5.mp3),
title = test5,
artistRefs = Set(KeyRef(2u)),
tags = Set(),
id = None,
sourceId = None,
mixSongId = None,
year = Some(1999)),
KeyRef(7l) -> Song(
relativePath = Path(test.mp3),
title = test,
artistRefs = Set(),
tags = Set(),
id = None,
sourceId = None,
mixSongId = None,
year = None),
KeyRef(8f) -> Song(
relativePath = Path(test2.mp3),
title = test2,
artistRefs = Set(),
tags = Set(),
id = None,
sourceId = None,
mixSongId = None,
year = None),
KeyRef(4p) -> Song(
relativePath = Path(test4.mp3),
title = test4,
artistRefs = Set(KeyRef(2u)),
tags = Set(),
id = None,
sourceId = None,
mixSongId = None,
year = Some(1999)),
compilationMap = Map(
KeyRef(11x) -> Compilation(
title = Compo,
songRefs = Sequence(KeyRef(6t)),
marks = Set(),
year = Some(1999),
cdOrSide = Some(B)),
KeyRef(10g) -> Compilation(
title = Compo,
songRefs = Sequence(KeyRef(3w), KeyRef(4p), KeyRef(5c)),
marks = Set(),
year = Some(1999),
cdOrSide = Some(A))))
</pre>
<ad></ad>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6273818684831454306.post-90844004484110500612012-08-18T21:14:00.001+03:002012-09-04T22:47:18.928+03:00Scala 2.10: annotated fields macroHere is a short example of how one can leverage <a href="http://docs.scala-lang.org/sips/pending/self-cleaning-macros.html">SIP-16</a> introduced in Scala-2.10.<br>
(The source code you will find below is expected to be compiled on Scala 2.10-M7. Note, that -M6 provides a slightly different set of API for macro.)
<br><br>
Lets define a macro that makes it possible to traverse value fields of a (case) class. First, we import what we will use:
<pre>
<span style="color: #00ffff;">import</span> language.experimental.macros
<span style="color: #00ffff;">import</span> scala.reflect.macros.Context
<span style="color: #00ffff;">import</span> scala.annotation.Annotation
</pre>
The macros, we are implementing, will be located in 'annotated' object since Scala allows usage of type aliases inside object (unlike package namespace).
<pre>
<span style="color: #00ffff;">object</span> <span style="color: #eedd82;">annotated</span> {
</pre>
Any field belongs to a class (denoted as I). An annotated field might have useful information given by arguments on annotation. Type of the annotation arguments is denoted as A. Here is the definition of the Field class:
<pre>
<span style="color: #ff7f24;">/**</span><span style="color: #ff7f24;">
* An object of this class represents an annotated field.
* @tparam I type of class the field belongs to
* @tparam A type of annotation arguments (TupleX or None)
* @param name name of the field
* @param get function that returns field value of an instance given as argument to the function
* @param args list of arguments to the annotation found on the field
*/</span>
<span style="color: #00ffff;">case</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Field</span>[<span style="color: #98fb98;">I <: </span><span style="color: #026DF7;">AnyRef</span>, <span style="color: #98fb98;">A <: </span><span style="color: #026DF7;">Product</span>](<span style="color: #13ff12;">name</span> : <span style="color: #98fb98;">String</span>, <span style="color: #13ff12;">get</span> : <span style="color: #084EA8;">I => Any</span>, <span style="color: #13ff12;">args</span> : <span style="color: #026DF7;">A</span>)
</pre>
Here is the type alias to save some typing:
<pre>
<span style="color: #ff7f24;">/**</span><span style="color: #ff7f24;">
* List of fields belonging to the given type.
* @tparam I Owner of fields
* @tparam A type of annotation arguments (TupleX or None)
*/</span>
<span style="color: #00ffff;">type</span> <span style="color: #98fb98;">Fields</span>[I <: <span style="color: #026DF7;">AnyRef</span>, A <: <span style="color: #026DF7;">Product</span>] = <span style="color: #98fb98;">List[Field[I, A]]</span>
</pre>
That is how our macro is supposed to be seen by developers (i.e. it is supposed to be seen as an ordinary function):
<pre>
<span style="color: #ff7f24;">/**</span><span style="color: #ff7f24;">
* Macro which inspects class 'I' and returns a list of fields annotated with annotation 'Ann'.
* @tparam Ann search for field with this annotation
* @tparam Args type of arguments in the annotation (TupleX or None)
* @tparam I type of class to scan for annotated fields
*/</span>
<span style="color: #00ffff;">def</span> <span style="color: #87cefa;">fields</span>[<span style="color: #98fb98;">Ann <: </span><span style="color: #026DF7;">Annotation</span>, <span style="color: #98fb98;">Args <: </span><span style="color: #026DF7;">Product</span>, <span style="color: #98fb98;">I <: </span><span style="color: #026DF7;">AnyRef</span>] = macro <span style="color: #24BEE3;">fieldsImpl</span>[<span style="color: #026DF7;">Ann</span>, <span style="color: #026DF7;">Args</span>, <span style="color: #026DF7;">I</span>]
</pre>
Finally, here is the implementation of the macro itself. The implementation is called by the scala compiler whenever it sees 'fields' macro:
<pre>
<span style="color: #ff7f24;">/**</span><span style="color: #ff7f24;">
* Implementation of the fields macro.
*/</span>
<span style="color: #00ffff;">def</span> <span style="color: #87cefa;">fieldsImpl</span>[<span style="color: #98fb98;">AnnTT <: </span><span style="color: #026DF7;">Annotation</span><span style="color: #98fb98;"> </span><span style="color: #ffff70;">: c.AbsTypeTag</span>,
<span style="color: #98fb98;">Args <:</span> <span style="color: #026DF7;">Product</span> <span style="color: #ffff70;">: c.AbsTypeTag</span>,
<span style="color: #98fb98;">ITT <:</span> <span style="color: #026DF7;">AnyRef</span> <span style="color: #ffff70;">: c.AbsTypeTag</span>](<span style="color: #ffff70;">c</span> : <span style="color: #084EA8;">Context</span>) : <span style="color: #084EA8;">c.Expr[Fields[ITT, Args]]</span> = {
</pre>
("Args <: Product : c.AbsTypeTag" means "type Args is a subtype of type Product and there is an implicit value of type c.AbsTypeTag[Args]")<br>
Note that here and further below we use types (like AbsTypeTag) which are from the context 'c'. That is a compilation context of the application which the scala compiler will construct for the source code where the macro invocation is faced (not exactly but..).<br>
<br>
Now lets import types and values (like Select, Ident, newTermName) from the universe of the application the macro is currently used in:
<pre>
<span style="color: #00ffff;">import</span> c.universe._
</pre>
Lets materialize some types as objects for further manipulation:
<pre>
<span style="color: #00ffff;">val</span> <span style="color: #73ff73;">instanceT</span> = <span style="color: #24BEE3;">implicitly</span>[<span style="color: #026DF7;">c.AbsTypeTag</span>[ITT]].<span style="color: #24BEE3;">tpe</span>
<span style="color: #00ffff;">val</span> <span style="color: #73ff73;">annT</span> = <span style="color: #24BEE3;">implicitly</span>[<span style="color: #026DF7;">c.AbsTypeTag</span>[AnnTT]].<span style="color: #24BEE3;">tpe</span>
</pre>
Now, some real action: get annotated fields. Note that hasAnnotation doesn't work for a reason I don't know...
<pre>
<span style="color: #00ffff;">val</span> <span style="color: #73ff73;">annSymbol</span> = <span style="color: #73ff73;">annT.typeSymbol</span>
<span style="color: #00ffff;">val</span> <span style="color: #73ff73;">fields</span> = <span style="color: #73ff73;">instanceT</span>.<span style="color: #24BEE3;">members</span> <span style="color: #24BEE3;">filter</span> (<span style="color: #ffff70;">member</span> => <span style="color: #ffff70;">member</span>.<span style="color: #24BEE3;">getAnnotations</span>.<span style="color: #24BEE3;">exists</span>(<span style="color: #ffff70;">_</span>.<span style="color: #24BEE3;">atp</span> == <span style="color: #73ff73;">annT</span>))
</pre>
It is convenient to have a helper function. This function will fold given expression sequence into a new expression that creates List of expressions at runtime ;-)
<pre>
<span style="color: #00ffff;">def</span> <span style="color: #87cefa;">foldIntoListExpr</span>[<span style="color: #98fb98;">T</span> <span style="color: #ffff70;">: c.AbsTypeTag</span>](<span style="color: #ffff70;">exprs</span> : <span style="color: #084EA8;">Iterable[c.Expr[T]]</span>) : <span style="color: #084EA8;">c.Expr[List[T]]</span> =
<span style="color: #ffff70;">exprs</span>.<span style="color: #24BEE3;">foldLeft</span>(reify { Nil : List[T] }) {
(<span style="color: #ffff70;">accumExpr</span>, <span style="color: #ffff70;">expr</span>) =>
reify { expr.splice :: accumExpr.splice }
}
</pre>
For each field, construct expression that will instantiate Field object at runtime:
<pre>
<span style="color: #00ffff;">val</span> <span style="color: #73ff73;">fieldExprs</span> =
<span style="color: #00ffff;">for</span> (field <- <span style="color: #73ff73;">fields</span>)<span style="color: #24BEE3;"> yield</span> {
<span style="color: #00ffff;">val</span> <span style="color: #eedd82;">argTrees</span> = field.getAnnotations.find(_.atp == annT).get.args
<span style="color: #00ffff;">val</span> <span style="color: #eedd82;">name</span> = field.name.toString.trim <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">Why is there a space at the end of field name?!
</span> <span style="color: #00ffff;">val</span> <span style="color: #eedd82;">nameExpr</span> = c literal name
<span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">Construct arguments list expression
</span> <span style="color: #00ffff;">val</span> <span style="color: #eedd82;">argsExpr</span> =
<span style="color: #00ffff;">if</span> (argTrees.isEmpty) {
c.Expr [Args] (Select(Ident(newTermName(<span style="color: #ffa07a;">"scala"</span>)), newTermName(<span style="color: #ffa07a;">"None"</span>)))
} <span style="color: #00ffff;">else</span> {
<span style="color: #00ffff;">val</span> <span style="color: #eedd82;">tupleConstTree</span> = Select(Select(Ident(newTermName (<span style="color: #ffa07a;">"scala"</span>)),
newTermName(s<span style="color: #ffa07a;">"Tuple${argTrees.size}"</span>)),
newTermName(<span style="color: #ffa07a;">"apply"</span>))
c.Expr [Args] (Apply (tupleConstTree, argTrees))
}
<span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">Construct expression (x : $I) => x.$name
</span> <span style="color: #00ffff;">val</span> <span style="color: #eedd82;">getFunArgTree</span> = ValDef(Modifiers(), newTermName(<span style="color: #ffa07a;">"x"</span>), TypeTree(instanceT), EmptyTree)
<span style="color: #00ffff;">val</span> <span style="color: #eedd82;">getFunBodyTree</span> = Select(Ident(newTermName(<span style="color: #ffa07a;">"x"</span>)), newTermName(name))
<span style="color: #00ffff;">val</span> <span style="color: #eedd82;">getFunExpr</span> = c.Expr[ITT => Any](Function(List(getFunArgTree), getFunBodyTree))
reify {
Field[ITT, Args](name = nameExpr.splice, get = getFunExpr.splice, args = argsExpr.splice)
}
}
</pre>
By this moment, value fieldExprs will contain something like
<pre>
List (
reify {Field ('field1', (x => x.field1), (..)},
reify {Field ('field2', (x => x.field2), (..)}
)
</pre>
(where (..) are arguments of annotaiton on that field)<br>
Now we have to lift List construction into expression and we're done!
<pre>
<span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">Construct expression list like field1 :: field2 :: Field3 ... :: Nil
</span> <span style="color: #24BEE3;">foldIntoListExpr</span>(<span style="color: #73ff73;">fieldExprs</span>)
}
}
</pre>
<br>
And finally lets have some fun. Lets test it in REPL! (beware that scala macros are supposed to be compiled before they are used)<br>
<pre>
scala> <span style="color: #00ffff;">type</span> <span style="color: #98fb98;">FormatFun</span> = <span style="color: #084EA8;">Any => Any</span>
defined type alias FormatFun
scala> <span style="color: #00ffff;">type</span> <span style="color: #98fb98;">PrettyArgs</span> = <span style="color: #98fb98;">(Option[String], FormatFun)</span>
defined type alias PrettyArgs
scala> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Pretty</span>(<span style="color: #13ff12;">aka</span> : <span style="color: #98fb98;">Option[String]</span> = None, <span style="color: #13ff12;">format</span> : <span style="color: #084EA8;">FormatFun</span> = identity) <span style="color: #00ffff;">extends</span> <span style="color: #084EA8;">annotation.StaticAnnotation</span>
defined class Pretty
</pre>
<pre>
scala> :paste
// Entering paste mode (ctrl-D to finish)
<span style="color: #00ffff;">def</span> <span style="color: #87cefa;">pp</span>[<span style="color: #98fb98;">X <: </span><span style="color: #026DF7;">AnyRef</span>](<span style="color: #ffff70;">fields</span> : <span style="color: #026DF7; ">annotated</span><span style="color: #026DF7;">.Fields</span><span style="color: #98fb98;">[X, PrettyArgs]</span>)(<span style="color: #ffff70;">x</span> : <span style="color: #026DF7;">X</span>) = {
<span style="color: #ffff70;">fields</span> <span style="color: #24BEE3;">map</span> {
<span style="color: #00ffff;">case</span> <span style="color: #eedd82;">annotated.</span><span style="color: #24BEE3;">Field</span>(<span style="color: #eedd82;">fieldName</span>, <span style="color: #eedd82;">get</span>, (<span style="color: #eedd82;">akaOpt</span>, <span style="color: #eedd82;">fmtFun</span>)) =>
<span style="color: #00ffff;">val</span> <span style="color: #eedd82;">name</span> = fieldName.<span style="color: #24BEE3;">replaceAll</span>(<span style="color: #ffa07a;">"([A-Z][a-z]+)"</span>, <span style="color: #ffa07a;">" $1"</span>).<span style="color: #24BEE3;">toLowerCase</span>.<span style="color: #24BEE3;">capitalize</span>
<span style="color: #00ffff;">val</span> <span style="color: #eedd82;">aka</span> = akaOpt <span style="color: #24BEE3;">map</span> (<span style="color: #ffa07a;">" (aka "</span> <span style="color: #24BEE3;">+</span> _ <span style="color: #24BEE3;">+</span> <span style="color: #ffa07a;">")"</span>) <span style="color: #24BEE3;">getOrElse</span> <span style="color: #ffa07a;">""</span>
<span style="color: #00ffff;">val</span> <span style="color: #eedd82;">value</span> = fmtFun(get(x))
s<span style="color: #ffa07a;">"$name$aka: $value"</span>
} <span style="color: #24BEE3;">mkString</span> <span style="color: #ffa07a;">"\n"</span>
}
// Exiting paste mode, now interpreting.
pp: [X <: AnyRef](fields: info.akshaal.radio.uploader.annotated.Fields[X,(Option[String], Any => Any)])(x: X)String
</pre>
<br>
Still no macro was used. Now here it comes. First, we define case class. Next, we gather annotated fields in the definition of personPrettyFields. When you run it in REPL, it is quite important to use :paste, otherwise annotation of the case class will be lost because subtypes of StaticAnnotation are visible during compilation only (REPL calls a new scala compiler for each expression reusing binary classes compiled during previous steps). So:
<pre>
scala> :paste
// Entering paste mode (ctrl-D to finish)
<span style="color: #00ffff;">case</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Person</span>(
<span style="color: #13ff12;">id</span> : <span style="color: #98fb98;">Int</span>,
<span style="color: #13ff12;">@Pretty</span>(aka = Some(<span style="color: #ffa07a;">"nickname"</span>)) name : <span style="color: #98fb98;">String</span>,
<span style="color: #13ff12;">@Pretty</span> firstName : <span style="color: #98fb98;">String</span>,
<span style="color: #13ff12;">@Pretty</span>(None, format = _.toString.toUpperCase) secondName : <span style="color: #98fb98;">String</span>,
<span style="color: #13ff12;">@Pretty</span>(None, format = { <span style="color: #00ffff;">case</span> <span style="color: #eedd82;">x</span> : <span style="color: #98fb98;">Option[_] => x </span><span style="color: #eedd82;">getOrElse</span> <span style="color: #ffa07a;">""</span> <span style="color: #eedd82;">}</span>) twitter : <span style="color: #98fb98;">Option[String]</span>)
<span style="color: #00ffff;">val</span> <span style="color: #13ff12;">personPrettyFields</span> = <span style="color: #73ff73;">annotated</span>.<span style="color: #24BEE3;">fields</span>[<span style="color: #98fb98;">Pretty</span>, <span style="color: #98fb98;">PrettyArgs</span>, <span style="color: #98fb98;">Person</span>]
// Exiting paste mode, now interpreting.
defined class Person
personPrettyFields: List[info.akshaal.radio.uploader.annotated.Field[Person,(Option[String], Any => Any)]] =
List(Field(name,<function1>,(Some(nickname),<function1>)),
Field(firstName,<function1>,(None,<function1>)),
Field(secondName,<function1>,(None,<function1>)),
Field(twitter,<function1>,(None,<function1>)))
</pre>
(I've aligned the output of REPL a bit..)<br>
Lets check field names:
<pre>
scala> personPrettyFields <span style="color: #24BEE3;">map</span> (field => field.<span style="color: #24BEE3;">name</span>)
res0: List[String] = List(name, firstName, secondName, twitter)
</pre>
Here are getters of each field:
<pre>
scala> personPrettyFields <span style="color: #24BEE3;">map</span> (_.<span style="color: #24BEE3;">get</span>)
res1: List[Person => Any] = List(<function1>, <function1>, <function1>, <function1>)
</pre>
Now, lets create a Person object:
<pre>
scala> <span style="color: #00ffff;">val</span> <span style="color: #13ff12;">person1</span> = <span style="color: #026DF7;">Person</span>(1, <span style="color: #ffa07a;">"akshaal"</span>, <span style="color: #ffa07a;">"Evgeny"</span>, <span style="color: #ffa07a;">"Chukreev"</span>, <span style="color: #026DF7;">Some</span>(<span style="color: #ffa07a;">"https://twitter.com/Akshaal"</span>))
person1: Person = Person(1,akshaal,Evgeny,Chukreev,Some(https://twitter.com/Akshaal))
</pre>
... and a value for each field of this person:
<pre>
scala> personPrettyFields <span style="color: #24BEE3;">map</span> (_.<span style="color: #24BEE3;">get</span> (person1))
res2: List[Any] = List(akshaal, Evgeny, Chukreev, Some(https://twitter.com/Akshaal))
</pre>
Some more objects for more fun:
<pre>
scala> <span style="color: #00ffff;">val</span> <span style="color: #13ff12;">person2</span> = <span style="color: #026DF7;">Person</span>(2, <span style="color: #ffa07a;">"</span><span style="color: #ffa07a;">BillGates</span><span style="color: #ffa07a;">"</span>, <span style="color: #ffa07a;">"Bill"</span>, <span style="color: #ffa07a;">"Gates"</span>, <span style="color: #026DF7;">Some</span>(<span style="color: #ffa07a;">"https://twitter.com/</span><span style="color: #ffa07a;">BillGates</span><span style="color: #ffa07a;">"</span>))
person2: Person = Person(2,BillGates,Bill,Gates,Some(https://twitter.com/BillGates))
scala> <span style="color: #00ffff;">val</span> <span style="color: #13ff12;">persons</span> = List(<span style="color: #13ff12;">person1</span>, <span style="color: #13ff12;">person2</span>)
persons: List[Person] =
List(Person(1,akshaal,Evgeny,Chukreev,Some(https://twitter.com/Akshaal)),
Person(2,BillGates,Bill,Gates,Some(https://twitter.com/BillGates)))
scala> <span style="color: #00ffff;">val</span> <span style="color: #13ff12;">ppPerson</span> = <span style="color: #24BEE3;">pp</span>(personPrettyFields) _
ppPerson: Person => String = <function1>
</pre>
And finally:
<pre>
scala> persons <span style="color: #24BEE3;">map</span> ppPerson <span style="color: #24BEE3;">mkString</span> <span style="color: #ffa07a;">"\n----------------------------\n"</span>
res5: String =
Name (aka nickname): akshaal
First name: Evgeny
Second name: CHUKREEV
Twitter: https://twitter.com/Akshaal
----------------------------
Name (aka nickname): BillGates
First name: Bill
Second name: GATES
Twitter: https://twitter.com/BillGates
</pre>
<br>
That's all ;-)
You will find complete source code along with specs2 specification (with one more example) on the gist: <a href="https://gist.github.com/3388753">https://gist.github.com/3388753</a>
<br>
<h1>No animals were killed.</h1>
<h1>No types were casted.</h1>
<h1>No reflections were used.</h1>
<ad></ad>
Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com1tag:blogger.com,1999:blog-6273818684831454306.post-79255085777980890912010-01-20T13:04:00.003+02:002010-01-20T13:16:09.785+02:00nut & ipponIt was tricky to make nut 2.4.1 work with IPPON Power PRO 1000 using USB interface.<br /><br />Any driver (blazer_usb, megatec_usb) failed with the message:<br />Can't claim USB device [xxxx:yyyy]: could not detach kernel driver from interface 0: Operation not permitted<br /><br />It turned out, that nut came with the broken configuration for udev 150 (on debian). To fix the problem, I commented out all lines in /etc/udev/rules.d/52-nut-usbups.rules, and created a new file with the name /etc/udev/rules.d/46-ippon.rules and the following content:<pre><br />SUBSYSTEM=="usb", ATTR{idVendor}=="0665", ATTR{idProduct}=="5161", MODE="0664", GROUP="nut"</pre><ad></ad><br />This helped. Required product id and vendor id are discovered from the output of lsusb program.<br /><br />PS. The following alias is very useful when configuring something with udev:<br />alias udevinfo="udevadm info -a -n"<br />and it can be used like:<br />udevinfo /dev/sdaAkshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6273818684831454306.post-62216434609220577422009-11-26T14:27:00.003+02:002009-11-26T14:32:14.087+02:00Upgrade of FirefoxAfter apt-get dist-upgrade I got this "Could not initialize the browser's security component. The most likely cause is problems with files in your browser's profile directory. Please check that this directory has no read/write restrictions and your hard disk is not full or close to full. It is recommended that you exit the browser and fix the problem. If you continue to use this browser session, you might see incorrect browser behavior when accessing security features."<br /><br />I tried many possible solutions discovered in internet, but the only thing helped was removing of secmod.db file from my profile directory of firefox. I have no idea what this file is for, but it works. If you are having the same problem, backup your ~/.mozilla directory first before trying this or other solution which involves removing of files.Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6273818684831454306.post-3631944728026534222009-10-02T18:53:00.003+03:002009-10-02T19:09:42.351+03:00Auto-mount with halevthalevt is good piece of software but by default it mounts disks in a way very inconvenient for me - that is mount points are like '/media/disk' '/media/disk-1/ '/media/disk-2' and so on. In order to help myself find disks more easily I've reconfigured halevt and created a script. Now I have /media/Cruzer-d4ba-1 and /media/Cruzer-a5e1-1 mountpoints for my two Sandisk USB sticks. And there are SD_Reader-a6a1-1, SD_Reader-a6a1-2, SD_Reader-a6a1-3 (three partitions) for the SD card I've inserted into a reader. A mountpoint name is composed by concatenating storage model name, short version of storage serial id and partition number. This is done by the following script (~/bin/halevt-mount-helper):<pre>#!/bin/sh<br /><br />STORAGE=`hal-get-property --udi "$1" --key block.storage_device`<br />PARTITION=`hal-get-property --udi "$1" --key volume.partition.number`<br />UUID=`hal-get-property --udi "$STORAGE" --key storage.serial | md5sum | head -c 4`<br />MODEL=`hal-get-property --udi "$STORAGE" --key storage.model | sed 's/ /_/g' | sed 's/^USB_//g'`<br /><br />MPOINT="$MODEL-$UUID-$PARTITION"<br /><br />halevt-mount -u "$1" -p "$MPOINT" -o sync -m 007</pre><ad></ad>The script is used by configuring halevt with the following line instead of the default "halevt:insertion" line in halevt configuration file (/etc/halevt/halevt.xml or ~/.halevt/halevt.xml):<pre> <halevt:insertion exec="halevt-mount-helper $hal.udi$"></pre>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6273818684831454306.post-40638225815693073302009-10-02T14:59:00.003+03:002009-10-02T15:04:06.204+03:00More security with ZSHDon't save commands in history while a secure device is mounted. The mounted device must have .secure file in order to disable history file while the device mounted.<br /><br /><pre>zshaddhistory() {<br /> DIRS=`cat /proc/mounts | rgrep -P '(fuse|ext3|ext2|ext4|fat)' | cut -f2 -d' '`<br /> FLAG=`for dir in ${=DIRS} ; do test -f "$dir/.secure" && echo secure; done`<br /> echo $FLAG | grep secure 2>/dev/null >/dev/null && return -1 || return 0<br />}</pre><ad></ad>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6273818684831454306.post-24680007434733850872009-08-22T17:26:00.002+03:002009-08-22T17:31:49.250+03:00Constructor annotation in Scala 2.8.0It was really hard for me to find any information concerning annotations on default constractor. Finally I discovered that scala accepts the following syntax:<br />class MyClass @Annotation() (val arg : Int) {<br />}<br /><br />It is important that an annotation is followed by (), otherwise parameters of MyClass are parsed as parameters of annotation...<br /><ad></ad>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com2tag:blogger.com,1999:blog-6273818684831454306.post-15875062175857453672009-08-18T19:19:00.005+03:002009-08-18T20:11:39.225+03:00Richfaces & JSF 1.2The problem with Richfaces 3.3.1 and Sun JSF RI is that an exception thrown in action listener is suppressed by Richfaces. I will show why this happens. The following stacktrace shows an order of invocations that takes place when an action listener is called:<pre><br />((1)) at blah.blah.blah.ActionListenerTest.test(ActionListenerTest.java:122)<br />at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)<br />at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)<br />at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)<br />at java.lang.reflect.Method.invoke(Method.java:597)<br />at org.apache.el.parser.AstValue.invoke(AstValue.java:170)<br />at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)<br />at com.sun.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:68)<br />((2)) at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:99)<br />at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)<br />at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:771)<br />at javax.faces.component.UICommand.broadcast(UICommand.java:372)<br />at javax.faces.component.UIData.broadcast(UIData.java:938)<br />((3)) at org.ajax4jsf.component.AjaxViewRoot.processEvents(AjaxViewRoot.java:321)<br />at org.ajax4jsf.component.AjaxViewRoot.broadcastEvents(AjaxViewRoot.java:296)<br />at org.ajax4jsf.component.AjaxViewRoot.processPhase(AjaxViewRoot.java:253)<br />at org.ajax4jsf.component.AjaxViewRoot.processApplication(AjaxViewRoot.java:466)<br />at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:82)<br /></pre><br />I've marked interesting places with ((1)), ((2)) and ((3)). The first interesting method is ((1)) - that is where we throw an unchecked exception. The exception will be catched somewhere between ((1)) and ((2)) and wrapped into the ELException class. Then this exception will be caught in ((2)) as it can be seen here (sources are taken from Sun JSF RI 1.2.12):<pre><br /> public void processAction(ActionEvent actionEvent) throws AbortProcessingException {<br /> if (actionEvent == null) {<br /> throw new NullPointerException();<br /> }<br /><br /> try {<br /> FacesContext context = FacesContext.getCurrentInstance();<br /> ELContext elContext = context.getELContext();<br /> methodExpression.invoke(elContext, new Object[] {actionEvent});<br /> } catch (ELException ee) {<br /> Throwable eeCause = ee.getCause();<br /> if (LOGGER.isLoggable(Level.SEVERE)) {<br /> LOGGER.log(Level.SEVERE,<br /> "severe.event.exception_invoking_processaction"<br /> new Object[]{<br /> eeCause == null ? ee.getClass().getName() : eeCause.getClass().getName(),<br /> methodExpression.getExpressionString(),<br /> actionEvent.getComponent().getId()<br /> });<br /> StringWriter writer = new StringWriter(1024);<br /> if (eeCause == null) {<br /> ee.printStackTrace(new PrintWriter(writer));<br /> } else {<br /> eeCause.printStackTrace(new PrintWriter(writer));<br /> }<br /> LOGGER.severe(writer.toString());<br /> }<br /><br /> throw eeCause == null ? new AbortProcessingException(ee.getMessage(), ee) : new AbortProcessingException(ee.getMessage(), eeCause);<br /> }<br /> }<br /></pre><ad></ad>When the processActio methods catches exception it logs it and wraps exception cause into the AbortProcessingException. Here we come to place ((3)) which catches AbortProcessingException. The following is the source code from RichFaces 3.3.1.GA:<pre><br /> public void processEvents(FacesContext context,<br /> EventsQueue phaseEventsQueue, boolean havePhaseEvents) {<br /> FacesEvent event;<br /> while (havePhaseEvents) {<br /> try {<br /> event = (FacesEvent) phaseEventsQueue.remove();<br /> UIComponent source = event.getComponent();<br /> try {<br /> source.broadcast(event);<br /> } catch (AbortProcessingException e) {<br /> if (_log.isErrorEnabled()) {<br /> UIComponent component = event.getComponent();<br /> String id = null != component ? component<br /> .getClientId(context) : "";<br /> _log.error(<br /> "Error processing faces event for the component "<br /> + id, e);<br /> }<br /> }<br /> } catch (NoSuchElementException e) {<br /> havePhaseEvents = false;<br /> }<br /> }<br /> }<br /></pre> As you can see processEvents catches AbortProcessingException, logs it and does nothing! That is it!<br /><br />I've tried a lot of solutions to solve this, I've tried to solve it with servlets/filters/phase-listeners/action-listeners and so on with no luck! Then I've solved it with last resort - AspectJ. The following aspect does the job perfectly:<pre><br />@Aspect<br />public class RichfacesErrorIntercepterAspect {<br /> @Around("call(* javax.faces.component.UIComponent.broadcast(..)) && within (org.ajax4jsf.component.AjaxViewRoot)")<br /><br /> public void callToBroadcast (final ProceedingJoinPoint thisJoinPoint) throws Throwable<br /> {<br /> try {<br /> thisJoinPoint.proceed ();<br /> } catch (final AbortProcessingException e) {<br /> throw new RuntimeException ("Exception in action listener: " + e.getMessage (), e.getCause ());<br /> }<br /> }<br />}<br /></pre>To weave Richfaces's jar I've used the maven (I use it to build the project anyway):<pre><br /><plugin><br /> <groupId>org.codehaus.mojo</groupId><br /><br /> <artifactId>aspectj-maven-plugin</artifactId><br /><br /> <configuration><br /> <complianceLevel>1.5</complianceLevel><br /> <weaveDependencies><br /> <weaveDependency><br /> <groupId>org.richfaces.framework</groupId><br /> <artifactId>richfaces-impl</artifactId><br /> </weaveDependency><br /> </weaveDependencies><br /> </configuration><br /><br /> <executions><br /> <execution><br /> <goals><br /> <goal>compile</goal><br /> </goals><br /> </execution><br /> </executions><br /></plugin><br /></pre><ad></ad>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com3tag:blogger.com,1999:blog-6273818684831454306.post-68280852958524114352009-08-02T13:24:00.005+03:002009-08-02T14:06:01.600+03:00Richfaces or Trinidad with FaceletsI upgraded existing project from Java 1.4 to Java 1.5, JSF 1.1 to JSF 1.2, myfaces to sun ri... and decided to leverage a framework providing AJAX for JSF. The first I tried was richfaces. But it worked unstable and I spent 2 days trying to find a reason for it. Then I tried to use trinidad. It was the same. The framework worked but very unstable. For example. I opened a jsf page, if I clicked on a ajaxfied button just immediately after page appeared, then button worked OK. But if I clicked on the button after a while, then the button didn't work, the relevant page part was not updated! It looked like a magick in work. Then I noticed a very strange message which I noticed long time ago but didn't pay any attention to it. The message was "INFO: Facelet[/page/blah.xhtml] was modified @ 14:23:24 AM, flushing component applied...". A quick investigation revealed a root of my problem! It turned out that time in a virtual machine I used as a place for application server was 3 hours less then current time! And so file creation time of files in WAR-file was greater than time in the virtual machine. It looked like facelets framework had some strange algorithm based on current time to reload modified files (and flush components tree). Having set facelets.REFRESH_PERIOD context parameter in web.xml I solved the problem. Both richfaces and trinidad worked fine after that.<ad></ad>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6273818684831454306.post-87549804396774016222009-07-06T11:31:00.003+03:002009-07-06T12:55:33.675+03:00Simple DSL in ScalaRecently I started to use Scala for my hobby-project.I had heard that Scala made it possible to write a code in a way that it looked like a DSL embedded inthe Scala language itself. So I decided to try this feature myself. I needed some concise and convenient API to schedule messages for actors. The following is what I ended up with:<pre><br />final class TimeSpec[T] (number : Long, action : Long => T) {<br /> def nanoseconds = action (number)<br /> def microseconds = action (number * 1000L)<br /> def miliseconds = action (number * 1000L * 1000L)<br /> def seconds = action (number * 1000L * 1000L * 1000L)<br /> def minutes = action (number * 1000L * 1000L * 1000L * 60L)<br /> def hours = action (number * 1000L * 1000L * 1000L * 60L * 60L)<br /> def days = action (number * 1000L * 1000L * 1000L * 60L * 60L * 24L)<br />}<br /><br />final class Trigger (actor : MyActor, payload : Any) {<br /> def in (number : Long) = new TimeSpec[Unit] (number, scheduleIn)<br /> def every (number : Long) = new TimeSpec[Unit] (number, scheduleEvery)<br /><br /> private def scheduleIn (nanos : Long) = Scheduler.inNano (actor, payload, nanos)<br /> private def scheduleEvery (nanos : Long) = Scheduler.everyNano (actor, payload, nanos)<br />}<br /><br />final class ActorSchedule (actor : MyActor) {<br /> def payload (payload : Any) = new Trigger (actor, payload)<br />}<br /><br />trait MyActor ..... {<br /> protected val schedule = new ActorSchedule (this)<br /> ....<br />}</pre><ad></ad><br /><br />This code made it possible to schedule messages in a natural way, like:<pre><br />object TestActor extends MyActor {<br /> schedule payload `Hi in 10 nanoseconds<br /><br /> schedule payload `HowAreYou every 5 seconds<br /><br /> schedule payload `Bye in 5 days<br /><br /> def act () = {<br /> case `Hi => println ("Hello!")<br /> case `HowAreYou => println ("I am fine")<br /> case `Bye => println ("Bye-bye")<br /> }<br />}</pre><br />The idea is that schedule is an object of class ActorSchedule. This class has method payload which takes a payload object as its argument. So "schedule payload `Hi" is actually an invocation "schedule.payload(`Hi)". This invocation will create an object of class Trigger. Trigger class has two public methods - in(Long) and every(Long). Because we cannot do anything until a time unit is given, we create an object of TimeSpec class passing to it a method (scheduleIn or scheduleEvery) that is to be run with number of nanoseconds when one of TimeSpec's methods is called. I think this API is concise enough with only small efforts taken to implement it.<ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6273818684831454306.post-8160793863540759232009-03-22T13:49:00.004+02:002009-03-22T14:41:01.532+02:00CeBootLin - Linux autoloader for WinCE on Loox 5XX (560/550)Here is the "bootloader" for wince to boot linux automatically on startup of PDA. It is not real bootloader because it has nothing to do with boot sectors, it is just a wince program which is able to boot linux as soon as possible. I have implemented it in this way because I didn't want to brick my PDA meddling with boot sectors or something. Also I wanted to have a way to skip loading of linux and let wince load itself. So here we are. It works. The code is based on haret (thanks guys!) but I cut off the parts I not used. Because the laoder uses hardware registers (GPIO/CPLD for leds and keybaord) of Fujitsu Siemens Loox N560/C550, it will not work for other PDAs. When CeBootLin is installed and PDA is turned on, wince begins boot process loading applications defined under the HKEY_LOCAL_MACHINE\init registery key. This way it loads CeBootLin. CeBootLin waits for 1 second, blinking with keyboard led. During the keyboard blinking, user can press any button to stop CeBootLin from loading Linux. If no button has been pressed during keyboard blinking, CeBootLin will search for \CeBootLin\default.txt and use this haret script to load Linux.<br /><br />So, in essence, you should complete the following steps in order to install CeBootLin:<br />1. <a href="http://downloads.akshaal.info/linux-n560-c550/CeBootLin-1.zip?attredirects=0">Download</a> CeBootLin.<ad2></ad2><br />2. Unpack the downloaded archive into the PDA root. The CeBootLin.exe must be reachable with the path \CeBootLin\CeBootLin.exe.<br />3. Place default.txt under the \CeBootLin directory. The default txt might looks like this (if the Andorid is what you are going to load with CeBootLin):<pre><br />set MTYPE 1454<br />set KERNEL "\CeBootLin\zImage"<br />set CMDLINE "root=179:3 mem=62M rootdelay=3 boot_delay=0 init=/init console=tty0 fbcon=rotate:0 androidboot.console=tty0 android.checkjni=1"<br />set RAMADDR 0xA0200000<br />bootlinux<br /></pre><br />4. Place zImage under the directory \CeBootLin\.<br /><a href="http://picasaweb.google.com/lh/photo/11wJSVlZKWbWAN3DhaJXSw?authkey=Gv1sRgCMTt-MKs5cTh6wE&feat=embedwebsite"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdZkRMSUr62jBL1ImUfJijSiLy1sAyMvuJweLyHjt__DZsgJGu3IqK5XugDSAFD9l-l4zwYkF-8SaGBN1MbhWh_3YJ23B4ZGo3nbAyIhIdP1IlmqViNyvkn3I-d-Vw9pPYk3_yyxivlpuZ/s400/CeBootEdit-1.png" /></a><br />5. Modify HKEY_LOCAL_MACHINE\init adding Launch82 ="CeBootLin.exe" and Depend82 = 14 00.<br /><a href="http://picasaweb.google.com/lh/photo/00DSupXz9qiOXs43h5f5cA?authkey=Gv1sRgCMTt-MKs5cTh6wE&feat=embedwebsite"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2MZwhAf19ZPkhV9j-m4gtQF_cMBrMeznzwFzLQii9YHqoEQLPJ2QIoPoWIgLtUmbsYoQGmC8xRLQRHzTwy9OFEujuzUHD8VnPJh0Q5ktDlcnN6x3wrJRYUCU8DU2qXOSmE9Yy5YE0LFZA/s400/CeBootEdit-3.png" /></a><br /><a href="http://picasaweb.google.com/lh/photo/0Rc2C1G2xiQKk5R0RmvaZg?authkey=Gv1sRgCMTt-MKs5cTh6wE&feat=embedwebsite"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3JQlgO-EaIaUIakTQIDY5USc81MrvtjKqNvlzHD-V4FGNw4h5HspvDoC7xL1k1TpHvhnt0kIXfuMvYQtXBIvRDFsJ7oEhjdG9WarTWBdSnylug8LHyxB2I9zGXyw2-HDaCYjm6M92cFyE/s400/CeBootEdit-4.png" /></a><br />6. Modify HKEY_LOCAL_MACHINE\Loader\SystemPath adding a new directory \CeBootLin\ to the multi-string list.<br /><a href="http://picasaweb.google.com/lh/photo/hbLfmcNrlr6RpUPvLX_-5A?authkey=Gv1sRgCMTt-MKs5cTh6wE&feat=embedwebsite"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpiM0VaWjfzE7Bi5tf1yqRESsPgvTNPywQqJID1Kra0bws22Ch58GrCupZo-lPHO4ygmXhyphenhyphenrjO6ABQTE0C08ywidwkle-WHwSpiDRAOFGGc8L2VSK-LJjVQ85oNe4Z2EHuMOHiCuhape5N/s400/CeBootEdit-2.png" /></a><br />7. Wait for 5 minutes (WinCE needs time to persist changes to registry).<br />8. Feel free to reboot your PDA<br /><br />To test that CeBootLin is able to boot linux at all, run CeBootLin.exe manually.<br /><br />It looks little bit complicated but later, setup program might be created to ship automatically bootable Andorid on Loox550. But before, Andorid must be polished.<br /><br /><a href="http://downloads.akshaal.info/linux-n560-c550/CeBootLin-1.tar.gz?attredirects=0">Here</a> is the source code of CeBootLinux. CeBootLinux is licensed with GNU GPL.<ad></ad>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com10tag:blogger.com,1999:blog-6273818684831454306.post-15534963780288953562009-03-15T16:01:00.004+02:002010-01-26T22:49:23.339+02:00Pictures of Linux and Android on Fujitsu-Siemens Loox N560<a href="http://picasaweb.google.com/lh/photo/CUrNwUv_XICGqKQKeMx6rA?authkey=Gv1sRgCMTt-MKs5cTh6wE&feat=embedwebsite"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHPipxiFLXQ3xA743U47IXU9nsVCefgZ6PkBymR9Slh8R4zp_OxWYogjirzfPkFNXwxAcVaRG24YK41gGn_b5Teiz5Q4c2kHRe22nVyG4nUhuketzY80Eq-vN05xt43ypMj55bmjR3IFHb/s400/n560-1s.jpg" /></a><br />Today the desteny of WM5 is only to be replaced with Linux<br /><br /><a href="http://picasaweb.google.com/lh/photo/Wdt450DQpEcjKa1aIu3iUA?authkey=Gv1sRgCMTt-MKs5cTh6wE&feat=embedwebsite"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2Le3lTgew4AIitvwoxRLGr5jN4qeqbuZLlD1pfpZjH2BWk1bnmtPjRGY06TPgop4floQgz4d7T0ypVo1CidHyzvsew5TQgFC8V8wNPn-HHxSo6nFLBD4dm8z4x5GjJA66ewNmyK1oqzYQ/s400/n560-2s.jpg" /></a><br />Haret.. all you need is to press Run<br /><br /><a href="http://picasaweb.google.com/lh/photo/LQ7LXZhb1hXw6cwFARC4pg?authkey=Gv1sRgCMTt-MKs5cTh6wE&feat=embedwebsite"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlozCBxeDrqz9830_QbHaFo8LYsPSVMfPVX8OkHm5EDtV4XNzNGyxxvGTiFiSVbnlrNHlfJxFQfIKdcMi8MCdUUhxJ0jFayy5tc3duNbGf0U15jwKKqIhlLjTbujUyze8f-EFzlZAg-dnC/s400/n560-3s.jpg" /></a><br />Android on Loox N560<br /><br /><a href="http://picasaweb.google.com/lh/photo/K2EytIW2FJWybumV11UTRg?authkey=Gv1sRgCMTt-MKs5cTh6wE&feat=embedwebsite"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOvmMjWCSe0-jN7MRxqKGadD47YvQYMYoTeyAp8CLJdSUzrIbDNn2fAt-w-FNAilCIpearZx66_aqIQSVPCGUBG1MbJxtAVqEmt3TIkYW2F-D9XBR1n8pe23RKy5lEFrHZZ4am1KKQH_Rb/s400/n560-4s.jpg" /></a><br /><a href="http://www.akshaal.info/2009/03/install-emdebian-on-arm-device.html">Installation of debian</a> on Loox N560<br /><br /><a href="http://picasaweb.google.com/lh/photo/ReuuEUcxhZ4y-Es7lRGneQ?authkey=Gv1sRgCMTt-MKs5cTh6wE&feat=embedwebsite"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-6d-XniFGV7jx94znOxlRg-IvxPhHIWAdr7EH4bYrhvQcidLbdGgb2h9-J-VokNJLJ-86sDHr0CAoovBf2sLMqwhcVnUTevuzsF6mxGs1pXMAkAGPjn_G7o-G9XIaoZMyog1CoQxiVUMQ/s400/n560-5s.jpg" /></a><ad></ad><br /><a href="http://www.akshaal.info/2009/03/install-emdebian-on-arm-device.html">Installation of debian</a> on Loox N560Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com21tag:blogger.com,1999:blog-6273818684831454306.post-45732315800437811542009-03-15T15:05:00.003+02:002009-03-15T15:28:00.981+02:00Memory tester for Loox N560/C550Recently I've created a way to test memory for defects on Fujitsu-Siemens Loox N560/C550. Only one who upgraded (or wants to upgrade) PDA's memory from 64M to 128M needs this utility. Using this "util" it is possible to test memory immediately right after memory has been upgraded, without re-flushing WM5/WM6.<br /><br />So do the following to test your PDA's memory:<br />1. Download either <a href="http://downloads.akshaal.info/other-soft-for-pda">LooxMem128-v0.zip</a> (to test 128Mb of memory) or <a href="http://downloads.akshaal.info/other-soft-for-pda">LooxMem64-v0.zip</a> (to test 64Mb of memory).<br />2. Unpack the downloaded archive onto SD.<br />3. Insert SD into your Loox and reboot it.<br />4. Don't let PDA fall asleep, start haret.exe which is in the directory where unpacked the archive to.<br />5. When haret.exe is started press Run.<br />6. Read the caution when Linux is booted.<br />7. Make up your mind and then either press RESET (insert a stylus into a hole on the bottom side of the PDA, if you don't want to test memory) or press enter..<ad2></ad2><br />WARNING: Poor memory chips might be damaged during the test (that is why you want to test your PDA's memory, isn't it?). None will be responsible for your actions except yourself!!<br /><br />Note: You have to press any button during the testing process once per 5 or so minutes.<br />(<i>In a case you need to port the utility on the other platform (not Loox C550/N560) the only thing you have to do is to replace zImage and modify default.txt to let the linux for your platform boot on the target device).</i>)<ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6273818684831454306.post-20849940761418588312009-03-14T20:36:00.004+02:002009-03-14T21:22:42.397+02:00Linux Kernel for Fujitsu-Siemens Loox N560/C550 with support for CPLD and builtin ledsI've implemented support for CPLD and leds. htc-gpio driver is used with a custom list of CPLD registers/resources for Fujitsu-Siemens Loox 5XX (N560/C550). Now CPLD interface is available for all other drivers (existing and planned) of the linux/android kernel.<br /><br />It is interesting how CPLD is implemented in the linux kernel. Actually CPLD is a chip that supports very simple custom logic (and that is the reason why it is much faster than CPU). CPLD chip has a set of input pins and output pins. All these pins are mapped to a region of memory address space. The most important work with CPLD is that modifying values of pins to control devices. This is done setting a value to 0 or 1. In fact, programming of GPIO (general purpose input/output of CPU) is done in the same way: a programmer writes code that sets a GPIO pin to either 0 or 1. Linux kernel already has support for GPIO which provides a set of functions for platform drivers. In addition, GPIO driver provides a way to map any virtual GPIO pin to some custom code that is responsible for handling of setters and getters for the mapped pins. And indeed, that is how htc-egpio driver does the job. The driver leverages gpiolib mapping CPLD registers to GPIO pins. Thanks to this approach, no addition functions are required to work with CPLD. It is enough to use gpio_set_value/.. methods.<ad2></ad2><br />After the CPLD driver had been implemented, it was possible to implement a driver for the leds of Loox N560/C550. The leds driver, I implemented, exports a set of functions that other drivers (wifi, gps, bluetooth, pm, ...) are supposed to use to control the leds. Also, the leds driver makes it possible to control the leds from userspace (shell scripts, java program, ...) using files under sysfs filesystem.<br /><br />The following is the list of files exported by the leds driver and the possible content values for the each file:<br /><b>/sys/devices/platform/loox5xx-leds.1/keyboard</b>: on, off, any<br />- backlight for keyboard<br /><br /><b>/sys/devices/platform/loox5xx-leds.1/left_green</b>: on, off, any<br />- green led on the left side. WM5 indicates WiFi activity with this led<br /><br /><b>/sys/devices/platform/loox5xx-leds.1/left_blue</b>: on, off, any<br />- blue led on the left side. WM5 indicates Bluetooth activity with this led<br /><br /><b>/sys/devices/platform/loox5xx-leds.1/left_orange</b>: on, off, any<br />- orange led on the left side. WM5 indicates GPS activity with this led on Loox N560<br /><br /><b>/sys/devices/platform/loox5xx-leds.1/right_green</b>: on, off, any<br />- green led on the right side. WM5 allows programs to control this led using winapi.<br /><br /><b>/sys/devices/platform/loox5xx-leds.1/right_orange</b>: on, off, blink, any<br />- orange led on the left side. WM5 indicates charging activity with this led<br /><br />Where:<br /><b>on</b> - the led is on regardless of the kernel activity,<br /><b>off</b> - the led is off regardless of the kernel activity,<br /><b>blink</b> - the led is blinking regardless of the kernel activity,<br /><b>any</b> - the led is controlled by the kernel.<br /><br />For instance, if the content of the right_orange file is set to 'on', then the orange led (on right side of PDA) will be on no matter what you do: plug or unplug your device to/from a cradle. The driver will hold on the state of the led until, you write 'any' into the file right_orange. With 'any' value in file, the first 'power' event will change state of the led. The interface of the driver makes it possible to implement any notification (low battery, new mail..) effects you can imagine involving all leds of the device. The following script demonstrates how to blink with the keyboard backlight led:<pre><br />while true;<br /> do echo on > /sys/devices/platform/loox5xx-leds.1/keyboard;<br /> sleep 0.1;<br /> echo off > /sys/devices/platform/loox5xx-leds.1/keyboard;<br /> sleep 0.1;<br /> # Condition for break...<br />done<br />echo any > /sys/devices/platform/loox5xx-leds.1/keyboard;</pre><br />The current patch for the android cupcake kernel is located <a href="http://downloads.akshaal.info/linux-n560-c550/c550-android-kernel-2009-03-14.patch.gz?attredirects=0">here</a>.<br /><ad></ad>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com1tag:blogger.com,1999:blog-6273818684831454306.post-28696361298205727202009-03-10T10:19:00.004+02:002009-03-10T10:40:15.155+02:00Cross-Packaging On DebianDebian/Emdebian already has tons of packages. But sometimes you have a need to package or repackage a piece of software yourself. The following may be helpful if a platform you build for is not the platform you build on.<br /><br />Use the following command to build a package from a repository of apt:<pre>emsource --arch armel -b memtester</pre><br />If you need to install a package for target on your host:<pre><br />dpkg-cross -a armel -i zlib1g-dev_1.2.3.3.dfsg-13em1_armel.deb<br /></pre>The command <i>dpkg -l | grep zlib1g</i> will show you:<pre><br />ii zlib1g-dev-armel-cross 1:1.2.3.3.dfsg-13em1<br /></pre><ad2></ad2><br />(dpkg-cross automatically converts package names and moves content under the /usr/arm-linux-gnueabi (for armel target))<br /><br />You need to configure <i>~/.apt-cross/emsource</i> to use <i>emsource</i> without privileges of root. The content of the file may look like:<pre><br />workingdir: /home/akshaal/.apt-cross-working-dir<br /></pre><br />In a case you need to build a package from sources that have already been downloaded, use the following command:<pre><br />dpkg-buildpackage -aarmel</pre>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6273818684831454306.post-91371300565794869242009-03-08T22:11:00.005+02:002009-03-08T22:44:54.171+02:00Install emdebian on ARM deviceHere is how I've successfully installed emdebian on my Fujitsu-Siemens Loox N560. I assume there is an already installed emdebian-tools package and cross-compilers. Next thing is to run the following commands:<pre>cd /tmp;<br />mkdir grip/<br />sudo debootstrap --arch=arm --foreign lenny grip/ http://www.emdebian.org/grip/<br />cd grip/<br />sudo tar -czf /tmp/emdebian-grip-arm-debootstrap.tgz .</pre><br />Then SD card is to be partitioned with fdisk. For example it could be:<pre><br />cfdisk /dev/sdX<br />mkfs.ext3 /dev/sdXy</pre><br />where sdX - is a device for an SD card. And sdXy is a partition that is supposed to be used for linux on the SD card. Then mount the linux partition and untar the emdebian-grip-arm-debootstrap.tgz:<pre><br />mount /dev/sdXy /mnt<br />cd /mnt<br />tar zxpvf /tmp/emdebian-grip-arm-debootstrap.tgz<br />ln -s bin/sh init<br />cd /tmp<br />umount /mnt<br /></pre><br />Now we can boot linux from the partition. When linux has booted and a command line appeared, run the following commands step by step:<pre>cd /debootstrap<br />export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin<br />run ./debootstrap --second-stage<br />dpkg --configure -a<br />rm /init<br />cd /<br />ln -s sbin/init init<br /></pre><ad2></ad2><br />Now it is time to reboot linux again. This time a login prompt should work. Use root login and no password. Then configure basic settings:<pre><br />echo 'nameserver 1.1.1.1' > /etc/resolv.conf<br />echo '127.0.0.1 localhost' > /etc/hosts<br />echo '172.16.0.2 myhost 172.16.0.2' >> /etc/hosts<br />echo 'myhost' > /etc/hostname<br /></pre><br />use actual nameserver IP instead of 1.1.1.1. Reboot PDA one more time. Then configure network:<pre><br />ifconfig usb0 172.16.0.1 netmask 255.255.255.0<br />route add default gw 172.16.0.1</pre>Make sure network is up and running. Then upgrade your installation:<pre><br />echo 'deb http://www.emdebian.org/grip/ sid main' > /etc/apt/sources.list<br />apt-get update<br />apt-get dist-upgrade<br />apt-get install ...whateveryoulike...</pre><br />And configure network properly.<pre>cat > /etc/network/interfaces<br />auto lo<br />iface lo inet loopback<br />allow-hotplug usb0<br />iface usb0 inet static<br /> address 172.16.0.2<br /> netmask 255.255.255.0<br /> network 127.16.0.0<br /> broadcast 172.16.0.255<br /> gateway 172.16.0.1<br /> dns-nameservers 1.1.1.1<br /> dns-search your.domain<br /></pre><ad></ad>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com4tag:blogger.com,1999:blog-6273818684831454306.post-82714583204525958002009-03-08T12:56:00.004+02:002009-03-08T13:29:41.873+02:00Linux Kernel for Fujitsu-Siemens Loox N560/C550 with usbnet workingAfter 3 days of struggle I am finally able to build a linux kernel for my PDA Fujitsu-Siemens Loox N560. The kernel has been downloaded from <a href="http://www.asm32.ru">http://www.asm32.ru</a> and patched (pxa27x_udc.c) to support for usbnet (host-to-PDA networking through a usb coard). Also I've made a diff file with differences between the current cupcake kernel and the kernel (by date 02-mar-2009) from asm32.ru site. That will be useful later when I need to apply support for Loox to a new upstream cupcake kernel. <a href="http://downloads.akshaal.info/linux-n560-c550/c550-android-kernel-2009-03-07.patch.gz?attredirects=0">Here is the patch</a> which also includes support for usbnet on Loox C550/N560. The patch already contains a kernel configuration file (.config), but usbnet support is not enabled there. <a href="http://downloads.akshaal.info/linux-n560-c550/linux-config-2009-03-07?attredirects=0">Here is the other .config file</a> which is differ from that included in the patch by supporting usbnet, having power management switched off and configuration for larger fonts in console.<br /><br />It is possible to build the kernel with any toolchain for arm of your choice. I've tried crosstool-ng, emdebian and the one that is included in the android repo. I have decided to leverage emdebian toolchain for I use debian on my PC. The following is the command to build the kernel using emdebian toolchain:<pre>make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-</pre>Of course you have to have emdebian toolchain installed. You can install emdebian something like it is shown below:<pre><br />apt-get install emdebian-tool<br />emsetup --arch arm</pre>Then add:<pre><br />deb http://www.emdebian.org/debian/ unstable main</pre><br />into your /etc/apt/sources.list and run:<br /><pre>apt-get install linux-kernel-headers-arm-cross gcc-4.2-arm-linux-gnu</pre><br />When the kernel is built and ready you can copy it on an SD card and run it with haret with the following default.txt:<pre><br />set MTYPE 1454<br />set KERNEL zImage<br />set CMDLINE "root=179:2 mem=60M rootdelay=3 boot_delay=0 init=/init console=tty0 fbcon=rotate:0 androidboot.console=tty0 android.checkjni=1"<br />set RAMADDR 0xA0200000<br />bootlinux</pre><ad></ad>That is important! When you've placed zImage on an SD card, you will insert the card in your PDA. And then you must reboot your PDA! And only after you have rebooted your PDA with the SD card inside, you should ask haret to boot linux. That is very important because a linux kernel will not be loaded correctly (or it will but with only 10% chances) if one of the following conditions is true:<br />1. PDA has fallen asleep or suspended.<br />2. You have just inserted an SD card in your PDA and not rebooted it yet.<br />It looks like it is a bug in wince...<br /><br />P.S. There you can download cupcake kernel <a href="http://source.android.com/download"> http://source.android.com/download</a><br /><br />P.P.S. When you build kernel with usbnet, don't set CONFIG_USB_ETH_RNDIS to 'y'! Or your PC kernel (2.6.x) will not find your PDA... neither cdc_ether nor cdc_subset will claim your PDA.Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com5tag:blogger.com,1999:blog-6273818684831454306.post-42323063544377975982009-03-06T19:49:00.004+02:002009-03-08T14:02:10.967+02:00Async Related Posts WidgetI have finally implemented a feature I wanted to have on my blog. It is Related Posts Widget, but not just Yet Another Related Posts Widget. It differs form all other widgets that show related posts. It has features that no other widget has (yet at least):<br />1. It sorts related posts not only by date, but by <b>relevance</b>!<br />2. It is <b>small</b>. It is <b>fast</b>. It is <b>asynchronous</b>!. It is just AJAX :).<br />3. It is <b>easy</b> to install. It is very crucial point for me because I maintain a bunch of blogs and I don't want to waste my time doing coplicated setups for each blog over and over again.<br /><br />So, lets install the widget in a blog. The installation process constists of two simple modifications to the blog HTML Template. Go to <b>Settings -> Layout -> HTML Template</b>. But <i>Before</i> you start doing any modification, make a backup of your template (<b>Download full template</b>)! Now you are ready. The option <b>Expend Widget Templates</b> should be checked. Then follow the steps below:<br />1. Find string <b><data:post.body/></b> in your template code. Right <b>after(!)</b> this string, insert the snipped below:<pre><div caption='Related posts:' id='akRelatedPosts' max='8'/><br /><b:if cond='data:blog.pageType == &quot;item&quot;'><br /><script language='javascript' type='text/javascript'><br />(function(_1,_2){var _3={};var _4=_2.length;var _5=function(_6){var _7=&quot;([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?&quot;;var d=_6.match(new RegExp(_7));var _9=0;var _a=new Date(d[1],0,1);if(d[3]){_a.setMonth(d[3]-1)}if(d[5]){_a.setDate(d[5])}if(d[7]){_a.setHours(d[7])}if(d[8]){_a.setMinutes(d[8])}if(d[10]){_a.setSeconds(d[10])}if(d[12]){_a.setMilliseconds(Number(&quot;0.&quot;+d[12])*1000)}if(d[14]){_9=(Number(d[16])*60)+Number(d[17]);_9*=((d[15]==&quot;-&quot;)?1:-1)}_9-=_a.getTimezoneOffset();time=(Number(_a)+(_9*60*1000));return Number(time)};var _b=function(){var _c=[];for(var i in _3){_c.push(_3[i])}if(_c.length&lt;1){return}var _e=document.getElementById(&quot;akRelatedPosts&quot;);if(!_e){return}var _f=_e.getAttribute(&quot;max&quot;)||5;_c=_c.sort(function(a,b){var _12=b.weight-a.weight;if(_12!=0){return _12}return b.date-a.date});var s=&quot;&lt;ul&gt;&quot;;for(var i in _c){if(_f--&lt;1){break}var _14=_c[i];s+=&quot;&lt;li&gt;&lt;a href=&#39;&quot;+_14.href+&quot;&#39;&gt;&quot;+_14.title+&quot;&lt;/a&gt;&lt;/li&gt;&quot;}s+=&quot;&lt;/ul&gt;&quot;;var _15=_e.getAttribute(&quot;caption&quot;);s=&quot;&lt;span class=&#39;caption&#39;&gt;&quot;+_15+&quot;&lt;/span&gt;&quot;+s;_e.innerHTML=s};var _16=function(_17){for(var i in _17.feed.entry){var _19=_17.feed.entry[i];var _1a=_19.id[&quot;$t&quot;];var _1b=_3[_1a];if(_1b){_1b.weight++}else{var _1c;for(var _1d in _19.link){if(_19.link[_1d].rel==&quot;alternate&quot;){_1c=_19.link[_1d].href;break}}if(_1c==_1){continue}_1b={weight:1,title:_19.title[&quot;$t&quot;],date:_5(_19.published[&quot;$t&quot;]),href:_1c};_3[_1a]=_1b}}if(--_4==0){_b()}};var _1e=function(_1f){var _20;try{_20=new XMLHttpRequest()}catch(excp1){try{_20=new ActiveXObject(&quot;Msxml2.XMLHTTP&quot;)}catch(excp2){try{_20=new ActiveXObject(&quot;Microsoft.XMLHTTP&quot;)}catch(excp3){_20=false}}}var _21=function(){if(_20.readyState==4){if(_20.status==200){_16(eval(&quot;(&quot;+_20.responseText+&quot;)&quot;))}}};_20.open(&quot;GET&quot;,_1f,true);_20.onreadystatechange=_21;_20.send(null)};for(var _22 in _2){_1e(_2[_22])}} <!-- = = = = = endoffunc = = = = = = --><br />)(&quot;<data:blog.url/>&quot;,[<br /><b:loop values='data:post.labels' var='label'><br /> &quot;/feeds/posts/default/-/<data:label.name/>?alt=json&amp;max-results=5&quot;<b:if cond='data:label.isLast != &quot;true&quot;'>,</b:if><br /></b:loop><br />]);<br /></script><br /></b:if></pre><ad></ad>You should end up with something like this (click on the picture to open a full-size version):<br /><a href="http://picasaweb.google.com/lh/photo/vp8KXBOLZ3SC7Y_p36AILA?authkey=Gv1sRgCMTt-MKs5cTh6wE&feat=embedwebsite"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3q3NHxW34YjmA35EHpexe9BZvAyCl-af4tq633xxbPR5kLd-S0BpSqB3eM4FstRTFvcXtFlX-ALyo3sxHWoyL96uiWOJ4FZMKdjJv-Jl_ZX9whJASjNrwMyS7o95woF-ZnExqYH5rsjVe/s400/eng.png" /></a> Pay attention to <i>caption='...'</i> and <i>max='8'</i> You may consider to edit these values. A value for <i>caption</i> defines text to be shown above a list of related posts. And <i>max</i> defines a number of displayed relevant posts. <br />2. This step is optional. Everything should start working without it, but the widget will not be nice-looking. That is why you may want to complete it. So find the string <b>]]></b:skin></b>. And insert the following css snippet <b>before(!)</b> the string:<pre>#akRelatedPosts {<br /> padding-top: 20px;<br />}<br /><br />#akRelatedPosts .caption {<br /> font-weight: bold;<br />}<br /><br />#akRelatedPosts ul {<br /> margin: 0;<br />}</pre>If you think you have knowledge of css, you can tweak the styles below as you like. Finally you should see a picture like the following (click on picture to see full-size version):<a href="http://picasaweb.google.com/lh/photo/1KWdAkPHB-8HbUACiKYfZA?authkey=Gv1sRgCMTt-MKs5cTh6wE&feat=embedwebsite"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyjUC7PMUS-G33pNZ6g9FWvIu_jZhI2Zc2s0DdmfELO4s9ppi47Sod_wRyLR9oNMozXCGGuVK0vC9T1GpT_FWq_r8C6qopR6PpL7Zel6XLm4z0J-cfjL6GQYicJmtZEypy4_jXvE1Slrp1/s400/css.png" /></a><br /><ad2></ad2>That is all. You can save your template and check your posts.Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6273818684831454306.post-45574568194997325712009-03-05T18:35:00.005+02:002009-03-05T18:50:16.141+02:00Cross-site requestIt is handy to test javascript snippets without uploading them on a production server. But it is hard to test AJAX request like that. The reason for it is that firefox doesn't allow a cross-site request for a sake of user's security.<pre>uncaught exception: Access to restricted URI denied (NS_ERROR_DOM_BAD_URI)</pre>But if you know what you are doing you can temporarley switch this behavior off. Open <b>about:config</b> page and set <b>signed.applets.codebase_principal_support</b> to <b>true</b>. Also your script must have the following line executed before any cross-site request:<pre>netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");</pre><ad2></ad2>And don't forget to set <b>signed.applets.codebase_principal_support</b> to <b>false</b> value back and remove the line above from script when you have done with testing!!Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com3tag:blogger.com,1999:blog-6273818684831454306.post-37990931841970975022009-02-28T12:27:00.004+02:002009-03-01T12:04:57.685+02:00Remove Solid BorderIf you want to crop a picture stripping it from a border of some solid color, in linux you can use <b>convert</b> command which is a part of <b>ImageMagick</b> package:<pre><br />convert <i>original.jpg</i> -trim <i>modified.jpg</i><br /></pre><ad2></ad2><br />In a case you have a set of pictures, use <b>find</b> command to execute <b>convert</b>:<pre>find *.jpg -exec convert {} -trim <i>out</i>/{} \;<br /></pre><br />Where <b>out</b> is a directory for converted images.Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com1tag:blogger.com,1999:blog-6273818684831454306.post-5526625546282287412009-02-23T11:24:00.006+02:002009-02-23T11:54:51.885+02:00Extract Config from zImageIt was hard for me to find this simple thing in internet, so I gonna make life for someone a little bit easier.<br /><br />If you want to extract config file from existing linux image, zImage or bzImage, do the following:<br /><ul><li>Download archive file with linux <b>sources</b>. </li><li>Unpack linux kernel sources</li><li>Go into root directory of the kernel sources</li><li>Run chmod 755 ./scripts/extract-ikconfig</li><li>Run ./scripts/extract-ikconfig /tmp/zImage > /tmp/config</li></ul>Where /tmp/zImage is a file you want to extract a config from. And /tmp/config it is a filename for the extracted config.<ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com4tag:blogger.com,1999:blog-6273818684831454306.post-4657752878900406582009-02-22T17:52:00.002+02:002009-02-22T17:58:22.358+02:00Top Delusions About Google SitesAs far as I can see from forums, the most common delusion about Google Sites are:<br />1. <i>Google Sites doesn't support custom domains.</i> This is not true. <b>Google Sites supports custom domains.</b> You can map any part of google site to any domain.<br />2. <i>Google Sites gives you absolute freedom to populate your site with legal content.</i> This is not true. For example <b>you are not allowed to use adsense units on your Google Site.</b><ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com1