Monday, November 20, 2006

پشتیبانی جاوا از زبان های اسکریپتی (2)

در پست قبلی در مورد قابلیت تعامل جاوا با زبان های اسکریپتی در JDK 6 و قدرت بالای این ویژگی گفتم. در این پست برای اینکه موضوع بیشتر مشخص شود یک مثال کاربردی آورده ام. احتمالا در پست بعدی مثال دیگری را خواهم آورد.

قابلیت گسترش

امروزه برنامه هایی که می شود به آنها plug-in اضافه کرد یا آنها را به نحوی customize کرد خیلی متداول شده. خیلی خوب است اگر کاربر بتواند برنامه ای را که در دست دارد به نحوی آنطور که می خواهد تغییر دهد یا چیزی به آن اضافه کند. اضافه کردن چنین ویژگی هایی به یک برنامه در جاوا دو راه حل کلی(حداقل تا آنجا که من می دانم) دارد. یک راه حل مشکل و یک راه حل ساده. راه حل مشکل همان راه حلی است که eclipse و بسیاری دیگر از IDE ها و برنامه های تجاری از آن استفاده می کنند و آن هم اضافه کردن این قابلیت با استفاده از تعریف یک سری extension point است. توسعه دهندگان می توانند با استفاده از پروتکلی که برنامه اصلی تعریف می کند extension های خود را به برنامه اضافه کنند(این پروتکل معمولا بصورت یک DTD یا یک چیزی شبیه به آن به علاوه یک سری interface جاوا هست). برنامه اصلی معمولا از Java Reflection برای اضافه کردن extension ها به خود استفاده می کند.

ولی راه حل ساده استفاده از یک زبان اسکریپتی به همراه جاوا هست(همان کاری که jEdit انجام می دهد). در این راه حل قسمت عمده برنامه با استفاده از جاوا نوشته و کامپایل می شود و قسمت کوچکی از برنامه می تواند (بعدا) توسط یک زبان اسکریپتی نوشته و به برنامه اضافه شود. هر کدام از این روش ها مزایا و معایب خاص خود را دارد ولی در اینجا نمی خواهم به آنها بپردازم. کدی که در ادامه آورده شده یک مثال بسیار ساده(ولی کامل) از این روش است.

package com.blogspot.zoftware.jdk6.script;

import java.awt.BorderLayout;

import java.io.File;

import java.io.FileReader;

import javax.script.ScriptEngine;

import javax.script.ScriptEngineManager;

import javax.swing.JButton;

import javax.swing.JFrame;

