3G ฉบับยิ่งกว่า Dummy

มีคนถามฮับ ว่าโทรศัพท์ 3G เป็นยังไง ดูยังไงถึงเป็น 3G ก็เลยเริ่มสงสัยเหมือนกัน ตัวเองก็ทำงาน IT แต่ก็ไม่ค่อยรู้เรื่องพวกนี้สักเท่าไร ก็เลยลองหาข้อมูลดู แ่ต่ก็นะ เนื่องจากก็ไม่ได้เก่งกาจ data com ก็ได้ความรู้มาแบบงูๆ ปลาๆ ดังนี้ (ไม่ต้องเชื่อมากก็ได้นะ ลองหาข้อมูลดูอีกทีก็ดีฮับ)

3G มี 2 มาตรฐาน
1. CDMA2000 ซึ่งใช้กับระบบ CDMA หรือที่ Hutch บ้านเราใช้กัน
2. UMTS ซึ่งจะใช้กับพวกที่เป็น GSM (2G) เดิม ซึ่งโทรศัพท์มือถือที่จะออกมารองรับ 3G แบบมาตรฐานี้ก็จะออกเป็น Hybrid คือใช้ได้ทั้งที่เป็น GSM และ UMTS

ส่วน W-CDMA เป็น มาตรฐานที่ใช้กันมากที่สุดของ UMTS ทำให้บางครั้งก็เรียกทั้งสองชื่อนี้สลับกันไปมาได้
สุดท้าย HSDPA (High-Speed Downlink Package Access) เป็น protocol ที่ใช้บน UMTS ซึ่งทำให้ data transfer สูงๆ หรืออาจเรียกได้ว่าเป็น 3.5G หรือ 3G+ นั่นหมายความว่าถ้าโทรศัพท์ที่สนับสนุน HSDPA ก็แสดงว่าเป็นโทรศัพท์ 3G แ่น่นอน

แต่ทั้งนี้แต่ละประเทศก็ใช้คลื่นความถี่ 3G แตกต่างกัน สำหรับประเทศไทย ตอนนี้คือ 850 MHz ที่ True ให้บริการอยู่ หรือ 2100 MHz ที่ TOT ให้บริการ

Reference:

SCWCD สรุป

เพิ่งจะผ่านมาสอบมาหมาดๆ ค่ะ แต่ตอนที่อ่านก่อนสอบก็ทำสรุปไปด้วยเรื่อยๆ ตาม link ด้านล่างนะค่ะ


สำหรับสรุปนี้รวมมาจากหนังสือ Head First Servlet and JSP เป็นหลัก
มาทำ link รวมไว้ให้เผื่อใครจะสอบ ตอนที่สอบเป็นรหัส 310-083 นะค่ะ รู้สึกว่าจะเป็น J2EE 1.5 ค่ะ
ขอให้โชคดีกันนะค่ะ

Tomcat: setting SSL

การ setting SSL บน Tomcat สามารถทำได้ 2 แบบ คือ โดย JSSE กับ APR ซึ่ง APR จะใช้ OpenSSL เป็น engine ซึ่งมีความเป็น standard มากกว่า ไม่ติดว่าจะต้องเป็น Java เท่านั้น แต่ทั้งนี้การใช้ APR จะต้องใช้คู่กับ certificate file หรือ CA (certification authority) และไฟล์นี้ได้จากการขอผ่านทาง VeriSign หรือเวปอื่นๆ ที่ทำหน้าที่นี้โดยเฉพาะ เพื่อแสดงตัวตนของ server

ในที่นี้เราจึงขอข้ามไปไม่กล่าวถึง (เนื่องจากก็ยังไม่เคยลองทำจริงๆ เหมือนกันฮับ) ดังนั้นเรามาลอง set สำหรับใช้กันเล่นๆ ดูก่อนละกันนะค่ะ โดยใช้ JSSE ซึ่งทำได้ไม่ยากเลย สำหรับ JSSE เราก็ใช้คู่กับไฟล์เหมือนกัน แต่เป็นไฟล์ที่เรียกกันว่า keystore ซึ่งสำหรับคนที่ใช้ java อยู่แล้วจะมี tool ที่มากับ java ที่ใช้ในการสร้างไฟล์นี้ โดยใช้คำสั่ง

%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA
จากนั้นใส่ password เป็น changeit (ซึ่งเป็น password default ที่ใช้กับ tomcat)

