星期二, 1月 31, 2012

[Flickr] Flickr API

最近想要來開發一些Flickr的小工具,讓自已貼圖更方便!!
找了其他一個.NET的Flickr .NET API Library ,以下是一些教學資源~

12/02/07 Update:測試心得,登入驗證無法登入通過,想直接自已寫一個api了 XD


以下記錄一些參考連結
官方教學:http://www.flickr.com/services/api/
OAuth and Flickr – Part 2

星期一, 1月 30, 2012

[Alfresco] Pagination of Lucene

使用javascript API的search.query(searchParameters)方法時,
當skipCount超過一千筆時,會無法取得回傳的結果,
導致客製化分頁會失敗。

找到以下這篇跟我遇到一樣的問題:
Improve the skipCount function not to check the permissions.

記錄一下:
This is an enhancement request for paging offset in FTS query called "skipcount". Alfresco don't have to check permission of skipped items when we specify the skipCount. 

(*1 system.max.permissionChecks 1000 as the default) 

I know the paging search itself won't be affected by the permission check as far as I tested it with an out of box webscripts named "children.get. js". So, in this case it works very fine, because this webscript uses "group.getChildGroups(maxItems, skipCount)" with ModelUtil.paging internally, so with this webscripts I can correctly get the result more than the specified number to the permission check. I attached the webscript, please find the sample-webscripts.zip for your reference. 


But, the problem is that if we use the paging offset in FTS query called "skipcount" combined with the Lucene search query in the WebScripts as follows, then it will be affected by the permission check. I attached the webscirpts named paging-result.zip for your reference. 

    var skipCount = 0 + args["skip"]; 
    var searchParams = {}; 
    searchParams.query = "cm\:name:document*"; 
    searchParams.language = "fts-alfresco"; 
    var paging = {}; 
    paging.maxItems = 100; 
    paging.skipCount = skipCount; 
    paging.totalItems = 100, 
    searchParams.page = paging; 
    var results = search.query(searchParams); 
    model["length"] = results.length; 
    model["results"] = results; 

In this case, when we specify the skipcount below the number of system.max.permissionCheck for example 1000 as the default, and set a proper paging value, then it will return the correct result, but the problem is when we specify skipcount over 1,000, then webscripts returns no results (zero items). 
So, the work around is to set over 1,000 to the "system.acl.maxPermissionChecks" , then we can get the results correctly. But increasing this parameter will give more stress to Alfresco server, so that would be nice if we could improve the function of skipCount since Alfresco don't have to check the permission of skipped items when we specify the skipCount. 


請在repository.properties修正以下二個參數
#
# Properties to limit resources spent on individual searches
#
# The maximum time spent pruning results
system.acl.maxPermissionCheckTimeMillis=100000
# The maximum number of results to perform permission checks against
system.acl.maxPermissionChecks=10000

不過當存取超過10000的時候發生以下例外錯誤!!(待續)
目前限制只能取到一層的一萬筆,當該層超過一萬筆後就拿不到資料!!
Transactional update cache 'org.alfresco.cache.node.aspectsTransactionalCache' is full (10000)

星期四, 1月 12, 2012

[Java] 自訂Exception

簡單的自訂例外處理
public class HttpClientException extends Exception{
 
 private String protocol = null;
 private String endpoint = null;
 private String httpMethod = null;
 private String postParameters = null;
 private int statuscode = 0;
 private String msg = null;
 
 public HttpClientException(String msg){
  super(msg);
 }
 
 public HttpClientException(String endpoint,String httpMethod,String postParameters,int statuscode,String msg){
  this.endpoint = endpoint;
  //detect protocal from endpoint
  if(this.endpoint.contains("https"))
   this.protocol = "HTTPS";
  else
   this.protocol = "HTTP";
  
  this.httpMethod = httpMethod;
  this.postParameters = postParameters;
  this.statuscode = statuscode;
  this.msg = msg;
 }
 
 public String getEndPoint(){
  return this.protocol + " Request Endpoint:" + this.endpoint;
 }
 
 public String getHttpMethod(){
  return this.protocol +  " Request Method:" + this.httpMethod;
 }
 
 public String getRequestBody(){
  if(this.postParameters != null)
   return this.protocol + " Request Body:" + this.postParameters;
  else
   return "Can't get request body.";
 }
 
 public String getStatusCode(){
  return this.protocol + " Status Code:" + this.statuscode;
 }
 
 public String getErrorMessage(){
  return this.protocol + " Error Message:" + this.msg;
 }
}

星期三, 1月 11, 2012

[Java] 字串比對搜尋

