搜尋此網誌

2013年10月8日 星期二

【Java】HTTP response code 505解決辦法

如題
URL url = new URL(urlstring.trim());                        
urlConnection = (HttpURLConnection) url.openConnection();
int response = urlConnection.getResponseCode();

解決辦法
需對url的parameter先作encode
String urlString = "http://test.com?param1=" + URLEncoder.encode(value1, "UTF-8") + "&param2=" + URLEncoder.encode(value2, "UTF-8") ;

URL url = new URL(urlstring.trim());                        
urlConnection = (HttpURLConnection) url.openConnection();
int response = urlConnection.getResponseCode();
參考:

  1. http://stackoverflow.com/questions/13252814/getting-505-responce-from-server
  2. http://stackoverflow.com/questions/3625659/java-io-ioexception-server-returns-http-response-code-505

2013年9月27日 星期五

【Java】實作透過Gmail SMTP Server 發送信件 版本三

改寫版本二的內容(尚未測試,ps筆者跑太多次,gmail被暫停使用)
  1. 參考至這篇TLS加密並不是明文傳送。若要用密文傳送需要用SSL,且設定需要用SMTPS。
    (若需測試使用,下面兩行註解拿掉)
    // if (this.secureType == secureType.SSL)
    // protocol = SMTPS;
  2. 更貼近E-mail功能,使寄件者以及收信者均包含名字以及email地址,也可以設定同時多個收信者。所以增加:EmailSender和EmailReceiver。
  3. Properties 參數可以參考:Package com.sun.mail.smtp


EmailSender.java

class EmailSender{
	String name;
	String address;
	
	EmailSender(){
		name = "";
		address = "";
	}	
}
EmailReceiver.java

public interface EmailReceiver {
	String name();
	String address();
}

Email.java

package option;

import java.text.DateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.Vector;

import javax.mail.Address;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import option.GmailSetting.SecureType;

public class Email {

	String subject;
	String content;
	SecureType secureType;
	boolean valid;
	String account;
	String passowrd;
	EmailSender emailSender;
	Vector<EmailReceiver> emailReceivers;

	static final String SMTP = "smtp";
	static final String SMTPS = "smtps";

	Email(SecureType secureType, boolean valid, String account, String password) {
		subject = "";
		content = "";
		this.secureType = secureType;
		this.valid = valid;
		this.account = account;
		this.passowrd = password;
		emailSender = new EmailSender();
		emailReceivers = new Vector<EmailReceiver>();
	}

	public void setSubject(String subject) {
		this.subject = subject;
	}

	public void setContents(String content) {
		this.content = content;
	}

	public void setSender(String name, String address) {
		emailSender.name = name;
		emailSender.address = address;
	}

	public void addReceiver(final String name, final String address) {
		emailReceivers.add(new EmailReceiver() {
			public String address() {
				return address;
			}

			public String name() {
				return name;
			}
		});
	}

	Properties generateRequireProp() {

		String protocol = SMTP;
		final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
		String portNumber = GmailSetting.PORT_NUMBER.get(secureType.value()).toString();

		//
		// if (this.secureType == secureType.SSL)
		// protocol = SMTPS;

		// set up gmail information
		Properties props = new Properties();
		props.setProperty("mail." + protocol + ".host", "smtp.gmail.com");
		props.setProperty("mail." + protocol + ".port", portNumber);
		props.setProperty("mail.transport.protocol", protocol);

		if (valid)
			props.setProperty("mail" + protocol + ".smtp.auth", "true");

		if (this.secureType != SecureType.None) {
			if (this.secureType == secureType.TLS)
				props.setProperty("mail." + protocol + ".smtp.starttls.enable", "true");
			else {
				props.setProperty("mail." + protocol + ".socketFactory.class", SSL_FACTORY);
				props.setProperty("mail." + protocol + ".socketFactory.fallback", "false");
				props.setProperty("mail." + protocol + ".socketFactory.port", portNumber);
				props.setProperty("mail." + protocol + ".smtps.ssl.enable", "true");

			}
		}
		return props;
	}

