星期二, 5月 03, 2011

[JQuery Plugin] Jeditable

本文介紹如何使用Jeditable來實作inline editing。
html source
<div id="talk_sth" >
What's on your mind?
</div>

javascript

$(function(){
//在加了event屬性後似乎會跟onblur事件有衝突。
 $("#talk_sth").editable(
   editableEventHandler, 
     {
        indicator : "",
           tooltip   : "Move mouseover to edit...",
            placeholder : "What's on your mind?",
           //event     : "mouseover",
           type      : "textarea",//編輯元素的樣式
//           submit    : "OK",//顯示ok按鈕
//           cancel    : "Cancel"//顯示cancel按鈕
           onblur : "submit"
     }

    );
});

//透過editableEventHandler處理post json data
function editableEventHandler(value, settings){
    console.log("update status:" + value);
    var endpoint = HOSTNAME + "/alfresco/service/slingshot/profile/userstatus?alf_ticket=" + TICKET;
    var requestBODY = "{'status':'" + value + "'}";
    var result = requestBODY;
    console.log(requestBODY);
    $.ajax({
     type: "POST",
     url: endpoint,
     contentType: "application/json",
     dataType: "json",
     processData: false,
     data: requestBODY, 
     success: function(data){
      alert(data);
     },
     error: function(){
      
     }
  }); 
    //important
    return value;
}
Reference:
Jeditable - Edit In Place Plugin For jQuery

[WordPress] query_post methods