Java字串搜尋的方法:

  String endpoint = "http://www.google.com.tw";
  System.out.println("string index of http:" + endpoint.indexOf("http://"));
  
  endpoint = "https://www.google.com.tw";
  System.out.println("string index of https:" + endpoint.indexOf("https://"));
  
  System.out.println("string re:" + endpoint.matches("^https://.*"));
  System.out.println("string contain:" + endpoint.contains("http"));

星期一, 1月 09, 2012

[Alfresco] Dot symbol in account

先前寫了一個範例關於在URL上面有uid含有dot符號會發生問題!!
原本以為是alfresco不支援,結果是自已搞錯了XD
會發生以下錯誤!!
GET http:///alfresco/service/test/person/?alf_ticket=
UserName: ken.tsai
後端顯示找不到這個uid的錯誤,因為uid被截斷了
ERROR [extensions.webscripts.AbstractRuntime] Exception from executeScript - redirecting to status template error: 00100007 Web Script format 'tsai' is not registered

參考一下原本的範例程式,發現在webscript xml的描述檔把原本的
   any
改為
   argument
就成功解決了。

後續的釐清程序之後再補

Reference:
Alfresco Web Scripts Wiki

星期一, 1月 02, 2012

console.log throws error on IE8


經測試可用的程式碼如下:
(function($){
 
 $.console = function(logger){
  if(typeof window["console"] != "undefined"){
   console.log(logger);
  }
 };
 
})(jQuery);

缺點要改用自已寫的方式,優點是在ie8有無使用開發者工具都能正常執行網頁。
Reference:
console.log throws error on Internet Explorer IE

星期二, 12月 27, 2011

[Java] Parameterized method in JDBC

JDBC supports many setXXX() methods, one for each Java data type, so that you can set parameter values directly with the desired Java data types without any conversion. Here is a list of setXXX() methods:


[Java] Preventing SQL Injection in Java

一般基礎常犯的執行sql查詢的危險寫法:

conn = pool.getConnection( );
String sql = "select * from user where username='" + username +"' and password='" + password + "'";
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
if (rs.next()) {
loggedIn = true;
 out.println("Successfully logged in");
} else {
 out.println("Username and/or password not recognized");
}


為避免執行sql語句讓hacker使用sql injection,可改用PreparedStatement物件


String selectStatement = "SELECT * FROM User WHERE userId = ? ";
PreparedStatement prepStmt = con.prepareStatement(selectStatement);
prepStmt.setString(1, userId);
ResultSet rs = prepStmt.executeQuery();

如何使用PreparedStatement執行批次

import java.util.*;
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
public class MySqlPreparedStatementBatch {
  public static void main(String [] args) {
    Connection con = null;
    try {
      com.mysql.jdbc.jdbc2.optional.MysqlDataSource ds 
        = new com.mysql.jdbc.jdbc2.optional.MysqlDataSource();
      ds.setServerName("localhost");
      ds.setPortNumber(3306);
      ds.setDatabaseName("HerongDB");
      ds.setUser("Herong");
      ds.setPassword("TopSecret");
      con = ds.getConnection();

// PreparedStatement
      PreparedStatement ps = con.prepareStatement(
 "INSERT INTO Profile (FirstName, LastName) VALUES (?, ?)");

// Provide values to parameters for copy 1
      ps.setString(1,"John");
      ps.setString(2,"First");

// Create copy 1
      ps.addBatch();

// Provide values to parameters for copy 2
      ps.setString(1,"Bill");
      ps.setString(2,"Second");

// Create copy 2
      ps.addBatch();

// Provide values to parameters for copy 3
      ps.setString(1,"Mark");
      ps.setString(2,"Third");

// Create copy 3
      ps.addBatch();

// Provide values to parameters for copy 4
      ps.setString(1,"Jack");
      ps.setString(2,"Last");

// Create copy 4
      ps.addBatch();

// Execute all 4 copies
      int[] counts = ps.executeBatch();
      
      int count = 0;
      for (int i=0; i<counts.length; i++) {
       count += counts[i];
      }
      System.out.println("Total effected rows: "+count);

// Close the PreparedStatement object
      ps.close();

      con.close();        
    } catch (Exception e) {
      System.err.println("Exception: "+e.getMessage());
      e.printStackTrace();
    }
  }
}

Reference:
Preventing SQL Injection in Java PreparedStatement in Batch Mode
如何在 Java 網站應用程式中防範 SQL Injection

[Java] Regex replace matcher

專案有一個需求需要將找到的字元進行相關取代的處理,
由於每一個找到的字元需要經過decode的處理,所以不適用replaceAll方法來處理。
以下找到符合的處理方法:

Reference:http://stackoverflow.com/questions/5568081/regex-replace-all-ignore-case

Avoid ruining the original capitalization:

In the above approach however, you're ruining the capitalization of the replaced word. Here is a better suggestion:
String inText="Sony Ericsson is a leading company in mobile. " +
              "The company sony ericsson was found in oct 2001";
String word = "sony ericsson";
Pattern p = Pattern.compile(word, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(inText);
StringBuffer sb = new StringBuffer();
while (m.find()) {
  String replacement = m.group().replace(' ', '~');
  m.appendReplacement(sb, Matcher.quoteReplacement(replacement));
}
m.appendTail(sb);
String outText = sb.toString();
System.out.println(outText);
Output:
Sony~Ericsson is a leading company in mobile.
The company sony~ericsson was found in oct 2001

星期四, 12月 15, 2011

星期二, 12月 13, 2011

[Alfresco] Search API


Search API Example:
  var def =
  {
     query: "cm:name:test*",
     language: "fts-alfresco"
  };
  var results = search.query(def);

Parameters
search
{
   query: string,          mandatory, in appropriate format and encoded for the given language
   store: string,          optional, defaults to 'workspace://SpacesStore'
   language: string,       optional, one of: lucene, xpath, jcr-xpath, fts-alfresco - defaults to 'lucene'
   templates: [],          optional, Array of query language template objects (see below) - if supported by the language 
   sort: [],               optional, Array of sort column objects (see below) - if supported by the language
   page: object,           optional, paging information object (see below) - if supported by the language
   namespace: string,      optional, the default namespace for properties
   defaultField: string,   optional, the default field for query elements when not explicit in the query
   onerror: string         optional, result on error - one of: exception, no-results - defaults to 'exception'
}

sort
{
   column: string,         mandatory, sort column in appropriate format for the language
   ascending: boolean      optional, defaults to false
}

page
{
   maxItems: int,          optional, max number of items to return in result set
   skipCount: int          optional, number of items to skip over before returning results
}

template
{
   field: string,          mandatory, custom field name for the template
   template: string        mandatory, query template replacement for the template
}

Reference:
Full Text Search Query Syntax
Alfresco.util.DataTable and search maxItems 

What is the maximum length of a URL?

http://www.boutell.com/newfaq/misc/urllength.html

[Java] DataOutputStream 的 writeBytes(String s) 編碼問題!!

Java編碼紀綠:

java 的DataOutputStream 的 writeBytes(String s) 方法對中文編碼會錯誤


public final void writeBytes(String s) throws IOException {

int len = s.length();

for (int i = 0 ; i < len ; i++) {

out.write((byte)s.charAt(i));

}

incCount(len);

}


举个例子,以字符串"你好"作为参数输入,(byte)s.charAt(i) 这句就会导致问题,
因为java里的char类型是16位的,一个char可以存储一个中文字符,在将其转换为 byte后高8位会丢失,
这样就无法将中文字符完整的输出到输出流中。
所以在可能有中文字符输出的地方最好先将其转换为字节数组,然再通过write(byte[] b)方法输出。例:

String s = "你好";

write(s.getBytes());

注意:getBytes沒指定編碼格式的話是使用預設系統的編碼。

2012/02/09更新:
DataOutputStream模擬form post上傳的時候,改用write方法才能解決中文編碼的問題。

  /*
  --boundary\r\n
  Content-Disposition: form-data; name=""; filename=""\r\n
  Content-Type: \r\n
  \r\n
  \r\n
  */ 
  this.dataOutputStream.writeBytes(this.PREFIX);
  this.dataOutputStream.writeBytes(this.boundary);
  this.dataOutputStream.writeBytes(this.CRLF);
  this.dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"");
//  this.dataOutputStream.writeBytes(fieldName);
  this.dataOutputStream.write(fieldName.getBytes());
  this.dataOutputStream.writeBytes("\"; filename=\"");
  //don't support char in Chinese
//  this.dataOutputStream.writeBytes(fileName);
  this.dataOutputStream.write(fileName.getBytes());
  this.dataOutputStream.writeBytes("\"");
  this.dataOutputStream.writeBytes(this.CRLF);
  if(mimeType != null){
   this.dataOutputStream.writeBytes("Content-Type:");
   this.dataOutputStream.writeBytes(mimeType);
   this.dataOutputStream.writeBytes(this.CRLF);
   this.dataOutputStream.writeBytes(this.CRLF);
  }



2012/03/12 更新
今天在別的case之下竟然會讓中文亂碼,所以使用getBytes方法前還是指定你要的編碼比較合適
getBytes(Charset.forName("utf-8"))

Reference:
java 的DataOutputStream 的 writeBytes(String s) 方法在向
java String.getBytes()的問題

其他你感興趣的文章

Related Posts with Thumbnails