C:\Program Files\Java\jdk1.6.0_10\bin>keytool -genkey -alias tomcat -keyalg RSA
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]:
What is the name of your organizational unit?
[Unknown]:
What is the name of your organization?
[Unknown]:
What is the name of your City or Locality?
[Unknown]:
What is the name of your State or Province?
[Unknown]:
What is the two-letter country code for this unit?
[Unknown]:
Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
[no]: y

Enter key password for
(RETURN if same as keystore password):

ซึ่ง keytool จะทำการสร้างไฟล์ที่ชื่อ .keystore ไว้ที่ home directory ของเรา ในกรณีของ Windows มันก็จะสร้างไว้ที่ C:\Documents and Settings\username ซึ่ง Tomcat จะไปหาไฟล์ .keystore ที่ home directory โดย default ซึ่งเราไม่จำเป็นต้องกำหนดอะไรเพิ่มเติมอีก

หลังจากที่ได้ keystore มาแล้ว เราก็มาแก้ configuration ของ Tomcat เพื่อให้สามารถใช้ SSL ได้ โดยเพิ่ม config ในส่วนด้านล่างในไฟล์ conf\server.xml ซึ่งอยู่ใน Tomcat directory อีกที

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />

สำหรับกรณีที่เราต้องการวาง .keystore ไว้ที่อื่นที่ไม่ใช่ home directory จะต้องมีการกำหนดเพิ่ม keystoreFile และ keystorePass attribute เ้ข้าไป เช่น

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
keystoreFile=" E:\Program Files\Apache Software Foundation\Tomcat6.0\conf\.keystore"
keystorePass="changeit"
clientAuth="false" sslProtocol="TLS" />

*แต่เท่าที่ได้ลองทำดู ดูเหมือนใช้ไม่ได้ เหมือนกับ Tomcat ไม่ได้สนใจ keystoreFile กับ keystorePass เลย ไม่แน่ใจเหมือนกันว่าทำอะไรผิดหรือเปล่า ก็ลองทำดูนะค่ะ แล้วมาบอกกันบ้างก็จะดี อิอิ

เท่านี้ก็เป็นอันเสร็จในส่วนของ Tomcat แต่สำหรับ ตัว web application ซึ่งถ้่าเราอยากให้ web เราใช้ SSL จะต้องกำหนดไว้ใน web.xml ด้วย โดยกำหนด tag ไว้ (สำหรับใครที่ยังไม่่เข้าใจในการ set security constraint ของ web application แนะนำให้ลองหาหนังสือมาอ่านเอานะฮับ เพราะว่าเรื่องนี้เราต้องการเน้นเรื่องการ set บน Tomcat เท่านั้น)

</security-constraint>
...
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>



Reference:
Apache Tomcat 6.0 - SSL Configuration HOW-TO
Configuring Tomcat 6 For https (SSL) Page
Setting Up SSL on Tomcat In 3 Easy Steps

JSP - Custom Tag

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
  http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd ">
  <tlib-version>1.2</tlib-version>
  <short-name>NMTOKEN</short-name>

  <uri>DiceFunction</uri>

  <!-- สำหรับ Custom Tag -->
  <tag>
    <description>random advice</description>
    <name>advice</name>
    <tag-class>package.AdvisorTagHandler</tag-class>
    <body-content> empty | scriptlet | tagdependent </body-content>

    <attribute>
      <name>user</name>
      <required> true | false </required>
      <rtexprvalue> true | false </rtexprvalue>
      <type>int | java.lang.String | etc. </type>
    </attribute>
    [<attribute> ... </attribute>]
    <dynamic-attributes> true | false </dynamic-attributes>
  </tag>

  <!-- สำหรับ tag file -->
  <tag-file>
    <name>Header</name>
    <path>/META-INF/tags/Header.tag</path>
  </tag-file>

  <!-- สำหรับ function -->
  <function>
    <name>rollIt</name>
    <function-class>com.amadmonster.scwcd.el.function.DiceRoller</function-class>
    <function-signature>int rollDice()</function-signature>
  </function>

  <!-- สำหรับ function ที่รับตัวแปร -->
  <function>
    <name>rollWith</name>
    <function-class>com.amadmonster.scwcd.el.function.DiceRoller</function-class>
    <function-signature>int rollDice(int)</function-signature>
  </function>

</taglib>