	boolean sendMail() {
		try {
			if (emailReceivers.isEmpty()) {
				System.out.println("Email Receiver is empty.");
				return false;
			}

			System.out.println("Start to send email");

			int receiverAddressCount = emailReceivers.size();
			Address[] mailAddress = new Address[receiverAddressCount];
			for (int i = 0; i < receiverAddressCount; i++) {
				mailAddress[i] = new InternetAddress(emailReceivers.get(i).address(), emailReceivers.get(i).name());
			}

			Address senderAddress = new InternetAddress(emailSender.address, emailSender.name);

			Properties props = generateRequireProp();

			// build the new session service
			Session session = Session.getInstance(props, null);

			Message message = new MimeMessage(session);

			// build the mail of sender , receiver and subject info
			message.setHeader("Content-Transfer-Encoding", "utf-8");
			message.setFrom(senderAddress);
			message.setRecipients(Message.RecipientType.TO, mailAddress);
			message.setSubject(subject);

			// set mime content
			MimeMultipart multipart = new MimeMultipart();
			MimeBodyPart messageBodyPart = new MimeBodyPart();
			messageBodyPart.setContent(content + "by " + secureType.value() + " connection.", "text/html;charset=utf-8");
			multipart.addBodyPart(messageBodyPart);
			message.setContent(multipart);

			message.saveChanges();
			String protocol = SMTP;

			if (valid) {
				Transport transport = session.getTransport();
				if (this.secureType == secureType.SSL)
					protocol = SMTPS;
				transport = session.getTransport(protocol);
				transport.connect("smtp.gmail.com", this.account, this.passowrd);
				Transport.send(message, message.getAllRecipients());
				transport.close();
			} else {
				Transport.send(message);

			}
			System.out.println("Done");

		} catch (Exception e) {
			// throw new RuntimeException(e);
			e.printStackTrace();
		}
		return true;

	}

	public static void main(String args[]) {

		final String senderAddr = "sender@gmail.com";
		final String password = "sender password";

		Email testEmail = new Email(SecureType.SSL, true, senderAddr, password);
		testEmail.setSubject("Test mail " + DateFormat.getDateTimeInstance().format(new Date(System.currentTimeMillis())));
		testEmail.setContents("This is a test e-mail by javamail library");
		testEmail.addReceiver("Test123", "receiver@mail");
		testEmail.setSender("SenderTest by Jorden", senderAddr);

		if (testEmail.sendMail())
			System.out.println("Success to send email!");

		else
			System.out.println("Error");
	}
}

2013年9月26日 星期四

【Java】實作透過Gmail SMTP Server 發送信件 版本二

本實作是改寫上篇透過SSL加密寄信;新增TLS以及None的方法。
因為Gmail已經不提供None(不加密)的寄信,所以在執行None方法時,會出現問題。

這部分除了改寫原本code以外,新增一個class放置gmail secure設定以及對應的port number。

Email.java


package option;

import java.text.DateFormat;
import java.util.Date;
import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import option.GmailSetting.*;

public class Email {

	String subject;
	String content;
	String receiver;
	SecureType secureType;

	Email(SecureType secureType) {
		subject = "";
		content = "";
		receiver = "";
		this.secureType = secureType;
	}

	public void setSubject(String subject) {
		this.subject = subject;
	}

	public void setContents(String content) {
		this.content = content;
	}

	public void setReceiverAddress(String address) {
		this.receiver = address;
	}

	Properties generateRequireProp() {

		final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
		String portNumber = GmailSetting.PORT_NUMBER.get(secureType.value()).toString();

		// set up gmail smtp information
		Properties props = new Properties();
		props.setProperty("mail.smtp.host", "smtp.gmail.com");
		props.setProperty("mail.transport.protocol", "smtp");
		props.setProperty("mail.smtp.auth", "true");
		props.setProperty("mail.smtp.port", portNumber);

		if (this.secureType != SecureType.None) {
			if (this.secureType == secureType.TLS)
				props.setProperty("mail.smtp.starttls.enable", "true");
			else {
				props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
				props.setProperty("mail.smtp.socketFactory.fallback", "false");
				props.setProperty("mail.smtp.socketFactory.port", portNumber);
				props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
			}
		}
		return props;
	}