query_posts('page_id=179'); //指定單頁 (page) 的文章編號
query_posts($query_string . "&order=ASC"); //用變數帶入並指定排序
query_posts("cat=-3"); // 3 這個類別編號的不顯式
query_posts('p=5'); //指定單篇文章 (post) 編號
query_posts('pagename=about'); //指定單頁 (page) 的文章主題
query_posts('pagename=parent/child'); //傳回單頁 (page) 的子類別
query_posts('cat=1'); //指顯示這個類別編號的文章
query_posts('category_name=product); //用類別名稱去撈出文章
query_posts('tag=cooking'); //用標籤來撈文章
query_posts('tag=bread,baking'); //可以多標籤來撈文章
posts_per_page=10 每個網頁顯示的文章數目;
query_posts('showposts=5&offset=1'); //秀出5則
query_posts('cat=3&year=2004'); //參數組合查詢

[Javascript] 正則式驗證圖片

常常會用到的javascript 正則式,以下為驗證上傳圖片格式。

$("#filedata").change(function(){
console.log($("#filedata").val());
var selectFile = $("#filedata").val();
var re = /^.*\.(jpg|png|gif|bmp)/;
if(selectFile.match(re) == null){
alert("File format is error.");
$("#updateAvatar").attr("disabled", true);

}else{
$("#updateAvatar").removeAttr("disabled");
}
});

Reference:
JavaScript Regex 的 字串比對(Match) 與 取代(Replace)
Regular Expression (RegExp) in JavaScript

[Json] Convert JSON Object to String javascript

you can user browser native function JSON.stringify to do this
var foo = {};
foo.bar = "new property";
foo.baz = 3;
var jsonString = JSON.stringify(foo);

星期六, 4月 30, 2011

[Java] 快快樂樂安裝Tomcat in Window

本文記錄如果在Window安裝Tomcat伺服器
1.下載tomcat 這裡,下載解壓放在你想放的目錄下
本文是統一放在Apache自動安裝的AppServ目錄下,以方便管理
Tip:現在還有提供Windows Service Installer方便Windows的用戶

2.安裝JAVA JDK 這裡
目前版本為Java 6

3.設定JAVA 環境變數
我的電腦->右鍵->內容-> 進階系統設定(Vista) ->進階 -> 環境變數

在PATH變數里的最後面貼上你JAVA安裝的路徑

;C:\Program Files\Java\jdk1.6.0_19
(注意每個變數前面要用分號隔開)

新增下列所有的環境變數值
變數名稱                                               變數值
JAVA_HOME                                        C:\Program Files\Java\jdk1.6.0_19\
CLASSPATH                                       C:\Program Files\Java\jdk1.6.0_19\lib
CATALINA_HOME                                C:\AppServ\apache-tomcat-6.0.32

註:第三個是選擇性設定

4.測試你的java環境
C:\Program Files\apache-tomcat-6.0.32\bin>java -version
java version "1.6.0_19"
Java(TM) SE Runtime Environment (build 1.6.0_19-b04)
Java HotSpot(TM) 64-Bit Server VM (build 16.2-b04, mixed mode)

5.啟動你的Tomcat

C:\Program Files\apache-tomcat-6.0.32\bin>startup.bat
關掉的話就是將命令提示字元(終端機)關掉即可

6.測試Tomcat
瀏覽器開啟http://127.0.0.1:8080/ 測試tomcat是否有啟動,讀到Tomcat首頁你就完成了 :)

星期六, 4月 23, 2011

[JAVA] 快快樂樂學JAVA JDBC 連接 MySQL

JDBC連接MySQL
使用JDBC連接資料庫存取資料時,必須執行以下三個步驟:

1.用DriverManager載入及註冊適當的JDBC驅動程式
Class.forName("com.mysql.jdbc.Driver");

如果發生Driver not found錯誤訊息改改用
Class.forName("com.mysql.jdbc.Driver").newInstance();

2.用JDBC URL定義驅動程式與資料來源之間的連結,並且建立一個連結物
//option1
String jdbcUrl = "jdbc:mysql://[hostname]:[port]/[dbname]?user=[username]&password=[pwd]";
Connection conn = DriverManager.getConnection(jdbcUrl);

//option2
String jdbcUrl = ""jdbc:mysql://[hostname]:[port]/[dbname]";
Connection conn = DriverManager.getConnection(jdbcUrl,"username","password");

3.建立一個sql陳述句,並利用它來執行SQL語法
Statement stmt = conn.createStatement();


執行陳述句有三種方法:

方法一:取回結果集

ResultSet rs = stmt.executeQuery("sql語法")

//取得每一列資訊
while(rs.next()){
//取得這筆資料的結果
rs.getString(1);
rs.getInt(2);
}


方法二:新增、更新、刪除等等使用

//updateRow為執行成功的列數
int updateRow = stmt.excuteUpdate("sql語法");
方法三:單純判斷執行有無成功使用,回傳boolean
bool success = stmt.execute("sql語法");


[JAVA] 快快樂樂學JAVA RESTful Service using Jersey

本文記錄如何在JAVA+TOMCAT下使用Jersey快速建立RESTful WebService :
感謝Owen血尿付出。

第一步:安裝Eclipse跟Tomcat 6.0.32
第二步:下載Jersey Library 1.6。官網http://jersey.java.net/
第三步:將下載的.jar檔放到Tomcat/lib
核心的lib asm-3.1.jar, jersey-core.jar, jersey-server.jar, jsr-311-api-1.0.jar



第四步:開啟Eclipse,新建一個Dynamic Web Project
第五步:修改專案內的YourProjectName/WebContent/WEB-INF/web.xml,新增以下內容

<servlet>
      <servlet-name>JerseyServlet</servlet-name>
      <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
      <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
      <servlet-name>JerseyServlet</servlet-name>
      <url-pattern>/services/*</url-pattern>
 </servlet-mapping>

第六步:第一個HelloWorld Restful API (支援GET / POST)

星期三, 4月 20, 2011

[Linux] 快快樂樂學Linux指令筆記

如何mount裝置內的共享資料夾

1.設定共用資料夾
裝置->共用資料夾->加入共用資料夾

2.在ubuntu建立一個暫存的目錄
$cd /home
$mkdir temp

3.掛載裝置:D_DRIVE為共用資料夾的名稱
#掛載的共享資料夾目錄名稱 ./要掛載的目錄
$sudo mount -t vboxsf D_DRIVE ./temp

4.卸載所有裝置
$umount -a
=====================================================================
Symbol Link

unlink 其實就跟 rm 一樣罷了,當要移除一個 symbolic link ,有時發現怎樣移不掉,一直說 "unkink: my_symbolic_link/ : is a directory" ,這個訊息就跟使用 rm 去移除一個目錄時的錯誤訊息!原來,在移除一個 symbolic link 時,要留意後面不能加個 "/" !這樣,若 symbolic link 是連到一個目錄時,等同於在對那個目錄做 rm 的動作,才會顯示 "is a directory" 訊息。這時可不能一氣之下用 rm -rf !可會將 link 到的目錄給移除掉的!要額外小心。

#目的地是一個檔案
$ ln -s target_file_path my_file_link
$ unlink my_file_link

目的地是一個目錄
$ln -s target_dir my_dir_link
例如:產生在當前目錄下的symbol link
$sudo ln -s /home/temp/mysite.war

$unlink my_dir_link/
$unlink: my_dir_link/: is a directory
$unlink my_dir_link

Done
=====================================================================
MYSQL

#安裝圖形化介面(ubuntu)
$sudo apt-get install mysql-admin

#連接資料庫
$mysql -u root -p

#離開資料庫
mysql>exit


=====================================================================
RM

#移除整個資料夾
$rm -rf 資料夾名

=====================================================================
ifconfig


#列出網路卡資訊
$ifconfig

#設定網路卡ip
$ifconfig eth10 192.168.0.112

=====================================================================
Apache Web Server


#開啟apcahe
$/etc/init.d/httpd start

#關閉apache
$/etc/init.d/httpd stop

#開機啟動檔路徑,可設定開機執行一些shell script指令
$vim /etc/rc.local

=====================================================================
VI

#搜尋
/ <搜尋的字串>

#強制執行存檔
:w ! tee %

#強制離開
:q!


#刪除一行(離開insert模式)
dd

#全刪除
dG



星期二, 4月 19, 2011

[JQuery] getting URL parameters values

/**
 * 
 * get request url parameters and values
 */
(function($) {
 $.extend({
    getUrlVars: function(){
      var vars = [], hash;
      var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
      for(var i = 0; i < hashes.length; i++)
      {
        hash = hashes[i].split('=');
        vars.push(hash[0]);
        vars[hash[0]] = hash[1];
      }
      return vars;
    },
    
    getUrlVar: function(name){
      return $.getUrlVars()[name];
    }
 });
})(jQuery);

Reference: Get URL parameters & values with jQuery

[JQuery Plugin] 自訂jQuery plugin 教學

記錄jQuery外掛的常見的寫作方法。

第一步:將下面的範例程式複製起來,
這是一個簡單將jQuery物件別名為$號的方法,
可以避免其他Javascript Framework別名衝突的問題!!

(function($) {

})(jQuery);


第一種:我偏好的方式 $.fn與$來擴充jQuery物件的方法
(function($) {
 
//呼叫此方法需要帶入指定的元素,可一定綁定多個元素
   $.fn.helloworld= function() {
        this.each(function(){
             alert('helloworld');
        });
        
    };
    
//不需元素即可呼叫(靜態函式)
    $.helloworld2 = function() {
       alert('helloworld 2');
    };
    
})(jQuery);



第二種:改用extend方法來擴充!!
什麼是extend方法請參考黑大的文章:jQuery extend 的用法

(function($) {
 $.extend({
   helloworld: function(){
    alert('helloworld');
   },
   goodbyeworld: function(){
    alert('goodbyeworld');
   }
 });
})(jQuery);


Reference:
網站製作學習誌 » [jQuery] 自製 jQuery Plugin – Part 1
網站製作學習誌 » [jQuery] 自製 jQuery Plugin – Part 2

星期一, 4月 18, 2011

[Alfresco] login using Jquery

/**
 * authentication
 */

$(function(){
 //dologin
 $("#login_submit").click(function(){
  var username = $("#username").val();
  var password = $("#password").val();
  if(username == "" || password == ""){
   alert("Invalid UserName or Password.");
  }else{
   //call resetful api
   
   var endpoint = "http://localhost:8080/alfresco/service/api/login?u=" + username + "&pw=" + password + "&format=json";
   alert(endpoint);
   $.ajax({
     type: "GET",
     headers: {
                 "Content-Type": "application/json"
     },
     url: endpoint,
     //contentType: "application/json",
     processData: false,
     //data: stringData,
     dataType: "jsonp",
     jsonp:"alf_callback",
     jsonpCallback:"jsonp_callback_login",
     statusCode: {
        404: function() {
          alert('page not found');
        },
     400: function() {
           alert('bad request');
         }
     }
   });
  }
 });
});

function jsonp_callback_login(data){
 alert(data.data.ticket);
}

[Alfresco] alf_ticket VS ticket url parameter

For all the pages under the path /faces/* and Web Scripts with the Web Client authenticator alfresco/wcservice/*, you have to use the ticket parameter.
For all the Web Scripts with a path alfresco/service/ you have to use the alf_ticket parameter and in this case you are using the HTTP Basic Authenticator.



Reference:
http://forums.alfresco.com/en/viewtopic.php?f=4&t=28524

[JQuery] AJAX cross-domain issues

Reference:
jQuery抓取跨網域外的資料(cross-domain) 運用JSONP

[Alfresco] Restful API cross-domain issues

Reference:
Web Scripts:JSON Callbacks



[MSSQL] 安裝錯誤解決方法

問題:升級到 SQL Server 2005 失敗,並出現「安裝程式無法連接到資料庫服務進行伺服器組態。」錯誤訊息。

問題:如果在升級到 SQL Server 2005 期間無法使用通訊埠 1433,則 SQL Server 安裝程式會傳回下列錯誤:

SQL Server 安裝程式無法連接到資料庫服務進行伺服器組態。

解決方案:若要繼續,請終止使用通訊埠 1433 的處理序,並繼續進行 SQL Server 2005 安裝程式:

從命令提示字元執行 netstat -o。
識別使用通訊埠 1433 的應用程式或處理序。
使用 [工作管理員] 來關閉應用程式或終止處理序以釋放通訊埠 1433。
繼續 SQL Server 2005 安裝程式。
如果使用上述步驟仍無法釋放通訊埠 1433,請使用下列其他步驟:

開啟 [控制台] 的 [新增或移除程式]。
選取 [Microsoft SQL Server 2005],再按一下 [變更]。
在 [元件選擇] 頁面上,按一下要升級的 SQL Server 執行個體的選項按鈕,然後按 [下一步]。
在 [功能維護] 頁面上,按一下 [Database Engine],然後按 [下一步]。
按一下 [繼續] 來繼續 SQL Server 2005 的升級作業。

Reference:
對 SQL Server Database Engine 的安裝進行疑難排解

星期四, 4月 14, 2011

md5 image file

string ImageFileName = null;
string StrImageName = null;
string UploadImageFolderPath = Server.MapPath("../Upload/Images/");
string ImageFileExtension;

if (ImageUpload.HasFile)
{
StrImageName = ImageUpload.FileName.ToString();
ImageFileExtension = System.IO.Path.GetExtension(StrImageName);

// GIVE A UNIQUE FILENAME(MD5) TO THE UPLOADED FILE:

MD5CryptoServiceProvider objMD5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] bs = System.Text.Encoding.UTF8.GetBytes(StrImageName);
bs = objMD5.ComputeHash(bs);
System.Text.StringBuilder s = new System.Text.StringBuilder();

foreach (byte b in bs)
{
s.Append(b.ToString("x2").ToLower());
}

StrImageName = s.ToString();

ImageFileName = StrImageName + ImageFileExtension;

// As long as the Image-File-Name is exists in the folder then we are MD5ing again the imgage-file-name:

while (System.IO.File.Exists(UploadImageFolderPath + ImageFileName))
{
MD5CryptoServiceProvider objMD5While = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] bsWhile = System.Text.Encoding.UTF8.GetBytes(StrImageName);
bsWhile = objMD5.ComputeHash(bsWhile);
System.Text.StringBuilder sWhile = new System.Text.StringBuilder();

foreach (byte bWhile in bsWhile)
{
sWhile.Append(bWhile.ToString("x2").ToLower());
}

StrImageName = sWhile.ToString();
ImageFileName = StrImageName + ImageFileExtension;
}

ImageUpload.PostedFile.SaveAs(UploadImageFolderPath + ImageFileName);
}

星期三, 4月 13, 2011

圖片檔案hash

string hash = null;
                using (System.Security.Cryptography.SHA1CryptoServiceProvider sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider())
                {
                    System.Drawing.Imaging.ImageFormat format = System.Drawing.Imaging.ImageFormat.Jpeg;
                    System.Drawing.Image myImage = System.Drawing.Image.FromFile(path + f.ToString());
                    myImage.Save(ms, format);

                    hash = Convert.ToBase64String(sha1.ComputeHash(ms.ToArray()));
                }

星期四, 4月 07, 2011

[ZK] Image setContent using Stream

Aimage stream設定範例
    
URL url = new URL(avatar);
            AImage aimg = new AImage("avatar",url.openStream());
            myPhoto.setContent(aimg);

[Alfresco] upload user avatar using resetful api

Build a uploadavatar.jsp page to test uploadavatar restful api.
The page content is shown as the below:

<form id="avatar" enctype="multipart/form-data"
action="http://ideas-cosa.dyndns.org/alfresco/service/slingshot/profile/uploadavatar?alf_ticket=TICKET_32178fa17bcf3b975e76129dccb78d646466e88d" method="post">
<input type="text" name="username" value="ken"/>
Select a file:
<input type="file" name="filedata" />
<input type="submit" name="button" value="upload" />
</form>

星期二, 4月 05, 2011

HTTP 檔案上傳機制解析 [精華]

HTTP 檔案上傳機制解析 [精華]

[Asp.Net] 重新註冊IIS .NET Framework

以下程式碼為簡單的範例:請自已修正安裝的.net framework路徑

REM This batch file addresses "Server unavailable" error
@echo off

REM "Changing to the Framework install directory"
cd /d C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727

echo "Stopping IIS"
iisreset /stop
echo "----------------------"

echo "Stopping the ASP.NET state service if it is running"
net stop aspnet_state
echo "----------------------"

echo "Re-registering ASP.NET"
aspnet_regiis -i
echo "----------------------"

echo "Restarting IIS"
iisreset /start
echo "----------------------"

星期日, 3月 27, 2011

[ZK] How to download file in ZK

 public void onClick$downloadAgent(Event event){
  
  try {
   Filedownload.save("download/xxx.xls", "application/octet-stream");
  } catch (FileNotFoundException e) {
   System.out.println("FileNotFoundException:" + e.getMessage());
  }
  
 }

[Asp.Net] zip and unzip in asp.net using DotNetZip Library

If you want to create a zip in your asp.net.I suggests that you can use DotNetZip Libriay that is very easy to use.You can get more details in the following link :
DotNetZip Library


Create a downloadable zip within ASP.NET. This example creates a zip dynamically within an ASP.NET postback method, then downloads that zipfile to the requesting browser through Response.OutputStream. No zip archive is ever created on disk.

public void btnGo_Click (Object sender, EventArgs e)
{
  Response.Clear();
  Response.BufferOutput= false;  // for large files
  String ReadmeText= "This is a zip file dynamically generated at " + System.DateTime.Now.ToString("G");
  string filename = System.IO.Path.GetFileName(ListOfFiles.SelectedItem.Text) + ".zip";
  Response.ContentType = "application/zip";
  Response.AddHeader("content-disposition", "filename=" + filename);
  
  using (ZipFile zip = new ZipFile()) 
  {
    zip.AddFile(ListOfFiles.SelectedItem.Text, "files");
    zip.AddEntry("Readme.txt", "", ReadmeText);
    zip.Save(Response.OutputStream);
  }
  Response.Close();
}

星期二, 3月 22, 2011

[Alfresco] Create your first web script

if you want to create customize web script in Alfresco.
You will need to understand:
  • XML for expressing the Web Script description
    • <basename>.<httpmethod>.desc.xml
  • Optionally, JavaScript for writing Web Script behaviour
    • <basename>.<httpmethod>.js
  • Freemarker for rendering a Web Script response
    • <basename>.<httpmethod>.<format>.ftl

星期日, 3月 20, 2011

[XSLT] XSLT Note

XSLT(Extensible StyleSheet Language Transformations)
XSLT是一種把XML文件轉換成XHTML文件或是其他的XML文件的語言。
XPath則是可以操控XML文件的語言,XSLT大量的使用此技術。
XSLT文件是利用stylesheet當作root element的XML文件

Reference:
XSLT Tutorial

星期三, 3月 16, 2011

[ZK] How to pass parameter to another zul page

Today i want to pass parameter to another zul page so i find the solution for using "Executions.createComponents".



arg - java.util.Map(Refer to ZK:The User Guide)
The arg argument passed to the createComponents method in the
org.zkoss.zk.ui.Executions class. It might be null, depending on how
createComponents is called.

It is the same as self.desktop.execution.arg.
params.put("name", "John");
Executions.createComponents("/my.zul", null, params);

Then, in my.zul,

...

Notice that arg is available only when creating the components for the included page, say
my.zul. On the other hand, all events, including onCreate, are processed later. Thus, if you
want to access arg in the onCreate's listener, use the getArg method of the
org.zkoss.zk.ui.event.CreateEvent class.


Testing code is the below:
In the a.zul composer.
final Map<String, Object> map = new HashMap<String, Object>(0);
    map.put("userid",detailsUser.getUserName() );

    Window changepasswordWin = null; 
    changepasswordWin = (Window) Executions.createComponents(
      "/admin/change_password.zul", 
      null,
      map);

In teh b.zul composer.(change_password.zul)
Map<String, Object> args = null;
public void onCreate$changePasswordWin(Event e) throws Exception {
  System.out.println("--ChangePassword changePasswordWin--");
 
  CreateEvent ce = (CreateEvent) ((ForwardEvent) e).getOrigin();
  this.args = ce.getArg();
  System.out.println("pass userid:" + this.args.get("userid"));
  
  //do something
  //....

  System.out.println("--/ChangePassword changePasswordWin--");
 }

星期二, 3月 15, 2011

[ZK] Dynamic to add button and listen event

  Button btnModify = new Button("Modify Password");
                //parent is cell of row
  btnModify.setParent(cell);
  btnModify.setImage("/admin/images/btn/modify_key.png");
  btnModify.addEventListener("onClick", new EventListener() {
         public void onEvent(Event event) throws Exception {
          
           //to do something
          
          } 
   });

[ZK] Messagebox EventListener

捕捉Question Messagebox的事件

//popup messagebox
Messagebox.show("Are you sure?",
      "Question", Messagebox.OK | Messagebox.CANCEL,
      Messagebox.QUESTION, new EventListener() {
       public void onEvent(Event event) throws Exception {
        //if clicks ok to do something
        if (((Integer) event.getData()).intValue() == Messagebox.OK) {
         //to do something
        }
       }
      });

星期五, 3月 04, 2011

PHP ZEND Framwork

http://blog.corausir.org/website-design/ausir-1219
http://www.jaceju.net/blog/archives/category/web-development/php/zend-framework/page/2
http://blog.wu-boy.com/2009/03/24/1060

星期二, 3月 01, 2011

[ZK] ZK Eclipse Setting

From: ZK Essentials/Working with the Sample Applications/Setting Up the Applications Using Eclipse

In the fifth step:
"Once the download is complete, go to Window > Preferences > ZK > ZK Packages, click Add File/Directory to add the ZK package downloaded"

The default ZK Package versioin is 3.6.3, so downloaded the latest one which is zk-bin-5.0.5.zip from zk downloads. Then keep following the fifth step to select the downloaded file and then the latest version could be displayed as an option.

星期四, 2月 24, 2011

[Mysql] SP where in

DROP PROCEDURE IF EXISTS `simpleproc08`$$

CREATE PROCEDURE `simpleproc08`(IN param0 TEXT, OUT param1 INT)
BEGIN
SET @qry = CONCAT('SELECT COUNT(*) INTO @param1 FROM regions WHERE regions_id IN (', param0, ')');
PREPARE stmt FROM @qry;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET param1 = @param1;
END$$

DELIMITER ;

CALL simpleproc08('1, 2, 3', @a);
SELECT @a;
Result:
@a
------
3

[Java] HttpClient

使用Apache Client 實作 Post Get

星期三, 2月 23, 2011

[Alfresco] Authority

AuthorityDAOImpl.java
Language: Java
License: GPL
Copyright: (C) 2005-2007 Alfresco Software Limited.
LOC: 471

AuthorityServiceImpl.java
Language: Java
License: GPL
Copyright: (C) 2005-2007 Alfresco Software Limited.
LOC: 215

Reference:
Repository Cache Configuration
Repository Configuration

星期二, 2月 15, 2011

[Alfresco] Alfresco APIs Reference

if you want to use alfresco APIs to build costomized web application,those are some links as the following
Tips:Navigate to Web Script List:http://localhost:8080/alfresco/service/index
  1. RESTful API (source code path:remote-api/config/alfresco/templates/webscripts/org/alfresco/*)
    1. 3.1 REST API
    2. Deployment REST API
    3. 3.0 REST API
    4. Repository RESTful API Reference
    5. 2.1 REST API
    6. 2.0 RESTful API
    7. OpenSearch
    8. REST Design Guidelines
    9. CMIS RESTful API Reference
  2. 3.4 JavaScript Services API 
  3. JavaScript API Cookbook
  4. Java Foundation API

星期四, 1月 27, 2011

[Alfresco] Peer-Association 範例

BaseWebServiceSystemTest.java 
使用foundation api範例

[Alfresco] Avatar

--UserManager printProperties--
{http://www.alfresco.org/model/content/1.0}name:myfbphoto.jpg
{http://www.alfresco.org/model/system/1.0}node-dbid:20391
{http://www.alfresco.org/model/system/1.0}store-identifier:SpacesStore
{http://www.alfresco.org/model/content/1.0}content:contentUrl=store://2011/1/14/10/30/a9fc0ee8-f528-40c8-b4f2-f53459120a47.bin|mimetype=image/jpeg|size=13245|encoding=utf-8|locale=zh_TW_
{http://www.alfresco.org/model/content/1.0}modified:2011-01-14T10:30:51.377+08:00
{http://www.alfresco.org/model/system/1.0}node-uuid:100cbbf4-39c3-41cc-8d79-a80b112347a2
{http://www.alfresco.org/model/content/1.0}created:2011-01-14T10:30:51.377+08:00
{http://www.alfresco.org/model/system/1.0}store-protocol:workspace
{http://www.alfresco.org/model/content/1.0}creator:Ken
{http://www.alfresco.org/model/content/1.0}modifier:Ken
associationType:{http://www.alfresco.org/model/content/1.0}avatar
{http://www.alfresco.org/model/content/1.0}path:/{http://www.alfresco.org/model/system/1.0}system/{http://www.alfresco.org/model/system/1.0}people/{http://www.alfresco.org/model/content/1.0}ken/{http://www.alfresco.org/model/content/1.0}myfbphoto.jpg
--/UserManager printProperties--

星期三, 1月 26, 2011

[ZK] comfirm in zk component

使用程式控制替元件加入comfirm javascript。
範例如下:
//removePhoto.setWidgetListener("onClick", "alert('test');");
removePhoto.setWidgetListener("onClick", "if(!confirm('Remove Your Picture?')){evt.stop({au:true});}");

A client-side event listener could stop the sending of a widget event to the server by invoking Event.stop(Map) with {au:true}, such as

evt.stop({au: true});

Reference:
ZK Client-side Reference/Notifications/Widget Events
ZK Client-side Reference/Communication/AU Requests/Client-side Firing

星期一, 1月 24, 2011

[Alfresco] AdministrationServiceSystemTest.java

AdministrationServiceSystemTest.java
Language: Java
License: GPL
Copyright: (C) 2005-2007 Alfresco Software Limited.
LOC: 304
使用alfresco webservice提供簡單的User management測試範例,值得參考。


Reference:
AdministrationServiceSystemTest.java 

星期三, 1月 12, 2011

[Windows] 使用 net use 指令連線網路磁碟機

如果想要把連線指定到你本機的磁碟機p:,那可以這樣用
net use p: "\\serverip\foldername" /user:useraccount password /persistent:no

星期日, 1月 09, 2011

[Asp.Net] Https using WebClient

等入驗證之前先補上這一段就可以取得加密的憑證

即可用正常的webclient
try
{
System.Net.ServicePointManager.ServerCertificateValidationCallback =
delegate(object senderX, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
return true;
};
HtmlText = wc.DownloadString(wc.BaseAddress);

}
catch
{
System.Environment.Exit(System.Environment.ExitCode);
}

[Alfresco] Node References and Store Protocols

了解Alfresco的NodeRef與StoreRef的差異。

Reference:
Node References and Store Protocols

SourceCode:
NodeArchiveServiceImpl.java 
NodeRefTest.java
ArchiveAndRestoreTest.java

星期二, 1月 04, 2011

[Alfresco] Content Domain Model Notes

這隻ContentModel.java實作Alfresco Data Domain Model相關的QNAME,
簡單來說,就是把各個Data Domain Model內定義的QNAME,
用程式控制來取得完整的QName String

QNAME Format:{NameSapce}Name
Example:{http://www.alfresco.org/model/content/1.0}content


簡單分析contentModel.xml的結構:
model(root)
  --imports
  --namespaces
  --constrains
  --types
     --title
     --parent
     --archive
     --association
        --child-association
     --properties
        --property
   --aspects
      --aspect
      --title(aspect標題)
      --properties(aspect擁有的屬性集)
        --property
           --title(property標題)
           --type(屬性資料型態)
           --default(資料是否有預設值)
           --protected
           --index
           --mandatory
  --mandotory-aspects
     --aspect
  --associations
     --association
     --child-association

看ContentModel.xml原始碼

Reference:
ContentModel.java

[Alfresco] How to rename User Groups using web services? (4)

重新命名群組,下面程式尚未測試過,僅供參考。

[Alfresco] Node Testing

做了一些實驗的資料:

[Alfresco] delete a specific file without archival

If you want to delete a specific file without archival, then you can just apply the sys:temporary aspect prior to deletion.


nodeService.addAspect(nodeRef, ContentModel.ASPECT_TEMPORARY); 
PS: NodeService is not exposed as WebService API.

Reference:
Archive Store Lucene query
Invoking NodeService instance
Disabling Document Archival


[Alfresco] CMIS (Content Management Interoperability Services)

CMIS (Content Management Interoperability Services) is a standard for improving interoperability between ECM systems. It specifies a domain model plus a set of services and protocol bindings for Web Services (SOAP) and AtomPub.


Reference:
OpenCMIS Cookbook(Sample Code)
CMIS Webservice Wiki(新增的CMIS WS服務)

星期一, 1月 03, 2011

[Alfresco] NodeArchiveServiceImpl

/*
 * Copyright (C) 2005-2010 Alfresco Software Limited.
 *
 * This file is part of Alfresco
 *
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see .
 */
package org.alfresco.repo.node.archive;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.batch.BatchProcessWorkProvider;
import org.alfresco.repo.batch.BatchProcessor;
import org.alfresco.repo.batch.BatchProcessor.BatchProcessWorker;
import org.alfresco.repo.lock.JobLockService;
import org.alfresco.repo.lock.LockAcquisitionException;
import org.alfresco.repo.node.archive.RestoreNodeReport.RestoreStatus;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.ResultSetRow;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.EqualsHelper;
import org.alfresco.util.VmShutdownListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Implementation of the node archive abstraction.
 * 
 * @author Derek Hulley
 */
public class NodeArchiveServiceImpl implements NodeArchiveService
{
    private static final QName LOCK_QNAME = QName.createQName(NamespaceService.ALFRESCO_URI, "NodeArchive");
    private static final long LOCK_TTL = 60000;
    
    private static final String MSG_BUSY = "node.archive.msg.busy";
    
    private static Log logger = LogFactory.getLog(NodeArchiveServiceImpl.class);
    
    private NodeService nodeService;
    private SearchService searchService;
    private TransactionService transactionService;
    private JobLockService jobLockService;

    public void setNodeService(NodeService nodeService)
    {
        this.nodeService = nodeService;
    }

    public void setTransactionService(TransactionService transactionService)
    {
        this.transactionService = transactionService;
    }

    public void setSearchService(SearchService searchService)
    {
        this.searchService = searchService;
    }

    public NodeRef getStoreArchiveNode(StoreRef originalStoreRef)
    {
        return nodeService.getStoreArchiveNode(originalStoreRef);
    }

    public void setJobLockService(JobLockService jobLockService)
    {
        this.jobLockService = jobLockService;
    }

    public NodeRef getArchivedNode(NodeRef originalNodeRef)
    {
        StoreRef orginalStoreRef = originalNodeRef.getStoreRef();
        NodeRef archiveRootNodeRef = nodeService.getStoreArchiveNode(orginalStoreRef);
        // create the likely location of the archived node
        NodeRef archivedNodeRef = new NodeRef(
                archiveRootNodeRef.getStoreRef(),
                originalNodeRef.getId());
        return archivedNodeRef;
    }
    
    /**
     * Get all the nodes that were archived from the given store.
     * 
     * @param originalStoreRef      the original store to process
     * @param skipCount             the number of results to skip (used for paging)
     * @param limit                 the number of items to retrieve or -1 to get the all    
     * 
     * @deprecated          To be replaced with a limiting search against the database
     */
    private ResultSet getArchivedNodes(StoreRef originalStoreRef, int skipCount, int limit)
    {
        // Get the archive location
        NodeRef archiveParentNodeRef = nodeService.getStoreArchiveNode(originalStoreRef);
        StoreRef archiveStoreRef = archiveParentNodeRef.getStoreRef();
        // build the query
        String query = String.format("PARENT:\"%s\" AND ASPECT:\"%s\"", archiveParentNodeRef, ContentModel.ASPECT_ARCHIVED);
        // search parameters
        SearchParameters params = new SearchParameters();
        params.addStore(archiveStoreRef);
        params.setLanguage(SearchService.LANGUAGE_LUCENE);
        params.setQuery(query);
        params.setSkipCount(skipCount);
        params.setMaxItems(limit);
        // get all archived children using a search
        ResultSet rs = searchService.query(params);
        // done
        return rs;
    }
    
    /**
     * @return                      Returns a work provider for batch processing
     * 
     * @since 3.3.4
     */
    private BatchProcessWorkProvider getArchivedNodesWorkProvider(final StoreRef originalStoreRef, final String lockToken)
    {
        return new BatchProcessWorkProvider()
        {
            private VmShutdownListener vmShutdownLister = new VmShutdownListener("getArchivedNodesWorkProvider");
            private Integer workSize;
            private int skipResults = 0;
            public synchronized int getTotalEstimatedWorkSize()
            {
                if (workSize == null)
                {
                    workSize = Integer.valueOf(0);
                    ResultSet rs = null;
                    try
                    {
                        rs = getArchivedNodes(originalStoreRef, 0, -1);
                        workSize = rs.length();
                    }
                    catch (Throwable e)
                    {
                        logger.error("Failed to get archive size", e);
                    }
                    finally
                    {
                        if (rs != null) { rs.close(); }
                    }
                }
                return workSize;
            }
            public synchronized Collection getNextWork()
            {
                if (vmShutdownLister.isVmShuttingDown())
                {
                    return Collections.emptyList();
                }
                // Make sure we still have the lock
                try
                {
                    // TODO: Replace with joblock callback mechanism that provides shutdown hints
                    jobLockService.refreshLock(lockToken, LOCK_QNAME, LOCK_TTL);
                }
                catch (LockAcquisitionException e)
                {
                    // This is OK.  We don't have the lock so just quit
                    return Collections.emptyList();
                }
                
                Collection results = new ArrayList(100);
                ResultSet rs = null;
                try
                {
                    rs = getArchivedNodes(originalStoreRef, skipResults, 100);
                    for (ResultSetRow row : rs)
                    {
                        results.add(row.getNodeRef());
                    }
                    skipResults += results.size();
                }
                finally
                {
                    if (rs != null) { rs.close(); }
                }
                return results;
            }
        };
    }

    /**
     * This is the primary restore method that all restore methods fall back on.
     * It executes the restore for the node in a separate transaction and attempts to catch
     * the known conditions that can be reported back to the client.
     */
    public RestoreNodeReport restoreArchivedNode(
            final NodeRef archivedNodeRef,
            final NodeRef destinationNodeRef,
            final QName assocTypeQName,
            final QName assocQName)
    {
        RestoreNodeReport report = new RestoreNodeReport(archivedNodeRef);
        report.setTargetParentNodeRef(destinationNodeRef);
        try
        {
            // Transactional wrapper to attempt the restore
            RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
            RetryingTransactionCallback restoreCallback = new RetryingTransactionCallback()
            {
                public NodeRef execute() throws Exception
                {
                    return nodeService.restoreNode(archivedNodeRef, destinationNodeRef, assocTypeQName, assocQName);
                }
            };
            NodeRef newNodeRef = txnHelper.doInTransaction(restoreCallback, false, true);
            // success
            report.setRestoredNodeRef(newNodeRef);
            report.setStatus(RestoreStatus.SUCCESS);
        }
        catch (InvalidNodeRefException e)
        {
            report.setCause(e);
            NodeRef invalidNodeRef = e.getNodeRef();
            if (archivedNodeRef.equals(invalidNodeRef))
            {
                // not too serious, but the node to archive is missing
                report.setStatus(RestoreStatus.FAILURE_INVALID_ARCHIVE_NODE);
            }
            else if (EqualsHelper.nullSafeEquals(destinationNodeRef, invalidNodeRef))
            {
                report.setStatus(RestoreStatus.FAILURE_INVALID_PARENT);
            }
            else if (destinationNodeRef == null)
            {
                // get the original parent of the archived node
                ChildAssociationRef originalParentAssocRef = (ChildAssociationRef) nodeService.getProperty(
                        archivedNodeRef,
                        ContentModel.PROP_ARCHIVED_ORIGINAL_PARENT_ASSOC);
                NodeRef originalParentNodeRef = originalParentAssocRef.getParentRef();
                if (EqualsHelper.nullSafeEquals(originalParentNodeRef, invalidNodeRef))
                {
                    report.setStatus(RestoreStatus.FAILURE_INVALID_PARENT);
                }
                else
                {
                    // some other invalid node was detected
                    report.setStatus(RestoreStatus.FAILURE_OTHER);
                }
            }
            else
            {
                // some other invalid node was detected
                report.setStatus(RestoreStatus.FAILURE_OTHER);
            }
        }
        catch (AccessDeniedException e)
        {
            report.setCause(e);
            report.setStatus(RestoreStatus.FAILURE_PERMISSION);
        }
        catch (Throwable e)
        {
            report.setCause(e);
            report.setStatus(RestoreStatus.FAILURE_OTHER);
            logger.error("An unhandled exception stopped the restore", e);
        }
        // done
        if (logger.isDebugEnabled())
        {
            logger.debug("Attempted node restore: "+ report);
        }
        return report;
    }

    /**
     * @see #restoreArchivedNode(NodeRef, NodeRef, QName, QName)
     */
    public RestoreNodeReport restoreArchivedNode(NodeRef archivedNodeRef)
    {
        return restoreArchivedNode(archivedNodeRef, null, null, null);
    }

    /**
     * @see #restoreArchivedNodes(List, NodeRef, QName, QName)
     */
    public List restoreArchivedNodes(List archivedNodeRefs)
    {
        return restoreArchivedNodes(archivedNodeRefs, null, null, null);
    }

    /**
     * @see #restoreArchivedNode(NodeRef, NodeRef, QName, QName)
     */
    public List restoreArchivedNodes(
            List archivedNodeRefs,
            NodeRef destinationNodeRef,
            QName assocTypeQName,
            QName assocQName)
    {
        List results = new ArrayList(archivedNodeRefs.size());
        for (NodeRef nodeRef : archivedNodeRefs)
        {
            RestoreNodeReport result = restoreArchivedNode(nodeRef, destinationNodeRef, assocTypeQName, assocQName);
            results.add(result);
        }
        return results;
    }

    /**
     * Uses batch processing and job locking to purge all archived nodes
     */
    public List restoreAllArchivedNodes(StoreRef originalStoreRef)
    {
        final String user = AuthenticationUtil.getFullyAuthenticatedUser();
        if (user == null)
        {
            throw new IllegalStateException("Cannot restore as there is no authenticated user.");
        }
        
        final List results = Collections.synchronizedList(new ArrayList(1000));
        /**
         * Worker that purges each node
         */
        BatchProcessWorker worker = new BatchProcessor.BatchProcessWorkerAdaptor()
        {
            public void process(NodeRef entry) throws Throwable
            {
                AuthenticationUtil.pushAuthentication();
                try
                {
                    AuthenticationUtil.setFullyAuthenticatedUser(user);
                    if (nodeService.exists(entry))
                    {
                        RestoreNodeReport report = restoreArchivedNode(entry);
                        // Append the results (it is synchronized)
                        results.add(report);
                    }
                }
                finally
                {
                    AuthenticationUtil.popAuthentication();
                }
            }
        };
        doBulkOperation(user, originalStoreRef, worker);
        return results;
    }

    /**
     * Finds the archive location for nodes that were deleted from the given store
     * and attempt to restore each node.
     * 
     * @see NodeService#getStoreArchiveNode(StoreRef)
     * @see #restoreArchivedNode(NodeRef, NodeRef, QName, QName)
     */
    public List restoreAllArchivedNodes(
            StoreRef originalStoreRef,
            NodeRef destinationNodeRef,
            QName assocTypeQName,
            QName assocQName)
    {
        // get all archived children using a search
        ResultSet rs = getArchivedNodes(originalStoreRef, 0, -1);
        try
        {
            // loop through the resultset and attempt to restore all the nodes
            List results = new ArrayList(1000);
            for (ResultSetRow row : rs)
            {
                NodeRef archivedNodeRef = row.getNodeRef();
                RestoreNodeReport result = restoreArchivedNode(archivedNodeRef, destinationNodeRef, assocTypeQName, assocQName);
                results.add(result);
            }
            // done
            if (logger.isDebugEnabled())
            {
                logger.debug("Restored " + results.size() + " nodes into store " + originalStoreRef);
            }
            return results;
        }
        finally
        {
            rs.close();
        }
    }

    /**
     * This is the primary purge methd that all purge methods fall back on.  It isolates the delete
     * work in a new transaction.
     */
    public void purgeArchivedNode(final NodeRef archivedNodeRef)
    {
        RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
        RetryingTransactionCallback deleteCallback = new RetryingTransactionCallback()         {             public Object execute() throws Exception             {                 try                 {                     nodeService.deleteNode(archivedNodeRef);                 }                 catch (InvalidNodeRefException e)                 {                     // ignore                 }                 return null;             }         };         txnHelper.doInTransaction(deleteCallback, false, true);     }      /**      * @see #purgeArchivedNode(NodeRef)      */     public void purgeArchivedNodes(List archivedNodes)     {         for (NodeRef archivedNodeRef : archivedNodes)         {             purgeArchivedNode(archivedNodeRef);         }         // done     }      /**      * Uses batch processing and job locking to purge all archived nodes      */     public void purgeAllArchivedNodes(StoreRef originalStoreRef)     {         final String user = AuthenticationUtil.getFullyAuthenticatedUser();         if (user == null)         {             throw new IllegalStateException("Cannot purge as there is no authenticated user.");         }                  /**          * Worker that purges each node          */         BatchProcessWorker worker = new BatchProcessor.BatchProcessWorkerAdaptor()         {             public void process(NodeRef entry) throws Throwable             {                 AuthenticationUtil.pushAuthentication();                 try                 {                     AuthenticationUtil.setFullyAuthenticatedUser(user);                     if (nodeService.exists(entry))                     {                         nodeService.deleteNode(entry);                     }                 }                 finally                 {                     AuthenticationUtil.popAuthentication();                 }             }         };         doBulkOperation(user, originalStoreRef, worker);     }          /**      * Do batch-controlled work      */     private void doBulkOperation(final String user, StoreRef originalStoreRef, BatchProcessWorker worker)     {         String lockToken = null;         try         {             // Get a lock to keep refreshing             lockToken = jobLockService.getLock(LOCK_QNAME, LOCK_TTL);             // TODO: Should merely trigger a background job i.e. perhaps it should not be             //       triggered by a user-based thread             BatchProcessor batchProcessor = new BatchProcessor(                     "ArchiveBulkPurgeOrRestore",                     transactionService.getRetryingTransactionHelper(),                     getArchivedNodesWorkProvider(originalStoreRef, lockToken),                     2, 20,                     null, null, 1000);             batchProcessor.process(worker, true);         }         catch (LockAcquisitionException e)         {             throw new AlfrescoRuntimeException(MSG_BUSY);         }         finally         {             try             {                 if (lockToken != null ) {jobLockService.releaseLock(lockToken, LOCK_QNAME); }             }             catch (LockAcquisitionException e)             {                 // Ignore             }         }     } }

其他你感興趣的文章

Related Posts with Thumbnails