Custom Tag

<name> ของ <tag> จะเป็นชื่อที่ใช้อ้างใน JSP
<body-content> ของ <tag> สามารถเป็น
  • empty - ไม่มี body
  • scriptless - สามารถเป็น static text, EL expressions, standard action และ custom tags ได้ แต่จะใส่ JSP scriptlet () ไม่ได้
  • tagdependent - ค่า EL จะไม่ถูกแปล และถูกส่งให้ Custom Tag เสมือน plain-text เพื่อให้แปลด้วย Custom Tag เอง

<tag-class> เป็นชื่อ Package และ Class ของ Tag Handler
<attribute> จะบรรยายลักษณะของแต่ละ attribute ของ Custom Tag
<rtexprvalue> จะบอกว่า attribute ตัวนี้สามารถรับเป็น อย่างอื่นที่ไม่ใช่ text ได้หรือไม่ (เช่น EL expression, custom tag, scriptlet) (default: falue)
<type>
เป็นชนิดของ attribute ซึ่งใส่เป็น fully-qualified class name ยกเว้น primitive data type ซึ่งใส่ได้ตรงๆ เช่น int, char ในกรณีที่ไม่ใส่ ค่าอะไรเลย default จะเป็น java.lang.String
<dynamic-attributes> ใช้ config ว่า tag นี้จะรับ attribute แบบ dynamic หรือไม่ ซึ่งถ้าเป็น true ตัว tag handler จะต้อง implement DynamicAttributes


สำหรับ Custom Tag สามารถ implement ได้ 2 แบบ แบบแรกคือการ Simple Tag ซึ่งจะ extend SimpleTagSupport และมี life cycle ดังนี้




แบบที่ 2 คือ แบบ Classic Tag ซึ่งจะ extend TagSupport หรือ BodyTagSupport ซึ่งสามารถแก้ไข body ของ tag ที่จะแสดงออกไปได้ ซึ่งมี life cycle ดังนี้




และ State Diagram ของ TagSupport และ BodyTagSupport ดังนี้



Reference:
Tag Library Descriptor

JSTL - JSP Standard Tag Library


TagAttributeUsage
c:outvalueString ของค่าที่ต้องการจะแสดงผล
escapeXmlไม่ render XML หรือ HTML แ่ต่จะแสดงผลเหมือนกับ String ปกติ
default: true
defaultค่า default เมื่อ value เป็น null ซึ่งสามารถใช้ได้เช่นเดียวกับ
<c:out value="some string">default value</c:out>
c:forEachvarชื่อของตัวแปรที่ไว้รับ element ในแต่ละ loop
itemsชื่อของตัวแปรตัวแปร array, Collection, Map หรือ comma-delimited String ซึ่งเก็บแต่ละ element สำหรับการวนลูป
varStatueชื่อของตัวแปร javax.servlet.jsp.jstl.core.LoopTagStatus ซึ่งสามารถนำมาหาค่าต่างๆ เช่น count ต่อไป เช่น
<c:forEach var="movie" items="${movieList}"
varStatus="movieLoopCount">
 <tr><td>Count: ${movieLoopCount.count} </td></tr>
</c:forEach>

c:forTokensvarชื่อของตัวแปรที่ไว้รับ element ในแต่ละ loop
itemsชื่อของตัวแปรตัวแปร array, Collection, Map หรือ comma-delimited String ซึ่งเก็บแต่ละ element สำหรับการวนลูป
varStatueชื่อของตัวแปร javax.servlet.jsp.jstl.core.LoopTagStatus ซึ่งสามารถใช้ได้เช่นเดียวกับ varStatus ของ c:forEach
delimsString ที่เป็นตัวคั่นในการแบ่งแต่ละ token เช่น
<c:forTokens items="${dataString}" delims="," var="item">
Next item - ${item}
</c:forTokens>
beginตัวแรกที่จะเริ่มใช้ใน loop
endตัวสุดท้ายที่จะใช้ใน loop
stepตัวถัดที่จะใช้ใน loop
c:iftestค่าที่เป็น boolean เพื่อใช้ทดสอบว่าจะทำคำสั่งใน c:if หรือไม่
c:choose
ตัวนี้ไม่มี attribute จะใช้ ร่วมกับ c:when และ c:otherwise
<c:choose>
 <c:when test="${userPref == 'performance'}">
   ...do something...
 </c:when>
 <c:when test="${userPref == 'safety'}">
   ...do something...
 </c:when>
 <c:otherwise>
   ...do something...
 </c:otherwise>