	boolean sendMail() {
		if (this.receiver.equals("")) {
			System.out.println("Email Receiver is empty.");
			return false;
		}

		System.out.println("Start to send email");
		Properties props = generateRequireProp();
		final String username = "sender@gmail.com";
		final String password = "sender password";

		// build the new session service
		Session session = Session.getInstance(props, new Authenticator() {
			protected PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication(username, password);
			}
		});

		try {
			Message message = new MimeMessage(session);

			// build the mail of sender , receiver and subject info
			message.setFrom(new InternetAddress(username));
			message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(receiver, false));
			message.setSubject(subject);

			// set mime content
			MimeMultipart multipart = new MimeMultipart();
			MimeBodyPart messageBodyPart = new MimeBodyPart();
			messageBodyPart.setContent(content + "by " + secureType.value() + " connection.", "text/html;charset=utf-8");
			multipart.addBodyPart(messageBodyPart);
			message.setContent(multipart);

			Transport.send(message);
			System.out.println("Done");

		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return true;

	}

	public static void main(String args[]) {

		Email email = new Email(SecureType.SSL);
		email.setSubject("Test mail " + DateFormat.getDateTimeInstance().format(new Date(System.currentTimeMillis())));
		email.setContents("This is a test e-mail by javamail library");
		email.setReceiverAddress("receiver@mail");

		if (email.sendMail())
			System.out.println("Success to send email!");

		else
			System.out.println("Error");

	}
}


GmailSetting.java

package option;

import java.util.HashMap;
import java.util.Map;

public class GmailSetting {
	SecureType secureType;

	public GmailSetting() {
		// TODO Auto-generated constructor stub
	}

	public enum SecureType {
		None, SSL, TLS;

		public String value() {
			return name();
		}

		public static SecureType fromValue(String v) {
			return valueOf(v);
		}
	}

	static final Map<String, Integer> PORT_NUMBER = new HashMap<String, Integer>() {
		private static final long serialVersionUID = -5199045595923410899L;
		{
			put("None", 25);
			put("SSL", 465);
			put("TLS", 587);
		}
	};

}

【Java】class method VS. instance method


     
  1. 類別方法(class method or static method):這種方法以 static 宣告。呼叫的方式是 C.m(...),其中 C 是類別名稱,m 是方法名稱,...則是0至多個傳入的參數。在宣告時,會配置記憶體空間
  2. 實例方法(instance method or non-static method):這種方法不以 static 宣告,隸屬於一個類別所產生的實例。呼叫的方式是 o.m(...),其中 o 是這個類別或其子類別的實例,而 m 是其方法名稱,...則是0至多個傳入的參數。  在宣告時,不會配置記憶體空間

class A {
    static String c1() {
        return "class method不需new就可使用";
    }
    String c2() {
        return "instance method需new才可使用";
    }
}

public class ClassInstanceMethod {
    public static void main(String argv[]) {
        System.out.println("=呼叫class method=");
        System.out.println(A.c1());
        System.out.println("=呼叫instance method=");
        //System.out.println(A.c2()); =>error
        A a = new A();
        System.out.println(a.c2());
    }
}

參考:
http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
http://www.oreilly.com.tw/column_sleepless.php?id=j021

【Java】Primitive VS. Wrapper Class

看了很多書,都沒有很清楚說明為何要這兩個class的差別,而且又是從c語言跳到Java,覺得Wrapper Class的出現簡直莫名其妙。很久以前之前還被嗆難道不知道宣告int要先new出來。後來看了不少資料,得到以下結論:

參考

 Wrapper Class的出現,是因為Java裡面提供的許多API只能針對物件(例如,Collection),無法適用於基本型別(即int, long, char, boolean等)。為了使這些基本型別也可以適用,所以Java創造了與這些基本型別相對應的wrapper class
 Primitive  <-->Wrapper Class
--------------------------------
boolean <-> Boolean
byte <-> Byte
char <-> Character
short <->Short
int <-> Integer
long <-> Long
float <-> Float
double <-> Double


Primitive在宣告時,不需new,即可以在記憶體產生。例:int i=10;
Wrapper在宣告時,需new即可以在記憶體產生。例:Integer wInt= new Integer(10); 
int ii = wInt.intValue; //ii=10 


