星期一, 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             }         }     } }

星期三, 12月 29, 2010

[Alfresco] TrashcanDialog.java

印出lucene query string的結果,方便追踨。


Print Var.
Repository.getStoreRef():

workspace://SpacesStore

property.getArchiveRootRef():
archive://SpacesStore/20f1f650-07d2-4a93-b464-ac8e9f5ecf59

getArchiveRootRef().getStoreRef()
archive://SpacesStore

private final static String NAME_ATTR = Repository.escapeQName(ContentModel.PROP_NAME);
\{http\://www.alfresco.org/model/content/1.0\}name


private final static String USER_ATTR = Repository.escapeQName(ContentModel.PROP_ARCHIVED_BY);
\{http\://www.alfresco.org/model/system/1.0\}archivedBy


private final static String DATE_ATTR = Repository.escapeQName(ContentModel.PROP_ARCHIVED_DATE);
\{http\://www.alfresco.org/model/system/1.0\}archivedDate


System.out.println(ContentModel.PROP_NAME);
{http://www.alfresco.org/model/content/1.0}name

System.out.println(ContentModel.PROP_ARCHIVED_BY);
{http://www.alfresco.org/model/system/1.0}archivedBy

System.out.println(ContentModel.PROP_ARCHIVED_DATE); 
{http://www.alfresco.org/model/system/1.0}archivedDate

property.getArchiveRootRef():
      archive://SpacesStore/20f1f650-07d2-4a93-b464-ac8e9f5ecf59

Search Filter Rule:

search for ALL items in the archive store:
       PARENT:"archive://SpacesStore/20f1f650-07d2-4a93-b464-ac8e9f5ecf59" AND ASPECT:"{http://www.alfresco.org/model/system/1.0}archived"

search for user 
@\{http\://www.alfresco.org/model/system/1.0\}archivedBy:test1 AND PARENT:"archive://SpacesStore/20f1f650-07d2-4a93-b464-ac8e9f5ecf59" AND ASPECT:"{http://www.alfresco.org/model/system/1.0}archived"

search for user & today
@\{http\://www.alfresco.org/model/system/1.0\}archivedDate:[2010\-12\-30T00\:00\:00 TO 2010\-12\-30T14\:10\:41] AND @\{http\://www.alfresco.org/model/system/1.0\}archivedBy:test1 AND PARENT:"archive://SpacesStore/20f1f650-07d2-4a93-b464-ac8e9f5ecf59" AND ASPECT:"{http://www.alfresco.org/model/system/1.0}archived"

search for user & last 7 today
@\{http\://www.alfresco.org/model/system/1.0\}archivedDate:[2010\-12\-23T14\:12\:13 TO 2010\-12\-30T14\:12\:13] AND @\{http\://www.alfresco.org/model/system/1.0\}archivedBy:test1 AND PARENT:"archive://SpacesStore/20f1f650-07d2-4a93-b464-ac8e9f5ecf59" AND ASPECT:"{http://www.alfresco.org/model/system/1.0}archived"

Reference:
NodeArchiveService
Archive Store Lucene query
Calling Alfresco Web Services from C# 
TrashcanDialog.java  (source code)

[Alfresco] Lucene Language Note

Lucene Language

This is the recommended language as it is supported by the recommended indexer.
The query language is described on the Lucene site http://lucene.apache.org/java/2_4_0/queryparsersyntax.html. The QueryParser has been modified to allow wild cards at the start of wild card query elements otherwise the syntax is the same.
Note that certain characters need to be escaped in the query string. There is support to do this on a static method on the LuceneQueryParser.
The following fields are available

[Windows] Route

路由設定Command
ROUTE [-f] [-p] [-4|-6] command [destination]
                  [MASK netmask]  [gateway] [METRIC metric]  [IF inter

  -f           清除所有閘道項目的路由表。如果這與其中
               一個命令一起使用,將會在執行命令之前
               清除表格。

  -p           與 ADD 命令一起使用時,路由在系統開機期間
               可持續。依預設,系統重新啟動時並不會
               保留路由。對於會影響適當的持續路由的
               所有其他命令則會略過。Windows 95
               中不支援此選項。

  -4           強制使用 IPv4。

  -6           強制使用 IPv6。

  command      下列其中一個:
                 PRINT     列印路由
                 ADD       新增路由
                 DELETE    刪除路由
                 CHANGE    修改現有的路由
  destination  指定主機。
  MASK         指定下一個參數是 'netmask' 值。
  netmask      指定此路由項目的子網路遮罩值。
               如果沒有指定,將預設為 255.255.255.255。
  gateway      指定閘道。
  interface    指定之路由的介面號碼。
  METRIC       指定計量,例如目的地的成本。

目的地使用的所有符號名稱將會在網路資料庫檔案 NETWORKS
中查詢。閘道的符號名稱是在主機名稱資料庫檔案 HOSTS 中查詢。

如果是 PRINT 或 DELETE 命令,目的地或閘道可以是萬用字元
(指定星號 '*' 為萬用字元),或可以省略閘道引數。

如果目的地包含 * 或 ?,便會視為殼層模式,且只會列出相符的
目的地路由。'*' 表示與任何字串相符,
而 '?' 表示與任何一個字元相符。範例: 157.*.1, 157.*, 127.*, *224*。

只有 PRINT 命令才允許模式對應。
診斷注意事項:
    不正確的 MASK 會產生錯誤,例如當 (DEST & MASK) != DEST 時。
    範例> route ADD 157.0.0.0 MASK 155.0.0.0 157.55.80.1 IF 1
          路由新增失敗: 指定的遮罩參數不正確。
(Destination & Mask) != Destination。

範例:

    > route PRINT
    > route PRINT -4
    > route PRINT -6
    > route PRINT 157*          ....只列印符合 157* 的項目

    > route ADD 157.0.0.0 MASK 255.0.0.0  157.55.80.1 METRIC 3 IF 2
                   目的地^      ^遮罩      ^閘道            計量^    ^
                                                               介面^
      如果沒有指定 IF,將會嘗試為指定的閘道尋找最佳的介面。
    > route ADD 3ffe::/32 3ffe::1

    > route CHANGE 157.0.0.0 MASK 255.0.0.0 157.55.80.5 METRIC 2 IF 2

      CHANGE 只用來修改閘道及 (或) 計量。

    > route DELETE 157.0.0.0
    > route DELETE 3ffe::/32


Testing:
route add 10.15.3.97 mask 255.255.255.255 192.168.123.1 (gateway:vpn route ip)

星期五, 12月 24, 2010

[Alfresco] 目錄


Alfresco的檔案放置目錄結構,此版本為3.4.5

../alf_data
        /audit.contentstore
        /backup-lucene-indexes
        /contentstore
        /contentstore.deleted (deleted objects)
        /lucene-indexes

星期四, 12月 16, 2010

[Alfresco WebService]Ticket could not be found when calling callback handler

三種解法Aflreso Webserver login後Ticket有時候會無法正常取得的方法:

1 - start new session for for every separate thread.
2 - store authenticationDetails in the user's session, and use it to call the webservice

登入後使用session keep AuthenticationDetails 物件
AuthenticationUtils.startSession("user", "password");
    request.getSession().setAttribute("authenticationDetails", AuthenticationUtils.getAuthenticationDetails());
每次呼叫WebService時,把session中的AuthenticationDetails在設定回去
AuthenticationUtils.setAuthenticationDetails((AuthenticationDetails) req.getSession().getAttribute("authenticationDetails"));
Node[] nodes = repositoryService.get(new Predicate(null,spacesStore, qt));

3 - Modify AuthenticationUtils to store authenticationDetails in session instead of ThreadLocal, rebuild the SDK.

Reference:
Ticket could not be found when calling callback handler

星期二, 12月 14, 2010

[Wordpress] posts 相關


wp_posts table
--post_status:inherit,draft,publish,trash,auto-draft,pending
--post_type:attachment,nav_menu_item,page,post,revision


























星期二, 12月 07, 2010

[ZK] borderlayout Executions.createComponents

目前jsp頁面使用borderlayout zk tag遇到的問題
直接call jsp file 會出現"org.xml.sax.SAXParseException: The markup in the document preceding the root element must be well-formed."

有人提到的解法



你不能用Executions.createComponents來做,必須用一個include Component 或 iframe component 以setSrc的方式來操作。

星期一, 12月 06, 2010

[Java] Java如何讀取與寫入properties file Reading and Writing a Properties File

Properties properties = new Properties();
try {
properties.load(new FileInputStream("filename.properties"));
} catch (IOException e) {
}

// Write properties file.
try {
properties.store(new FileOutputStream("filename.properties"), null);
} catch (IOException e) {


上面寫法路徑一直讓我讀不到,採用package path是正確可以讀到的

資源的package path:local.my.properties
String repositoryLocation = null;
// create an instance of properties class
Properties props = new Properties();
URL url = Thread.currentThread().getContextClassLoader().getResource("local/my.properties");
try {
props.load(url.openStream());
// props.load(in);
repositoryLocation = props.getProperty(propertyName);
System.out.println("property:" + repositoryLocation);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return repositoryLocation;

後記:2012/03/22
使用以上作法會造成to many file open的議題產生(開檔後未關檔),不應該每要一個屬性就開properties檔案一次。可參考以下解法:
loading properties file from java package
When loading the Properties from a Class in the package com.al.common.email.templates you can use
Properties prop = new Properties();
InputStream in = getClass().getResourceAsStream("foo.properties");
prop.load(in);
in.close()
(Add all the necessary exception handling).
If your class is not in that package, you need to aquire the InputStream slightly differently:
InputStream in = getClass().getResourceAsStream("/com/al/common/email/templates/foo.properties");
Relative paths (those without a leading '/') in getResource()/getResourceAsStream() mean that the resource will be searched relative to the directory which represents the package the class is in.
Using java.lang.String.class.getResource("foo.txt") would search for the (inexistent) file/java/lang/String/foo.txt on the classpath.
Using an absolute path (one that starts with '/') means that the current package is ignored.

Reference:
Java Properties file examples

[Asp.Net] 将截断字符串或二进制数据。 语句已终止。

将截断字符串或二进制数据。语句已终止。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。

异常详细信息: System.Data.SqlClient.SqlException: 将截断字符串或二进制数据。
语句已终止。


今天page執行sp產生的以上的錯誤訊息(架在簡體的機器上Orz),原來是sp裡面插入暫存table所宣告的欄位長度過小而引起的錯誤。

星期日, 12月 05, 2010

[Asp.Net] URL Rewrite 懶人包心得

記錄使用rewrite相關問題解法。
最後使用免費的套件來ISAPIRewrite處理
(如有其他需求可參考這篇Tip/Trick: Url Rewriting with ASP.NET )
不過順利解決完rewrite的問題後。
又遇到二個問題需要處理lol~不過解法都在找到的資料裡面,
以下只是記錄一下流程跟心得:)

星期五, 12月 03, 2010

[CSS] 解決div無法滿版的問題

修正DOCTYPE xhtml DIV無法滿版的問題,請加入以下語法。
html, body { margin: 0; padding: 0; height: 100%; border:none; }
之後的div內的heigth:100%就可以正常

Reference:
TIPS-Get 100% Height in XHTML

星期三, 12月 01, 2010

A Coder’s Guide to Writing API Documentation

A Coder’s Guide to Writing API Documentation

Peter Gruenbaum

Ever been in a situation where your manager asks you to write documentation for the APIs that you developed? Let’s face it, if you’re like most developers, you love to code and hate to write. Furthermore, writing takes time away from critical tasks you need to do, such as feature development and bug fixing.
It’s no surprise that API documentation often ends up being frustrating and confusing for the reader—it rarely gets the attention it deserves.
This article is a guide on how to write API documentation. I’ll describe the most important components of API documentation and provide some suggestions about how to make it effective. I’ll also give you some hints for creating good overviews, sample code and reference material, including where you should focus your time and attention to get the best effect.

星期二, 11月 30, 2010

[ZK] ZK Ajax Framework

最近專案需求使用JAVA EE來開發,評估之後決定選用ZK Framework來作為前端UI設計,感覺很類似.net的元件,有很多現成的componets可以使用。重點是台灣軟體公司所開發的,一定要支持一下國貨。

星期一, 11月 29, 2010

[JSP] include(import) file with parameter

2. Include Directive 載入指令
include 指令
在編譯時期包括(include)另一個網頁,或是在執行時期包括另一個網頁,是一種靜態的指定方式,而不能傳送參數,使用指令元素include的對象通常是一個靜態網頁。

<%@page contentType="text/html; charset=big5"%>
<%@include file="header.inc"%>
<H1><B>include示範</B><H1>
<%@include file="foot.inc"%>

<%@ include %> v.s. <jsp:include>

<%@ include %> 主要是include靜態網頁
包含的文件視為同一份文件,被include的頁面裡面所宣告的變數,可以被主頁面直接拿來引用。
例如說在a.jsp 定義String a="aaa";
在b.jsp用<%@ include %> 把a.jsp 包含進來後,可視a.jsp跟b.jsp為同一份,所以不用再宣告String a(再宣告會有錯誤),可直接用a = "abcc";

<jsp:include> 可以include 動、靜態網頁
使用<jsp:include> 則不行,需透過<jsp:param......的方式傳參數才可被引用,承上例,如果用<jsp:include> 包含a.jsp,若直接打a = "abcc";,肯定出錯,因為他不把a.jsp跟b.jsp視為同一分文件

JSP 學習_3_語法 Directive Elements 指令元素

星期日, 11月 28, 2010

[JSP] JSP Tag Library in Eclipse

今天在要自訂 JSP Tag Library無法正確的import javax.servlet.jsp.tagext.*;
記得把安裝tomcat裡面的lib目錄,將 jsp-api.jarservlet-api.jar加到你專案的
WEB-INF/lib目錄下。
 ps:請不要將lib內在自訂子目錄來分類你的jar,會讀不到jar

星期四, 11月 25, 2010

[JSP] JSTL (JavaServer Pages Standard Tag Library 1.1) JSP標準標籤函式庫

JSTL提供的標籤庫分作五個大類:

[JSP] EL(Expression Language)

EL:變數
屬性範圍 在EL中的名稱
Page        pageScope
Request   requestScope
Session   sessionScope
Application applicationScope

PS:
1自動搜尋範圍 page->request->session->application
2 ${}在jsp 2.0中是特殊字元,JSP容器會自動將它當成EL來執行,因此假若要列印${}時,需在$前加上\,如:\${XXXXXX}

[Eclipse] Import & Export *.jar library

最近在新建的 eclipse專案匯入其他專案的jar檔時,常常會發生path錯誤無法編譯的問題。
找了一下其他人的解決方案,不過目前採用UserLibraries跟 Web-INF/lib裡面都有引入需要的jar,好像才不會有問題。

星期三, 11月 24, 2010

[Eclipse] 快速鍵

 Eclipse 快速鍵 佛心大整理:

The server does not support version 3.0 of the J2EE Web module specification

今天遇到在windows剛裝好eclipse執行測試的專案時,
在設定Servers遇到以下錯誤:

The server does not support version 3.0 of the J2EE Web module specification

原來新增的專案用的是Tomcat 6.0,jdk都是用的1.6
而Tomcat 6.0最多支持Servlet 2.5

解决如下:

在專案根目錄下有一個.settings的目錄下,找到以下文件
org.eclipse.wst.common.project.facet.core.xml文件
内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="jst.web"/>
<fixed facet="wst.jsdt.web"/>
<fixed facet="java"/>
<installed facet="java" version="1.5"/>
<installed facet="jst.web" version="3.0"/>
<installed facet="wst.jsdt.web" version="1.0"/>
</faceted-project>

把<installed facet="jst.web" version="3.0"/>改為 <installed facet="jst.web" version="2.5"/> 

星期二, 11月 23, 2010

[Eclipse] WINDOWS 設定 JAVA 環境變數

環境變數若有需要設定,建議是設定在 "系統變數":
PATH=C:\Program Files (x86)\Java\jdk1.6.0_XX\bin;
CLASSPATH=.;C:\Program Files (x86)\Java\jdk1.6.0_XX\lib;C:\Program Files (x86)\Java\jdk1.6.0_XX\lib\tools.jar;


Tip1:win7 啟動 tomcat 請將系統的JRE或JDK下的\bin\把msvcr71.dll手動copy到tomcat下的\bin\


Tip2:目前整合的IDE介面大多不需要額外設定環境變數 

星期一, 11月 22, 2010

WebDAV (Web Distributed Authoring and Versioning) using .Net C#

WebDAV(Web Distributed Authoring and Versioning)為一個HTTP/1.1通訊協定的延伸建議RFC-2518,讓用戶端使用者可以透過網路來進行網頁內容的編輯工作。
WebDAV透過HTTP/1.1通訊協定標準,提供簡單的檔案輸入/輸出(simple File I/O)的功能,包含:
  • 建立、修改、刪除檔案及瀏覽目錄和檔案。
  • 讀取檔案與目錄的屬性(properties)。
  • 簡單的檔案鎖定。
WebDAV提供幾個新的HTTP指令,包含:
  • GET:讀取WebDAV目錄下的檔案內容。
  •  PUTPOST:傳送檔案內容到伺服器WebDAV目錄下。
  •  PROPFINDPROPPATCH:讀取、設定檔案屬性。
  • COPYMOVECOPY複製目錄、或檔案,MOVE移動檔案。限於同一個WebDAV目錄操作。COPY時若無此路逕時會自動產生,COPY複製範圍也包括其子目錄。
  • MKCOL:建立一個目錄。
  • DELETE:刪除一個檔案或目錄。
  • LOCKUNLOCK:鎖定檔案、解除檔案鎖定。
  • SEARCH:使用SQL語法搜查檔案內容,可使用全文檢索,僅適用於Exchange 2000 Server共用資料匣。 
安裝Windows 2000IE 5、或Office 2000的用戶端電腦,具有權限的使用者,就可以針對IIS的虛擬目錄來發行、鎖定、管理Web的資源,將文件發行至Web伺服器,及在Web目錄中處理檔案,包含:
  • 移動、複製檔案:擁具權限的使用者可以在WebDAV目錄中移動、複製檔案。
  • 修改檔案:擁具權限的使用者可以讀取、修改寫入檔案的內容。
  •  鎖定檔案:多位使用者可以同時讀取同一個檔案,讀取時會將檔案鎖定,因此同時只有一人可以修改同一個檔案。
  • 搜尋檔案:連線到WebDAV目錄後,就可以搜尋WebDAV目錄中的檔案與內容,譬如搜尋到所有由Jack所建立的檔案,或者搜尋所有含有IIS關鍵字的檔案。



Reference:
WebDAV .NET
WebDav and Outlook Appointments in .NET
網際網路新通訊協定---WebDAV

星期一, 11月 15, 2010

[WordPress] 蒐集

研究wordpress找的相關文章記錄。

Reference:
用query_posts列出特定範圍文章 (2)語法 | WordPress不用插件直接實現五種文章代碼
wordpress code – wp_list_pages() 網誌分頁
[WordPress] 自己做友情隨機連結頁面
WordPress外掛【WP Page Numbers】分頁導航、內建5種樣式任君選擇
Codex:Creating a New Page
Codex:Creating a User Page

 

[WordPress] 基本語法擷錄 (轉)

(一)WordPress基本模板文件
一套完整的WordPress模板應至少具有如下文件:
style.css : CSS(樣式表)文件
index.php : 主頁模板
archive.php : Archive/Category模板
404.php : Not Found 錯誤頁模板
comments.php : 留言/回覆模板
footer.php : Footer模板
header.php : Header模板
sidebar.php : 側欄模板
page.php : 內容頁(Page)模板
single.php : 內容頁(Post)模板
searchform.php : 搜索表單模板
search.php : 搜索結果模板
當然,具體到特定的某款模板,可能不止這些文件,但一般而言,這些文件是每套模板所必備的。

星期日, 11月 14, 2010

[C# WinForm]Notifyicon with contextmenu and no form

實作沒有表單的contextMenu
using System;using System.Windows.Forms;
using System.Threading;using System.Drawing;
namespace WindowsApplication9
{   static class Program   {
      [STAThread]      static void Main()
      {        
         Application.EnableVisualStyles();         
         Application.SetCompatibleTextRenderingDefault(false);         
         NotifyIcon notifyIcon1 = new NotifyIcon();                
         ContextMenu contextMenu1 = new ContextMenu();        
         MenuItem menuItem1 = new MenuItem();
         contextMenu1.MenuItems.AddRange(new MenuItem[] { menuItem1 });
         menuItem1.Index = 0;
         menuItem1.Text = "E&xit";
         menuItem1.Click += new EventHandler(menuItem1_Click);
         notifyIcon1.Icon = new Icon("app.ico");
         notifyIcon1.Text = "Form1 (NotifyIcon example)";
         notifyIcon1.ContextMenu = contextMenu1;
         notifyIcon1.Visible = true;         Application.Run();
         notifyIcon1.Visible = false;
      }
      private static void menuItem1_Click(object Sender, EventArgs e)
      {         Application.Exit();
      }
   }
}
Reference: Notifyicon with contextmenu and no form

[VS Studio] vshost.exe 是做什麼用啊

接下來的問題是,如果程式要出貨想關閉這個功能要怎麼做呢?
只要選取 Project | Properties | Debug,將 Enable the Visual Studio hosting process 選項前的鉤鉤取消即可。

Reference:
[C#]一堆 ***.vshost.exe 是做什麼用啊
裝載處理序 (vshost.exe)

星期日, 11月 07, 2010

[Java] Hello World with Ant

本篇是一個Ant的基本教學,試用於初學者。
只是把Apache Ant User Manual-HelloWorld with Ant裡的範例重新記錄下來而已。
有樣版以後寫起ant會比較方便:)

[C# WinForm]在程式中開啟 檔案總管

    EXPLORER.EXE [/n][/e][,/root,][[,/select],

    /n:會針對每一個選取的項目,以單窗格 (我的電腦) 檢視方式開啟一個新視窗,
    即使新視窗與已開啟的視窗重複
    也一樣。
    
    /e:會使用 Windows 檔案總管檢視。Windows 檔案總管檢視十分類似
    Windows 3.x 版中的檔案管理員。請注意,預設檢視為
    開啟檢視。
    
    /root,:會指定所指定之檢視的根層級。預設 是使用標準命名空間根目錄 ( 桌面)。所指定的就是顯示器的根目錄 。  /select,:會指定成為初始焦點的資料夾 。如果使用 "/select",則會開啟
    上層資料夾,並選取所指定的物件。
    • "My Computer" highlighted in left side with all drives visible but not expanded and C: highlighted in right side: %SystemRoot%explorer.exe /e,/select,c:
    • Desktop highlighted and nothing expanded: %SystemRoot%explorer.exe /e,/n,/select,/root,c:
    • All drives visible and the system drive highlighted and expanded in full screen: %SystemRoot%explorer.exe /e,/select
    • All drives visible and the system drive expanded in small screen: %SystemRoot%explorer.exe /e,/select,%systemroot%
    • Only Windows Directory visible highlighted and expanded: %SystemRoot%explorer.exe /e,/root,%systemroot%
    • All drives visible but only C: highlighted and expanded: %SystemRoot%explorer.exe /e,c:
    • Nothing expanded and My Computer highlighted in right side: %SystemRoot%explorer.exe /n,/e,/select,
    • Opens the Windows folder as a folder: %SystemRoot%explorer.exe %systemroot%
    • Opens as "My Computer": %SystemRoot%explorer.exe %systemroot%,
    • This opens the Desktop folder with "My Computer" highlighted: %SystemRoot%explorer.exe %systemroot%,/select,
    • "Desktop" highlighted in the left side and no drives visible:
      %systemroot%explorer.exe /e,/root,::{20D04FE0-3AEA-1069-A2D8-08002B30309D},/select
    • "My Computer" highlighted in left side and all drives visible but none expanded:
      %systemroot%explorer.exe /e,/root,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}
    • "Desktop" in left side highlighted and "My Computer" highlighted in right side and no drives visible:
      %systemroot%explorer.exe /e,/select,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}

    Reference:
    在程式中開啟 檔案總管 (Using C#)
    如何開啟檔案總管在想要的目錄.

    星期五, 10月 29, 2010

    [Asp.Net] MasterPage ContentPage UserContrl 操作

    MasterPage 取得 ContentPage 內的 Control
    MasterPage 取得 ContentPage 內的 UserControl

    反之

    ContentPage 取得 MasterPage 內的 Control
    ContentPage 取得 MasterPage 內的 UserControl

    [Java] Create a coutom tag

    Reference:
    [JAVA] Tag 自訂標籤簡介

    [SVN] 轉貼: SVN in ubuntu

    SVN 功能介紹

    SVN安裝: $ sudo apt-get install subversion

    [Ant]Ubuntu using Ant Note

    1.Installation
    $apt-get install ant

    2.checked ant version
    $ant -version

    you should see
    Apache Ant version 1.7.1 compiled on July 2 2010


    3.ant build
    $ant

    if you didnt create build .xml , you should see
    Buildfile: build.xml does not exist!
    Build failed

    星期日, 10月 24, 2010

    [WebService C#]Call a Java WebService using WCE 3.0 and C#

    今天使用.net呼叫java WebService,學習到了動態叫用WebService的需求(待改良XD),不過又遇到另一個ws-seculity的error,原來還需要裝Web Service Enhancement 3.0來達到更安全的叫用WebService。

    Rewrite Module

    首先先在ISAPI 引入IIRF.dll

    在當前目錄創見檔案iirf.ini

    範例
    RewriteEngine ON
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^/([A-Z0-9]+).html$ /ShowExam.php?xid=$1

    星期三, 10月 20, 2010

    Toshiba M11 Drivers for Windows 7

    拿到公司新配的Toshiba筆電,本來以為是Thinkpad的,小失望了一下。
    用了二天之後真是大失望,很多小細節都考慮不周到呀。
    只設計二個usb孔是啥小?

    有在找驅動的朋友就到以下這二個網址下載吧XD。官方提供的驅動真不完全。
    Reference:
    Toshiba Tecra M11 Drivers For Windows 7
    Toshiba Tecra M11 Drivers For Windows 7 (64 Bit)

    星期六, 10月 16, 2010

    FaceBook Api 筆記

    最近有專案需使用FACEBOOK API,把學習的資料記錄在這篇文章中。
    透過Google大神也找到人家整理不錯的筆記 :)Facebook API宅學習。
    這次專案是使用php script,需要的人可以參考 PHP-SDK Sample

    星期四, 10月 14, 2010

    [PHP] 初探 php

    如題,剛開始測php,從簡單的mysql測試開始Orz

    檢查頁面是否有Session
    //放在頁面的最上端
    <?session_start();>
    
    清除頁面Session
    <?
    //將session清空
    unset($_SESSION['username']);
    echo '登出中......';
    >
    


    [PHP] IDE 工具

    開始寫php的專案,查詢一下有啥好用的IDE開發環境,最好還是選用Eclipse for PHP
    朝Free下手。

    星期六, 10月 02, 2010

    [Asp.Net] Pinging using asp.net

    要使用ping類別之前,需引入using System.Net.NetworkInformation;

    public class SitePinged : System.Web.Services.WebService {
    
        public SitePinged () {
    
            //如果使用設計的元件,請取消註解下行程式碼 
            //InitializeComponent(); 
        }
    
        [WebMethod]
        public string Ping(string site)
        {
            Ping wsPing = new Ping();
            PingReply wsPingReply = wsPing.Send(site);
            return wsPingReply.Status.ToString();
        }
        
    }
    

    其他你感興趣的文章

    Related Posts with Thumbnails