</c:choose>
c:whentestเหมือนกับ attribute test ของ c:if คือใช้ทดสอบเงื่อนไขในการทำงาน
c:otherwise
ตัวนี้ไม่มี attribute ใช้ร่วมกับ c:when ดังนี้
c:setvarตัวแปรที่ต้องการ set ค่า ในกรณีที่ไม่มีตัวแปรชื่อนี้ ตัวแปรนี้ก็จะถูกสร้างขึ้นมา
scopescope ของตัวแปร
  • page (default)
  • request
  • session
  • application
default: page
valueค่าที่ต้องการจะ set หรือสามารถใส่ค่านี้เป็น body ของ tag ก็ได้ เช่น
c:settargetbean หรือ Map ที่ต้องการจะ set ค่า
propertyชื่อ property ที่ต้องการจะ set ค่า
valueค่าที่ต้องการจะ set หรือสามารถใส่ค่านี้เป็น body ของ tag ก็ได้ เช่น
<c:set target="${person}" property="name">new name</c:set>
c:removevarตัวแปรที่ต้องการลบออก
scopescope ของตัวแปรที่ต้องการจะลบ
  • page (default)
  • request
  • session
  • application
default: page
c:importurlc:import จะใช้ได้เหมือน jsp:include แต่ว่าสามารถอ้างถึงไฟล์ได้ทั้งใน application และนอก web application โดยระบุ URL ของไฟล์ที่ต้องการจะใส่เข้ามา
c:paramnamec:param ใช้ในการส่งตัวแปรข้ามไปยัง included page เหมือนกับ jsp:param โดยระบุชื่อของตัวแปรที่ต้องการจะส่งไป
valueค่าของตัวแปรที่จะส่งไป ใช้ร่วมกับ c:import หรือ c:url ซึ่งค่าของตัวแปรก็จะ encodeUrl แล้ว และสามารถส่งได้อย่างถูกต้อง ตัวอย่างเช่น
<c:import url="Header.jsp">
 <c:param name="subTitle" value="any sub-title for this page" />
<c:import>
c:urlvaluepath และ file ที่ต้องการจะ link ไป โดย c:url จะจัดการเรื่อง session ให้อัตโนมัติ เช่นในกรณีที่ client ไม่รับ cookies มันจะใส่ session id ต่อท้าย url ให้อัตโนมัติ แต่มันจะไม่ได้ทำ encodeUrl ให้ดังนั้นถ้าใน URL มีค่าตัวแปรที่เป็นอักขระพิเศษสำหรับ HTML เช่น space ก็จะทำให้ error ได้
c:redirecturlurl ที่จะ redirect ไป ซึ่งจะมีการ rewrite URL เพื่อจัดการ session ให้อัตโนมัติ
c:catchvarสำหรับใส่ code ที่เสี่ยงจะ throw exception ถ้ามี exception เกิดขึ้น มันจะข้าม block ของ c:catch ไปทำคำสั่งต่อจากนั้นเลย และ property var เป็นชื่อของตัวแปร exception ซึ่งจะใช้หลังจาก c:catch ได้ เช่น
<c:catch var="ex">
 <% int x = 1/0 %>
</c:catch>
If error occurs with ${ex}
*ที่เขียน c:set แยกออกมาเพราะว่ามันสามารถ set ได้ทั้ง ตัวแปร และ Bean หรือ Map ซึ่งจะใช้ property ที่ต่างกันจึงเขียนแยกกันเพื่อความเข้าใจง่าย


Reference:
JSTL Reference Documentation
Setup Jstl for Jsp2

Java App: Send Keystoke to Windows

สำหรับการส่งการกด keyboard โดยผ่านทาง java นะค่ะ ง่ายๆ เราใช้ java.awt.Robot เป็นตัวช่วยในการส่ง keystoke ตัวอย่างด้านล่างเป็นแค่ส่วนหนึ่งของ program ที่ดึงมาให้ดูเฉพาะส่วนที่ต้องการส่ง keystoke นะค่ะ



import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;

...
try {
Robot robot = new Robot();
// ส่ง key A ไป
robot.keyPress(KeyEvent.VK_A);
} catch (AWTException e) {
e.printStackTrace();
}
...