而Autoboxing的機制,就是自動把primitive轉成wrapper;相反地,Unboxing的機制就是自動把
wrapper轉成primitive。

 Autoboxing機制的目的:是要減少實體化的物件數,因此透過建立一個pool來儲存這些因auboxing產生出的物件,但這也造成另一問題:這些備產生出的物件不會輕易隨便殺掉。如果沒有限制建立這些物件,記憶體會快就用光,避免這些memory overflow的問題,Java限制每個wrapper class的pool範圍。若超過這個範圍,就會以一般建立物件的方式new出來。例:Integer i = new Integer(321);
Boolean:  (全部暫存)
Byte:         (全部暫存)
Character:  [0, 127] 暫存
Short :          [-128, 127] 暫存
Long:           [-128, 127] 暫存
Float:        (沒有暫存)
Double:   (沒有暫存)


因此,下例

int getNumber() {
        //do something
        return 128;
}

Integer value1 = 128;  //Autoboxing
Integer value2 =
getNumber();  //Autobixing
if (value1 == value2) {
        System.out.println(“A”);
}
else {
        System.out.println(“B”);
}

當value1和value2都個別autoboxing成物件,所以會分別指向pool中不同的記憶體位置。
在做判斷"=",因為指向不同記憶體位置,所以回傳結果,答案會是B。 

 所以在牽涉到兩物件比較時,需要用equals或compareTo的method,比較兩物件的內容,而不是比較兩物件的地址。

2013年9月25日 星期三

【Java】實作透過Gmail SMTP Server 發送信件(利用javamail API)

連線加密方式有三種:
  1. None(不加密)
  2. TLS , port number:587
  3. SSL , port number:465 (參考網址)
這裡實作以SSL加密寄送信件。
需要包裝javamail API到lib,下例用JavaMail 1.4.2進行包裝。

注意: 若發送信件內容,不只是純文字,而有用到html、CSS。
經過測試後,確定gmail 不支援部分block css內容,若可行,請寫inline css。
其他html email設計的要素,參考:
  1. Guide to CSS support in email 
  2. How HTML email works, basic concepts, best practices, tips and tricks

package option;

import java.text.DateFormat;
import java.util.Date;
import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class Email {

 String subject;
 String content;
 String receiver;

 Email() {
  subject = "";
  content = "";
  receiver = "";
 }

 public void setSubject(String subject) {
  this.subject = subject;
 }

 public void setContents(String content) {
  this.content = content;
 }

 public void setReceiverAddress(String address) {
  this.receiver = address;
 }

 static Properties generateRequireProp() {

  final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
  
  // set up gmail information
  Properties props = new Properties();
  props.setProperty("mail.smtp.host", "smtp.gmail.com");
  props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
  props.setProperty("mail.smtp.socketFactory.fallback", "false");
  props.setProperty("mail.smtp.socketFactory.port", "465");
  props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
  props.setProperty("mail.smtp.auth", "true");
  props.setProperty("mail.smtp.port", "465");

  return props;
 }

 boolean send() {
  if (receiver.equals("")) {
   System.out.println("Email Receiver is empty.");
   return false;
  }

  Properties props = generateRequireProp();
  final String username = "sender@gmail.com";
  final String password = "sender password";

  // build the new session service
  Session session = Session.getInstance(props, new Authenticator() {
   protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication(username, password);
   }
  });

  try {   
   Message message = new MimeMessage(session);
   
   //build the mail of sender , receiver and subject info 
   message.setFrom(new InternetAddress(username));
   message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(receiver, false));
   message.setSubject(subject);
   
   // set mime content
   MimeMultipart multipart = new MimeMultipart();
   MimeBodyPart messageBodyPart = new MimeBodyPart();
   messageBodyPart.setContent(content, "text/html;charset=utf-8");
   multipart.addBodyPart(messageBodyPart);
   message.setContent(multipart);

   Transport.send(message);
   System.out.println("Done");

  } catch (Exception e) {
   throw new RuntimeException(e);
  }
  return true;

 }

 public static void main(String args[]) {

  Email email = new Email();
  email.setSubject("Test mail "+DateFormat.getDateTimeInstance().format(new Date(System.currentTimeMillis())));
  email.setContents("This is a test e-mail by javamail library");
  email.setReceiverAddress("receiver@mail");

  if (email.send())
   System.out.println("Sending is successing");

  else
   System.out.println("Error");

 }
}