public class ScriptedUI extends JFrame {

private JButton button = new JButton("Click Here");

public ScriptedUI() {

super("Script Demo");

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setLayout(new BorderLayout());

add(button);

setSize(180, 70);

}

public JButton getButton() {

return button;

}

static void runScripts(ScriptEngine eng, String folder) {

File[] scripts = new File(folder).listFiles();

for (File script : scripts) {

if (script.getName().endsWith(".js")) {

try {

eng.eval(new FileReader(script));

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

public static void main(String[] args) {

ScriptEngineManager factory = new ScriptEngineManager();

ScriptEngine bootstrapEng = factory.getEngineByName("JavaScript");

runScripts(bootstrapEng, "scripts/bootstrap");

ScriptedUI frame = new ScriptedUI();

ScriptEngine startupEng = factory.getEngineByName("JavaScript");

startupEng.put("frame", frame);

runScripts(startupEng, "scripts/startup");

frame.setVisible(true);

}

}

این برنامه هنگام شروع ابتدا هر اسکریپتی را که در پوشه scripts/bootstrap و با پسوند js وجود داشته باشد می خواند و اجرا می کند. سپس یک فریم می سازد و بعد از آن اسکریپت های پوشه scripts/startup را اجرا می کند. در اسکریپت های پوشه scripts/startup متغیر frame تعریف شده هست.

http://photos1.blogger.com/blogger/1266/3268/320/scripts.0.png

اگر در پوشه های starup و bootstrap فایلی وجود نداشته باشد، فریم نشان داده شده با LookAndFeel پیش فرض جاوا (Metal) و با اندازه مشخص شده در برنامه نشان داده می شود. حالا فرض کنیم بخواهیم LookAndFeel را تغییر دهیم. کافی است در پوشه scripts/bootstrap یک فایل با پسوند js قرار داده و داخل آن کد جاوا اسکریپت زیر را بنویسیم.

/* folder: scripts/bootstrap */
importPackage(javax.swing);
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

با اضافه کردن این فایل و اجرای مجدد برنامه شکل فریم تغییر می کند(شکل 2) و LookAndFeel برنامه همانند بقیه برنامه های سیستم می شود. اگر به کد برنامه دقت کرده باشید در خط 48 متغیر frame به موتور اسکریپت پاس می شود(به این معنی که این متغیر درون اسکریپت های پوشه startup شناخته شده است). حال اگر یک فایل با محتویات زیر درون پوشه scripts/startup قرار دهیم شکل فریم تغییر کرده و به شکل 3 در می آید. همچنین این فایل یک ActionListener به Button اضافه می کند که هنگام کلیک بر روی آن یک MessageBox به نمایش در می آید(شکل 4).

/* folder: scripts/startup */

frame.button.text = 'Do Not Click Please';

frame.setSize(200, 70);

importPackage(javax.swing);

listener = function(e){ JOptionPane.showMessageDialog(frame,

"You Clicked on " + e.source.text); }

frame.button.addActionListener(listener);

توجه دارید که بدون استفاده از زبان اسکریپتی، برای گسترش برنامه باید سورس آن را تغییر دهیم و دوباره آنرا کامپایل کنیم ولی با استفاده از این روش نیازی به کامپایلر نداریم. با استفاده از این روش، کاربر به آسانی می تواند محیط گرافیکی برنامه را تغییر داده و کامپوننت ها و منو های جدید به آن اضافه کند. البته این روش فقط خاص محیط گرافیکی نیست و می توان در بسیاری از موارد دیگر مانند نوشتن فایل های Configuratin برای برنامه نیز از آن استفاده کرد.

مثالی که در اینجا آورده شد بدون هیچ تغییر و نیاز به کتابخانه اضافی در JDK 6 اجرا می شود ولی اگر لازم باشد در ویرایش های قدیمی تر JDK اجرا شود نیاز به کمی تغییر و اضافه کردن کتابخانه های مورد نیاز است.

نکته آخر اینکه همیشه لازم نیست که extension ها کاملا به زبان اسکریپتی نوشته شود و می توان خود extension را با جاوا نوشت و کامپایل کرد و از زبان اسکریپتی بصورت یک چسپ برای اتصال extension ها استفاده کرد.

Saturday, November 18, 2006

پشتیبانی جاوا از زبان های اسکریپتی (1)

مقدمه

قبلا از ویژگیهای جدید JDK 6 گفتم. یکی از آن ویژگی ها ارتباط جاوا با زبان های اسکریپتی بود. البته پیش از این نیز BSF(Bean Scripting Framework) بصورت غیر رسمی استانداردی را برای تعامل جاوا با زبان های اسکریپتی فراهم می کرد ولی در JDK 6 این اتفاق بطور رسمی در کتابخانه جاوا افتاده است(البته این کتابخانه خیلی شبیه همان BSF هست). در حال حاظر زبان های اسکریپتی بسیار بسیار زیادی به زبان جاوا نوشته شده. از این میان می توان به پیاده سازی های مختلف جاوا اسکریپت، BeanShell (که یک مفسر برای زبان جاوا محسوب می شود)، groovy (دومین زبان استاندارد پلتفرم جاوا)، JRuby (پیاده سازی Ruby به زبان جاوا)، Jyton ( پیاده سازی Pyton به زبان جاوا) و ... (این لیست تا فردا صبح ادامه دارد) اشاره کرد. وجود این همه زبان اسکریپتی به زبان جاوا البته دلایل خاص خود را دارد، اول اینکه این زبان ها از انعطاف و قدرت بسیار بالایی برخوردارند(از لحاظ زبانی) و پیاده سازی آنها به زبان جاوا امکان دسترسی آنها به تمام کتابخانه های موجود در زبان جاوا را فراهم می آورد. دوم اینکه پیاده سازی یک زبان اسکریپتی در زبان جاوا با استفاده از Parser Generator های قدرتمندی مثل Javacc و ANTLR و به مدد استفاده از Java Reflection خیلی کار مشکلی نیست. در هر حال گرچه این زبان ها می توانند به تنهایی مورد استفاده قرار بگیرند ولی تعامل این زبان ها با جاوا امکان بسیار قدرتمند تری است. به این ترتیب می توان قسمت عمده پروژه ها را به زبان جاوا نوشت و تنها آنجاهایی که لازم است دست به دامان زبان های اسکریپتی شد.

یک مثال ساده:

استفاده از یک زبان اسکریپتی در JDK 6 بسیار ساده هست. ابتدا یک نمونه از کلاس javax.script.ScriptEngineManager درست می کنیم، سپس با استفاده از متد getEngineByName یک engine درست می کنیم. خوشبختانه JDK 6 همراه خود یک پیاده سازی از جاوا اسکریپت دارد ولی اگر زبان دیگری نیاز داشتید باید jar file های آن را به classpath اضافه کرده و تنظیمات لازم را انجام دهید. مثال زیر را ببینید:

import javax.script.ScriptEngine;

import javax.script.ScriptEngineManager;

public class TestScript {

public static void main(String[] args) throws Exception {

ScriptEngineManager factory = new ScriptEngineManager();

ScriptEngine engine = factory.getEngineByName("JavaScript");

engine.eval("println('Hello!')");

engine.put("x", 1);

engine.put("y", 2);

double result = (Double)engine.eval("x * x + y");

System.out.println(result);

}

}

با استفاده از متد ScriptEngine.put(varName, varValue) می توانیم یک متغیر را به engine پاس کنیم. متد eval می تواند اسکریپت های نوشته شده به آن زبان اسکریپتی را اجرا کند. و متد get مقدار متغیر های موجود در engine را بر می گرداند.

Friday, November 17, 2006

ویژگیهای جدید JDK 1.6


در
JDK 6 (یا به عبارت دیگر 1.6) با نام Mustang ویژگی های جالبی اضافه شده. البته هنوز نسخه نهایی آن منتشر نشده ولی اگر دوست داشته باشید میتوانید نسخه RC(Release Candidate) آن را از سایت java.net دانلود کنید. شرکت سان برای توسعه این ویرایش JDK روش جدیدی را بکار برد که در ویرایش های قبلی جاوا استفاده نکرده بود. تقریبا از 15 ماه پیش سورس JDK 6 در دسترس همه قرار گرفت تا همه کاربران بتوانند در آزمایش و توسعه آن نقش داشته باشند. به همین دلیل هم پیش بینی میشود این ویرایش JDK پایدار تر و کم خطا تر از نسخه های پیشین باشد. البته قرار داشتن سورس بر روی وب به معنی اپن سورس بودن نیست و هنوز سان(به احتمال قوی) از همان مجوز های قبلی برای انتشار JDK 6 استفاده خواهد کرد.

در هر حال با ویژگی های جدید و جذابی به JDK اضافه شده به نظر می رسد سان قصد دارد Java SE را به یک Java EE دیگر تبدیل کند. بعضی از این ویژگی ها در ادامه آورده ام:

JDK 6 @@@ بصورت استاندارد دارای یک ویرایش از پایگاه داده Apache Derby هست. Derby سیستم مدیریت پایگاه داده ای است که بطور کامل با جاوا نوشته شده و یک DBMS تمام عیار محسوب می شود و قابلیت های بسیار زیادی از جمله پشتیبانی کامل از SQL 92 و پشتیبانی از برخی از ویژگی های SQL 99 و پشتیبانی از JDBC 4 دارد. Derby می تواند بصورت Client/Server یا بصورت Embedded کار کند.

@@@ پشتیبانی کامل از وب سرویس ها (با استفاده از Annotation) به JDK اضافه شده، همچنین JDK شامل یک وب سرور در بسته com.sun.net.httpserver هست.

@@@ قابلیت اضافه کردن زبان های اسکریپتی به JDK اضافه شده. با استفاده ای این قابلیت زبان های اسکریپتی می توانند بصورت Pluggable و با استفاده از SPI(Service Provider Interface) به جاوا اضافه شوند. این قابلیت خیلی شبیه BSF(Bean Scripting Framework) که از سالها پیش مورد استفاده قرار می گرفت هست. همچنین JDK شامل یک پیاده سازی از جاوا اسکریپت هست (همان Mozilla Rhino). اضافه شدن زبان های اسکریپتی به جاوا قابلیت بسیار قدرتمندی هست که اگر فرصت شد بعدا در مورد آن بیشتر صحبت می کنم.

@@@ در JDK 6 واسط کاربر جاوا (Swing و AWT) تعامل مناسب تری با سیستم عامل دارد. از جمله قابلیت های اضافه شده، دسترسی به System Tray، قابلیت باز کردن فایل ها با نرم افزار پیش فرض سیستم عامل(مثلا باز کردن فایل های PDF با Acrobat Reader)، باز کردن یک URL خاص درون مرورگر سیستم و قابلیت باز کردن برنامه پیش فرض mail است(این قابلیت ها خیلی شبیه قابلیت هایی هست که پروژه JDIC به جاوا اضافه می کرد). همچنین به کلاس java.io.File متدهایی برای گرفتن مقدار فضای خالی و مقدار کل فضای دیسک ها اضافه شده.

@@@ قابلیت جالب(بخوانید خنده دار) دیگری که به جاوا اضافه شده و بیشتر شبیه معجزه هست این است که بالاخره برنامه نویسان جاوا بعد از 11 سال می توانند بدون درد سر Password را از Console هم بخوانند. این قابلیت به مدد اضافه کردن کلاس java.io.Console و متد System.console() به برنامه نویسان اجازه می دهد Password را بدون اینکه دیده شود از Console بخوانند. این مسئله از این جهت اهمیت دارد که بسیاری از برنامه های حساس بر روی سرورهایی اجرا می شوند که محیط گرافیکی ندارند(Headless) و فقط از طریق یک کنسول(و شاید از طریق telnet) می توان به آن ها دسترسی داشت، به همین خاطر نمی توان از JPasswordField استفاده کرد. از آن جایی که ذخیره کردن Password در فایل یا هر رسانه دیگری خیلی اوقات خطرناک است، تنها راهی که باقی می ماند خواندن از کنسول است.

در مجموع JDK 6 که هفتمین ویرایش عمده جاوا محسوب می شود، بسیار Stable و بدون دردسر هست. تقریبا هر چیزی که برای توسعه یک برنامه Desktop لازم است در JDK 6 وجود دارد. من چند روزی هست که ویرایش RC را بر روی دستگاه خودم نصب کرده ام و در مجموع مشکل خاصی با آن نداشتم.

Tuesday, November 14, 2006

جاوا اپن سورس می شود

بالاخره شرکت سان ماکرو سیستمز تحت فشار شرکت ها ،گروه ها و حتی برخی از کشورها امروز اعلام کرد که پلت فرم جاوا را بصورت اپن سورس ارائه دهد. این تصمیم شامل Java ME(Micro Edition) ، Java SE(Standard Edition) و پیاده سازی شرکت سان از Java EE(Enterprise Edition) با نام GlassFish می شود. بسیاری از کارشناسان این اتفاق را به رنسانسی در صنعت جاوا تعبیر کرده اند.

چند سالی بود که برخی از شرکت ها (علی الخصوص IBM)، برخی از کشورها(علی الخصوص چین و برزیل) و بسیاری از گروه های طرفدار اپن سورس از شرکت سان درخواست می کردند که این کار را انجام دهد، و این فشار ها تا همین امروز که سان اعلام کرد JDK 1.7 (و احتمالا JDK 1.6) را تحت مجوز GPL منتشر می کند ادامه داشت. انتشار JDK تحت مجوز GPL این اجازه را می دهد که دیگران بتوانند سورس آن را تغییر دهند ولی سورس تغییر یافته باید تحت مجوز GPL منتشر شود. به همین دلیل می توان گفت که GPL تا حد زیادی از سوء استفاده های تجاری جلوگیری می کند.

انتشار پیاده سازی مرجع جاوا بوسیله شرکت سان تغییرات و پیامدهای بزرگی را در پی خواهد داشت. اول اینکه تغییراتی که در کامپایلر، ماشین مجازی و کتابخانه جاوا داده می شود می تواند نوید ارتقای کیفیت این پلت فرم را در آینده بدهد. دوم اینکه زبان جاوا در آینده طرفداران بیشتری پیدا خواهد کرد. می توان گفت جاوا تحت سیستم عامل لینوکس ( که آن هم تحت مجوز GPL منتشر می شود) می تواند به حاکمیت C++ خاتمه دهد و توسعه دهندگان لینوکس روی خوش(تری) به جاوا نشان دهند. همچنین جاوا می تواند تحت سیستم عامل هایی که پیاده سازی از جاوا در آن وجود ندارد پیاده سازی شود. سومین تغییری (که برای ما ایرانی ها مهمترین تغییر نیز هست) این است که جاوا از انحصار شرکت های امریکایی خارج می شود. در حال حاظر(تا آنجایی که من خبر دارم) شرکت های Sun Microsystems، IBM، Bea و Oracle پیاده سازی خود را از JDK را ارائه می دهند که بر اساس قوانین امریکا صادرات این شرکت ها به ایران غیر قانونی است. البته پیاده سازی های اپن سورسی هم از JDK وجود دارد که عمدتا (هنوز) نصفه و نیمه هستند. از جمله مطرح ترین آن ها پروژه Harmony (تحت مجوز Apache) و پروژه Gnu Classpath (تحت GPL) هست. البته احتمالا هارمونی حتی پس از انتشار اپن سورس JDK هم به کار خود ادامه می دهد چرا که همان طور که گفتم هارمونی تحت مجوز آپاچی منتشر می شود(که یک مجوز اپن سورس ولی Commercial Friendly هست) که تفاوت های فلسفی عمیقی با GPL دارد، ولی پروژه های دیگر اپن سورس (که تحت GPL هستند) ممکن است خود را با پیاده سازی سان تطبیق دهند یا با آن ترکیب شوند!

کلام آخر اینکه تغییرات در JDK به معنی عدم سازگاری بین پیاده سازی های مختلف JDK نیست. تمام تغییرات ایجاد شده در JDK برای اینکه به اسم جاوا منتشر شود باید تمام تست های TCK(Tool Compatibility Kit) را پاس کند.

Related Links:
https://openjdk.dev.java.net/
http://www.infoq.com/news/2006/11/open-source-java