Reference:
Sending keystrokes to GUI applications

Java App: Send SMTP Mail Example

การส่งเมล์โดยใช้ java สามารถใช้ class ใน javax.mail ได้ ซึ่งตัวอย่างข้างล่างเป็น utility ที่สามารถเรียกใช้ได้เลย

MailUtility.java

package com.amadmonster.util.mail;

import java.util.Date;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.apache.log4j.Logger;

public class MailUtility {
/** Get logger. */
private static Logger logger = Logger.getLogger(MailUtility.class);
Properties props;

public MailUtility(String smtpServer) {
props = System.getProperties();
props.put("mail.smtp.host", smtpServer);
}

public void sendMail(String to, String from, String subject, String body) throws MailUtilityException {
Session session = Session.getDefaultInstance(props);
session.setDebug(false);

Message msg = new MimeMessage(session);
try {
msg.setFrom(new InternetAddress(from));
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to, true));
msg.setSubject(subject);
// check mime type from Web: Content Type
msg.setContent(body, "text/plain");
msg.setText(body);
msg.setSentDate(new Date());
// -- Send the message --
Transport.send(msg);
logger.info("Message sent OK.");

} catch (AddressException e) {
throw new MailUtilityException("Incorrrect address format", e);
} catch (MessagingException e) {
throw new MailUtilityException("Error occurs when sending mail", e);
}

}
}

MailUtilityException.java


package com.amadmonster.util.mail;

public class MailUtilityException extends Exception {

public MailUtilityException(String message, Throwable cause) {
super(message, cause);
}

public MailUtilityException(String message) {
super(message);
}

public MailUtilityException(Throwable cause) {
super(cause);
}

}


Reference:
JavaMail quick start

Java App: Windows Command Line Example

สำหรับการ run command line ผ่านทาง Java นั่นสามารถใช้ method Runtime.getRuntime().exec() ได้ แต่ว่าจะ run ตรงๆ ไม่ได้ จะต้องส่ง C:\WINDOWS\system32\cmd.exe /y /c ไปก่อน ตัวอย่างข้างล่างเป็นการเขียน utility class เพื่อที่จะนำไปใช้ต่อไปได้

CommandUtility.java


package com.amadmonster.util.command;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Logger;

public class CommandUtility {
static Logger logger = Logger.getLogger(CommandUtility.class);
private int status; // return command status, 0 - normal exit

/**
* Run Window command on specific working directory.
* @param command Array of command string and option.
* @param workDir String of working directory.
* @throws CommandUtilityException
*/
public void runCommand(String[] command, String workDir) throws CommandUtilityException {
String[] cmd = { "C:\\WINDOWS\\system32\\cmd.exe", "/y", "/c" };
List cmdList = new ArrayList();
cmdList.addAll(Arrays.asList(cmd));
cmdList.addAll(Arrays.asList(command));

Process p;
try {
p = Runtime.getRuntime().exec(cmdList.toArray(new String[0]), null,
new File(workDir));

logCommandInputStream(p);
logCommandErrorStream(p);
setStatus(p.exitValue());

if (getStatus() != 0) {
throw new CommandUtilityException("Fail to run command.");
}

} catch (IOException e) {
// TODO Auto-generated catch block
throw new CommandUtilityException("Fail to run command.", e);
}

}

private void logCommandInputStream(Process p) throws IOException {
InputStream is = p.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
logger.info(line);
}

}

private void logCommandErrorStream(Process p) throws IOException, CommandUtilityException {
InputStream is = p.getErrorStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
logger.error(line);
}

}

/**
* Run Window command on specific working directory.
* @param command Command string.
* @param workDir String of working directory.
* @throws CommandUtilityException
*/
public void runCommand(String command, String workDir) throws CommandUtilityException {
String[] cmd = { command };
runCommand(cmd, workDir);
}

/**
*
* @return int Status of running command, 0 - normal
*/
public int getStatus() {
return status;
}

/**
*
* @param status Exit command status
*/
private void setStatus(int status) {
this.status = status;
}

}


CommandUtilityException.java

package com.amadmonster.util.command;

public class CommandUtilityException extends Exception {

public CommandUtilityException(String message, Throwable cause) {
super(message, cause);
}

public CommandUtilityException(String message) {
super(message);
}

public CommandUtilityException(Throwable cause) {
super(cause);
}

}


Reference:
When Runtime.exec() won't