2013年9月23日 星期一

【Music】One more time, One more Chance



 これ以上何を失えば 心は許されるの
究竟還要再失去什麼 我的心才會得到寬恕
どれ程の痛みならば もういちど君に会える
到底要痛到什麼程度 才能夠再次見到妳
One more time 季節よ うつろわないで
One more time 季節啊 希望你別轉變
One more time ふざけあった 時間よ
One more time 與妳嬉鬧的時光啊

くいちがう時はいつも 僕が先に折れたね
發生爭執的時候 每次都是我先讓步
わがままな性格が なおさら愛しくさせた
這種任性的個性 卻更加地讓人憐愛
One more chance 記憶に足を取られて
One more chance 被記憶絆住
One more chance 次の場所を選べない
One more chance 無法選擇下一個地方

いつでも捜しているよ どっかに君の姿を
無論何時都在尋找 希望能在某處找到妳
向いのホーム 路地裏の窓
對面的月台 小巷的窗戶裡
こんなとこにいるはずもないのに
明明知道妳不可能會在這裡
願いがもしも叶うなら 今すぐ君のもとへ
如果願望能夠實現 我希望馬上到妳身邊
できないことは もうなにもない
如今沒有我辦不到的事
すべてかけて抱きしめてみせるよ
我會賭上一切緊緊擁抱妳

寂しさ紛らすだけなら
如果只是為了排遣寂寞
誰でもいいはずなのに
應該不管是誰都無所謂
星が落ちそうな夜だから
但是在星辰要落下的夜晚
自分をいつわれない
我無法對自己說謊
One more time 季節よ うつろわないで
One more time 季節啊 希望你別轉變
One more time ふざけあった時間よ
One more time 與妳嬉鬧的時光啊

いつでも捜しているよ どっかに君の姿を
無論何時都在尋找 希望能在某處找到妳
交差点でも 夢の中でも
就算在路口 在算在夢中
こんなとこにいるはずもないのに
明知道妳不可能會在這裡
奇跡がもしも起こるなら 今すぐ君に見せたい
如果奇蹟會發生的話 希望馬上能讓妳看到
新しい朝 これからの僕
全新的早晨 從今以後的我
言えなかった「好き」という言葉も
還有過去說不出口的「喜歡妳」

夏の想い出がまわる ふいに消えた鼓動
夏日的回憶在腦中盤旋 突然消失的悸動

いつでも捜しているよ どっかに君の姿を
無論何時都在尋找 希望能在某處找到妳
明け方の街 桜木町で
在黎明的街頭 櫻木町
こんなとこに来るはずもないのに
明明知道妳不可能會來這裡
願いがもしも叶うなら 今すぐ君のもとへ
如果願望能夠實現 我希望馬上到妳身邊
できないことはもう何もない
如今沒有我辦不到的事
すべてかけて抱きしめてみせるよ
我會賭上一切緊緊擁抱妳

いつでも捜しているよ
無論何時都在尋找
どっかに君の破片を
希望在某處找到妳的線索
旅先の店 新聞の隅
旅途上的小店 新聞的角落
こんなとこにあるはずもないのに
明明知道妳根本不可能會出現
奇跡がもしも起こるなら 今すぐ君に見せたい
如果奇蹟會發生的話 希望馬上能讓妳看到
新しい朝 これからの僕
全新的早晨 從今以後的我
言えなかった「好き」という言葉も
還有過去說不出口的「喜歡妳」

いつでも捜してしまう どっかに君の笑顔を
無論何時都在尋找 希望在某處找到妳的笑容
急行待ちの 踏切あたり
在等待快車通過的 平交道
こんなとこにいるはずもないのに
明知道妳不可能會在這裡
命が繰り返すならば 何度も君のもとへ
如果生命能夠重來 無論幾次我都要到妳身邊
欲しいものなど もう何もない
現在我已經 別無所求
君のほかに大切なものなど
除了妳以外我什麼都不想要