mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Moving to root below branch label
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
42
source/java/org/alfresco/util/ApplicationContextHelper.java
Normal file
42
source/java/org/alfresco/util/ApplicationContextHelper.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* Helper class to provide static and common access to the Spring
|
||||
* {@link org.springframework.context.ApplicationContext application context}.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class ApplicationContextHelper
|
||||
{
|
||||
/** location of required configuration files */
|
||||
public static final String[] CONFIG_LOCATIONS = new String[] { "classpath:alfresco/application-context.xml" };
|
||||
|
||||
/**
|
||||
* Instantiates a new application context.
|
||||
*
|
||||
* @return Returns a new application context
|
||||
*/
|
||||
public static ApplicationContext getApplicationContext()
|
||||
{
|
||||
return new ClassPathXmlApplicationContext(CONFIG_LOCATIONS);
|
||||
}
|
||||
}
|
94
source/java/org/alfresco/util/BaseAlfrescoSpringTest.java
Normal file
94
source/java/org/alfresco/util/BaseAlfrescoSpringTest.java
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
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.security.AuthenticationService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
|
||||
/**
|
||||
* Base Alfresco test.
|
||||
*
|
||||
* Creates a store and root node that can be used in the tests.
|
||||
*
|
||||
* Runs all tests as the system user.
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public abstract class BaseAlfrescoSpringTest extends BaseSpringTest
|
||||
{
|
||||
/** The node service */
|
||||
protected NodeService nodeService;
|
||||
|
||||
/** The content service */
|
||||
protected ContentService contentService;
|
||||
|
||||
/** The authentication service */
|
||||
protected AuthenticationService authenticationService;
|
||||
|
||||
/** The store reference */
|
||||
protected StoreRef storeRef;
|
||||
|
||||
/** The root node reference */
|
||||
protected NodeRef rootNodeRef;
|
||||
|
||||
|
||||
protected ActionService actionService;
|
||||
protected TransactionService transactionService;
|
||||
|
||||
/**
|
||||
* On setup in transaction override
|
||||
*/
|
||||
@Override
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
{
|
||||
super.onSetUpInTransaction();
|
||||
|
||||
// Get a reference to the node service
|
||||
this.nodeService = (NodeService) this.applicationContext.getBean("nodeService");
|
||||
this.contentService = (ContentService) this.applicationContext.getBean("contentService");
|
||||
this.authenticationService = (AuthenticationService) this.applicationContext.getBean("authenticationService");
|
||||
this.actionService = (ActionService)this.applicationContext.getBean("actionService");
|
||||
this.transactionService = (TransactionService)this.applicationContext.getBean("transactionComponent");
|
||||
|
||||
// Authenticate as the system user
|
||||
AuthenticationComponent authenticationComponent = (AuthenticationComponent) this.applicationContext
|
||||
.getBean("authenticationComponent");
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
// Create the store and get the root node
|
||||
this.storeRef = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
|
||||
this.rootNodeRef = this.nodeService.getRootNode(this.storeRef);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTearDownInTransaction()
|
||||
{
|
||||
authenticationService.clearCurrentSecurityContext();
|
||||
super.onTearDownInTransaction();
|
||||
}
|
||||
|
||||
}
|
101
source/java/org/alfresco/util/BaseAlfrescoTestCase.java
Normal file
101
source/java/org/alfresco/util/BaseAlfrescoTestCase.java
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util;
|
||||
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
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.security.AuthenticationService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* Base Alfresco test.
|
||||
*
|
||||
* Creates a store and root node that can be used in the tests.
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public abstract class BaseAlfrescoTestCase extends TestCase
|
||||
{
|
||||
/** the context to keep between tests */
|
||||
public static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||
|
||||
/** the service registry */
|
||||
protected ServiceRegistry serviceRegistry;
|
||||
|
||||
/** The node service */
|
||||
protected NodeService nodeService;
|
||||
|
||||
/** The content service */
|
||||
protected ContentService contentService;
|
||||
|
||||
/** The authentication service */
|
||||
protected AuthenticationService authenticationService;
|
||||
|
||||
/** The store reference */
|
||||
protected StoreRef storeRef;
|
||||
|
||||
/** The root node reference */
|
||||
protected NodeRef rootNodeRef;
|
||||
|
||||
|
||||
protected ActionService actionService;
|
||||
protected TransactionService transactionService;
|
||||
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
// get the service register
|
||||
this.serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
//Get a reference to the node service
|
||||
this.nodeService = (NodeService)ctx.getBean("NodeService");
|
||||
this.contentService = (ContentService)ctx.getBean("ContentService");
|
||||
this.authenticationService = (AuthenticationService)ctx.getBean("authenticationService");
|
||||
this.actionService = (ActionService)ctx.getBean("actionService");
|
||||
this.transactionService = (TransactionService)ctx.getBean("transactionComponent");
|
||||
|
||||
// Authenticate as the system user - this must be done before we create the store
|
||||
AuthenticationComponent authenticationComponent = (AuthenticationComponent)ctx.getBean("authenticationComponent");
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
// Create the store and get the root node
|
||||
this.storeRef = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
|
||||
this.rootNodeRef = this.nodeService.getRootNode(this.storeRef);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
authenticationService.clearCurrentSecurityContext();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
}
|
89
source/java/org/alfresco/util/BaseSpringTest.java
Normal file
89
source/java/org/alfresco/util/BaseSpringTest.java
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.springframework.orm.hibernate3.SessionFactoryUtils;
|
||||
import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
|
||||
|
||||
/**
|
||||
* Base test class providing Hibernate sessions.
|
||||
* <p>
|
||||
* By default this is auto-wired by type. If a this is going to
|
||||
* result in a conlict the use auto-wire by name. This can be done by
|
||||
* setting populateProtectedVariables to true in the constructor and
|
||||
* then adding protected members with the same name as the bean you require.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public abstract class BaseSpringTest extends AbstractTransactionalDataSourceSpringContextTests
|
||||
{
|
||||
/** protected so that it gets populated if autowiring is done by variable name **/
|
||||
protected SessionFactory sessionFactory;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public BaseSpringTest()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter present for in case autowiring is done by type
|
||||
*
|
||||
* @param sessionFactory
|
||||
*/
|
||||
public void setSessionFactory(SessionFactory sessionFactory)
|
||||
{
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the existing session attached to the thread.
|
||||
* A new session will <b>not</b> be created.
|
||||
*/
|
||||
protected Session getSession()
|
||||
{
|
||||
return SessionFactoryUtils.getSession(sessionFactory, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the session to flush to the database (without commiting) and clear the
|
||||
* cache. This ensures that all reads against the session are fresh instances,
|
||||
* which gives the assurance that the DB read/write operations occur correctly.
|
||||
*/
|
||||
protected void flushAndClear()
|
||||
{
|
||||
getSession().flush();
|
||||
getSession().clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the config locations
|
||||
*
|
||||
* @return an array containing the config locations
|
||||
*/
|
||||
protected String[] getConfigLocations()
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Getting config locations");
|
||||
}
|
||||
return ApplicationContextHelper.CONFIG_LOCATIONS;
|
||||
}
|
||||
}
|
59
source/java/org/alfresco/util/PropertyMap.java
Normal file
59
source/java/org/alfresco/util/PropertyMap.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Property map helper class.
|
||||
* <p>
|
||||
* This class can be used as a short hand when a class of type
|
||||
* Map<QName, Serializable> is required.
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class PropertyMap extends HashMap<QName, Serializable>
|
||||
{
|
||||
private static final long serialVersionUID = 8052326301073209645L;
|
||||
|
||||
/**
|
||||
* @see HashMap#HashMap(int, float)
|
||||
*/
|
||||
public PropertyMap(int initialCapacity, float loadFactor)
|
||||
{
|
||||
super(initialCapacity, loadFactor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see HashMap#HashMap(int)
|
||||
*/
|
||||
public PropertyMap(int initialCapacity)
|
||||
{
|
||||
super(initialCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see HashMap#HashMap()
|
||||
*/
|
||||
public PropertyMap()
|
||||
{
|
||||
super();
|
||||
}
|
||||
}
|
238
source/java/org/alfresco/util/SearchLanguageConversion.java
Normal file
238
source/java/org/alfresco/util/SearchLanguageConversion.java
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util;
|
||||
|
||||
import org.alfresco.repo.search.impl.lucene.QueryParser;
|
||||
|
||||
|
||||
/**
|
||||
* Helper class to provide conversions between different search languages
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class SearchLanguageConversion
|
||||
{
|
||||
/**
|
||||
* XPath like query language summary:
|
||||
* <ul>
|
||||
* <li>Escape: \</li>
|
||||
* <li>Single char search: _</li>
|
||||
* <li>Multiple char search: %</li>
|
||||
* <li>Reserved: \%_</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static LanguageDefinition DEF_XPATH_LIKE = new SimpleLanguageDef('\\', "%", "_", "\\%_");
|
||||
/**
|
||||
* Regular expression query language summary:
|
||||
* <ul>
|
||||
* <li>Escape: \</li>
|
||||
* <li>Single char search: .</li>
|
||||
* <li>Multiple char search: .*</li>
|
||||
* <li>Reserved: \*.+?^$(){}|</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static LanguageDefinition DEF_REGEX = new SimpleLanguageDef('\\', ".*", ".", "\\*.+?^$(){}|");
|
||||
/**
|
||||
* Lucene syntax summary: {@link QueryParser#escape(String) Lucene Query Parser}
|
||||
*/
|
||||
public static LanguageDefinition DEF_LUCENE = new LuceneLanguageDef();
|
||||
|
||||
/**
|
||||
* Escape a string according to the <b>XPath</b> like function syntax.
|
||||
*
|
||||
* @param str the string to escape
|
||||
* @return Returns the escaped string
|
||||
*/
|
||||
public static String escapeForXPathLike(String str)
|
||||
{
|
||||
return escape(DEF_XPATH_LIKE, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string according to the <b>regex</b> language syntax.
|
||||
*
|
||||
* @param str the string to escape
|
||||
* @return Returns the escaped string
|
||||
*/
|
||||
public static String escapeForRegex(String str)
|
||||
{
|
||||
return escape(DEF_REGEX, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string according to the <b>Lucene</b> query syntax.
|
||||
*
|
||||
* @param str the string to escape
|
||||
* @return Returns the escaped string
|
||||
*/
|
||||
public static String escapeForLucene(String str)
|
||||
{
|
||||
return escape(DEF_LUCENE, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic escaping using the language definition
|
||||
*/
|
||||
private static String escape(LanguageDefinition def, String str)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(str.length() * 2);
|
||||
|
||||
char[] chars = str.toCharArray();
|
||||
for (int i = 0; i < chars.length; i++)
|
||||
{
|
||||
// first check for reserved chars
|
||||
if (def.isReserved(chars[i]))
|
||||
{
|
||||
// escape it
|
||||
sb.append(def.escapeChar);
|
||||
}
|
||||
sb.append(chars[i]);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an <b>xpath</b> like function clause into a <b>regex</b> query.
|
||||
*
|
||||
* @param xpathLikeClause
|
||||
* @return Returns a valid regular expression that is equivalent to the
|
||||
* given <b>xpath</b> like clause.
|
||||
*/
|
||||
public static String convertXPathLikeToRegex(String xpathLikeClause)
|
||||
{
|
||||
return convert(DEF_XPATH_LIKE, DEF_REGEX, xpathLikeClause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an <b>xpath</b> like function clause into a <b>Lucene</b> query.
|
||||
*
|
||||
* @param xpathLikeClause
|
||||
* @return Returns a valid <b>Lucene</b> expression that is equivalent to the
|
||||
* given <b>xpath</b> like clause.
|
||||
*/
|
||||
public static String convertXPathLikeToLucene(String xpathLikeClause)
|
||||
{
|
||||
return convert(DEF_XPATH_LIKE, DEF_LUCENE, xpathLikeClause);
|
||||
}
|
||||
|
||||
public static String convert(LanguageDefinition from, LanguageDefinition to, String query)
|
||||
{
|
||||
char[] chars = query.toCharArray();
|
||||
|
||||
StringBuilder sb = new StringBuilder(chars.length * 2);
|
||||
|
||||
boolean escaping = false;
|
||||
|
||||
for (int i = 0; i < chars.length; i++)
|
||||
{
|
||||
if (escaping) // if we are currently escaping, just escape the current character
|
||||
{
|
||||
sb.append(to.escapeChar); // the to format escape char
|
||||
sb.append(chars[i]); // the current char
|
||||
escaping = false;
|
||||
}
|
||||
else if (chars[i] == from.escapeChar) // not escaping and have escape char
|
||||
{
|
||||
escaping = true;
|
||||
}
|
||||
else if (query.startsWith(from.multiCharWildcard, i)) // not escaping but have multi-char wildcard
|
||||
{
|
||||
// translate the wildcard
|
||||
sb.append(to.multiCharWildcard);
|
||||
}
|
||||
else if (query.startsWith(from.singleCharWildcard, i)) // have single-char wildcard
|
||||
{
|
||||
// translate the wildcard
|
||||
sb.append(to.singleCharWildcard);
|
||||
}
|
||||
else if (to.isReserved(chars[i])) // reserved character
|
||||
{
|
||||
sb.append(to.escapeChar).append(chars[i]);
|
||||
}
|
||||
else // just a normal char in both
|
||||
{
|
||||
sb.append(chars[i]);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple store of special characters for a given query language
|
||||
*/
|
||||
public static abstract class LanguageDefinition
|
||||
{
|
||||
public final char escapeChar;
|
||||
public final String multiCharWildcard;
|
||||
public final String singleCharWildcard;
|
||||
|
||||
public LanguageDefinition(char escapeChar, String multiCharWildcard, String singleCharWildcard)
|
||||
{
|
||||
this.escapeChar = escapeChar;
|
||||
this.multiCharWildcard = multiCharWildcard;
|
||||
this.singleCharWildcard = singleCharWildcard;
|
||||
}
|
||||
public abstract boolean isReserved(char ch);
|
||||
}
|
||||
private static class SimpleLanguageDef extends LanguageDefinition
|
||||
{
|
||||
private String reserved;
|
||||
public SimpleLanguageDef(char escapeChar, String multiCharWildcard, String singleCharWildcard, String reserved)
|
||||
{
|
||||
super(escapeChar, multiCharWildcard, singleCharWildcard);
|
||||
this.reserved = reserved;
|
||||
}
|
||||
@Override
|
||||
public boolean isReserved(char ch)
|
||||
{
|
||||
return (reserved.indexOf(ch) > -1);
|
||||
}
|
||||
}
|
||||
private static class LuceneLanguageDef extends LanguageDefinition
|
||||
{
|
||||
private String reserved;
|
||||
public LuceneLanguageDef()
|
||||
{
|
||||
super('\\', "*", "?");
|
||||
init();
|
||||
}
|
||||
/**
|
||||
* Discovers all the reserved chars
|
||||
*/
|
||||
private void init()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(20);
|
||||
for (char ch = 0; ch < 256; ch++)
|
||||
{
|
||||
char[] chars = new char[] {ch};
|
||||
String unescaped = new String(chars);
|
||||
// check it
|
||||
String escaped = QueryParser.escape(unescaped);
|
||||
if (!escaped.equals(unescaped))
|
||||
{
|
||||
// it was escaped
|
||||
sb.append(ch);
|
||||
}
|
||||
}
|
||||
reserved = sb.toString();
|
||||
}
|
||||
@Override
|
||||
public boolean isReserved(char ch)
|
||||
{
|
||||
return (reserved.indexOf(ch) > -1);
|
||||
}
|
||||
}
|
||||
}
|
103
source/java/org/alfresco/util/SearchLanguageConversionTest.java
Normal file
103
source/java/org/alfresco/util/SearchLanguageConversionTest.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @see org.alfresco.util.SearchLanguageConversion
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class SearchLanguageConversionTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* A string with a whole lod of badness to stress test with
|
||||
*/
|
||||
private static final String BAD_STRING =
|
||||
"\\ | ! \" <20> " +
|
||||
"$ % ^ & * ( " +
|
||||
") _ { } [ ] " +
|
||||
"@ # ~ ' : ; " +
|
||||
", . < > + ? " +
|
||||
"/ \\\\ \\* \\? \\_";
|
||||
|
||||
public void testEscapeXPathLike()
|
||||
{
|
||||
String good = SearchLanguageConversion.escapeForXPathLike(BAD_STRING);
|
||||
assertEquals("Escaping for xpath failed",
|
||||
"\\\\ | ! \" <20> " +
|
||||
"$ \\% ^ & * ( " +
|
||||
") \\_ { } [ ] " +
|
||||
"@ # ~ ' : ; " +
|
||||
", . < > + ? " +
|
||||
"/ \\\\\\\\ \\\\* \\\\? \\\\\\_",
|
||||
good);
|
||||
}
|
||||
|
||||
public void testEscapeRegex()
|
||||
{
|
||||
String good = SearchLanguageConversion.escapeForRegex(BAD_STRING);
|
||||
assertEquals("Escaping for regex failed",
|
||||
"\\\\ \\| ! \" <20> " +
|
||||
"\\$ % \\^ & \\* \\( " +
|
||||
"\\) _ \\{ \\} [ ] " +
|
||||
"@ # ~ ' : ; " +
|
||||
", \\. < > \\+ \\? " +
|
||||
"/ \\\\\\\\ \\\\\\* \\\\\\? \\\\_",
|
||||
good);
|
||||
}
|
||||
|
||||
public void testEscapeLucene()
|
||||
{
|
||||
String good = SearchLanguageConversion.escapeForLucene(BAD_STRING);
|
||||
assertEquals("Escaping for regex failed",
|
||||
"\\\\ | \\! \\\" <20> " +
|
||||
"$ % \\^ & \\* \\( " +
|
||||
"\\) _ \\{ \\} \\[ \\] " +
|
||||
"@ # \\~ ' \\: ; " +
|
||||
", . < > \\+ \\? " +
|
||||
"/ \\\\\\\\ \\\\\\* \\\\\\? \\\\_",
|
||||
good);
|
||||
}
|
||||
|
||||
public void testConvertXPathLikeToRegex()
|
||||
{
|
||||
String good = SearchLanguageConversion.convertXPathLikeToRegex(BAD_STRING);
|
||||
assertEquals("XPath like to regex failed",
|
||||
"\\ \\| ! \" <20> " +
|
||||
"\\$ .* \\^ & \\* \\( " +
|
||||
"\\) . \\{ \\} [ ] " +
|
||||
"@ # ~ ' : ; " +
|
||||
", \\. < > \\+ \\? " +
|
||||
"/ \\\\ \\* \\? \\_",
|
||||
good);
|
||||
}
|
||||
|
||||
public void testConvertXPathLikeToLucene()
|
||||
{
|
||||
String good = SearchLanguageConversion.convertXPathLikeToLucene(BAD_STRING);
|
||||
assertEquals("XPath like to regex failed",
|
||||
"\\ | \\! \\\" <20> " +
|
||||
"$ * \\^ & \\* \\( " +
|
||||
"\\) ? \\{ \\} \\[ \\] " +
|
||||
"@ # \\~ ' \\: ; " +
|
||||
", . < > \\+ \\? " +
|
||||
"/ \\\\ \\* \\? \\_",
|
||||
good);
|
||||
}
|
||||
}
|
111
source/java/org/alfresco/util/TestWithUserUtils.java
Normal file
111
source/java/org/alfresco/util/TestWithUserUtils.java
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Utility class containing some useful methods to help when writing tets that require authenticated users
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public abstract class TestWithUserUtils extends BaseSpringTest
|
||||
{
|
||||
/**
|
||||
* Create a new user, including the corresponding person node.
|
||||
*
|
||||
* @param userName the user name
|
||||
* @param password the password
|
||||
* @param rootNodeRef the root node reference
|
||||
* @param nodeService the node service
|
||||
* @param authenticationService the authentication service
|
||||
*/
|
||||
public static void createUser(
|
||||
String userName,
|
||||
String password,
|
||||
NodeRef rootNodeRef,
|
||||
NodeService nodeService,
|
||||
AuthenticationService authenticationService)
|
||||
{
|
||||
QName children = ContentModel.ASSOC_CHILDREN;
|
||||
QName system = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "system");
|
||||
QName container = ContentModel.TYPE_CONTAINER;
|
||||
QName types = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "people");
|
||||
|
||||
NodeRef systemNodeRef = nodeService.createNode(rootNodeRef, children, system, container).getChildRef();
|
||||
NodeRef typesNodeRef = nodeService.createNode(systemNodeRef, children, types, container).getChildRef();
|
||||
|
||||
HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>();
|
||||
properties.put(ContentModel.PROP_USERNAME, userName);
|
||||
NodeRef goodUserPerson = nodeService.createNode(typesNodeRef, children, ContentModel.TYPE_PERSON, container, properties).getChildRef();
|
||||
|
||||
// Create the users
|
||||
|
||||
authenticationService.createAuthentication(userName, password.toCharArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Autneticate the user with the specified password
|
||||
*
|
||||
* @param userName the user name
|
||||
* @param password the password
|
||||
* @param rootNodeRef the root node reference
|
||||
* @param authenticationService the authentication service
|
||||
*/
|
||||
public static void authenticateUser(
|
||||
String userName,
|
||||
String password,
|
||||
NodeRef rootNodeRef,
|
||||
AuthenticationService authenticationService)
|
||||
{
|
||||
authenticationService.authenticate(userName, password.toCharArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current user node reference
|
||||
*
|
||||
* @param authenticationService the authentication service
|
||||
* @return the currenlty authenticated user's node reference
|
||||
*/
|
||||
public static String getCurrentUser(AuthenticationService authenticationService)
|
||||
{
|
||||
String un = authenticationService.getCurrentUserName();
|
||||
if (un != null)
|
||||
{
|
||||
return un;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException("The current user could not be retrieved.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void deleteUser(String user_name, String pwd, NodeRef ref, NodeService service, AuthenticationService service2)
|
||||
{
|
||||
service2.deleteAuthentication(user_name);
|
||||
}
|
||||
|
||||
}
|
137
source/java/org/alfresco/util/ThreadPoolExecutorFactoryBean.java
Normal file
137
source/java/org/alfresco/util/ThreadPoolExecutorFactoryBean.java
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util;
|
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* Factory for {@link java.util.concurrent.ThreadPoolExecutor} instances,
|
||||
* which cannot easily be constructed using constructor injection.
|
||||
* <p>
|
||||
* This factory provides the a singleton instance of the pool.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class ThreadPoolExecutorFactoryBean implements FactoryBean, InitializingBean
|
||||
{
|
||||
private int corePoolSize;
|
||||
private int maximumPoolSize;
|
||||
private int keepAliveTime;
|
||||
private BlockingQueue<Runnable> workQueue;
|
||||
private ThreadPoolExecutor instance;
|
||||
|
||||
/**
|
||||
* Constructor setting default properties:
|
||||
* <ul>
|
||||
* <li>corePoolSize: 5</li>
|
||||
* <li>maximumPoolSize: 20</li>
|
||||
* <li>keepAliveTime: 60s</li>
|
||||
* <li>workQueue: {@link ArrayBlockingQueue}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public ThreadPoolExecutorFactoryBean()
|
||||
{
|
||||
corePoolSize = 5;
|
||||
maximumPoolSize = 20;
|
||||
keepAliveTime = 30;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of threads to keep in the pool, even if idle.
|
||||
*
|
||||
* @param corePoolSize core thread count
|
||||
*/
|
||||
public void setCorePoolSize(int corePoolSize)
|
||||
{
|
||||
this.corePoolSize = corePoolSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum number of threads to keep in the pool
|
||||
*
|
||||
* @param maximumPoolSize the maximum number of threads in the pool
|
||||
*/
|
||||
public void setMaximumPoolSize(int maximumPoolSize)
|
||||
{
|
||||
this.maximumPoolSize = maximumPoolSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time (in seconds) to keep non-core idle threads in the pool
|
||||
*
|
||||
* @param keepAliveTime time to stay idle in seconds
|
||||
*/
|
||||
public void setKeepAliveTime(int keepAliveTime)
|
||||
{
|
||||
this.keepAliveTime = keepAliveTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* The optional queue instance to use
|
||||
*
|
||||
* @param workQueue optional queue implementation
|
||||
*/
|
||||
public void setWorkQueue(BlockingQueue<Runnable> workQueue)
|
||||
{
|
||||
this.workQueue = workQueue;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
if (workQueue == null)
|
||||
{
|
||||
workQueue = new ArrayBlockingQueue<Runnable>(corePoolSize);
|
||||
}
|
||||
// construct the instance
|
||||
instance = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns true always.
|
||||
*/
|
||||
public boolean isSingleton()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the singleton {@link ThreadPoolExecutor instance}.
|
||||
*/
|
||||
public Object getObject() throws Exception
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("The ThreadPoolExecutor instance has not been created");
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ThreadPoolExecutor
|
||||
*/
|
||||
public Class getObjectType()
|
||||
{
|
||||
return ThreadPoolExecutor.class;
|
||||
}
|
||||
}
|
136
source/java/org/alfresco/util/debug/MethodCallLogAdvice.java
Normal file
136
source/java/org/alfresco/util/debug/MethodCallLogAdvice.java
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util.debug;
|
||||
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Performs writing to DEBUG of incoming arguments and outgoing results for a method call.<br>
|
||||
* If the method invocation throws an exception, then the incoming arguments are
|
||||
* logged to DEBUG as well.<br>
|
||||
* The implementation adds very little overhead to a normal method
|
||||
* call by only building log messages when required.
|
||||
* <p>
|
||||
* The logging is done against the logger retrieved using the names:
|
||||
* <p>
|
||||
* <pre>
|
||||
* org.alfresco.util.debug.MethodCallLogAdvice
|
||||
* AND
|
||||
* targetClassName
|
||||
* targetClassName.methodName
|
||||
* targetClassName.methodName.exception
|
||||
* </pre>
|
||||
* <p>
|
||||
* The following examples show how to control the log levels:
|
||||
* <p>
|
||||
* <pre>
|
||||
* org.alfresco.util.debug.MethodCallLogAdvice=DEBUG # activate method logging
|
||||
* AND
|
||||
* x.y.MyClass=DEBUG # log debug for all method calls on MyClass
|
||||
* x.y.MyClass.doSomething=DEBUG # log debug for all doSomething method calls
|
||||
* x.y.MyClass.doSomething.exception=DEBUG # only log debug for doSomething() upon exception
|
||||
* </pre>
|
||||
* <p>
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class MethodCallLogAdvice implements MethodInterceptor
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(MethodCallLogAdvice.class);
|
||||
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
return invokeWithLogging(invocation);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no logging required
|
||||
return invocation.proceed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Only executes logging code if logging is required
|
||||
*/
|
||||
private Object invokeWithLogging(MethodInvocation invocation) throws Throwable
|
||||
{
|
||||
String methodName = invocation.getMethod().getName();
|
||||
String className = invocation.getMethod().getDeclaringClass().getName();
|
||||
|
||||
// execute as normal
|
||||
try
|
||||
{
|
||||
Object ret = invocation.proceed();
|
||||
// logging
|
||||
Log methodLogger = LogFactory.getLog(className + "." + methodName);
|
||||
if (methodLogger.isDebugEnabled())
|
||||
{
|
||||
// log success
|
||||
StringBuffer sb = getInvocationInfo(className, methodName, invocation.getArguments());
|
||||
sb.append(" Result: ").append(ret);
|
||||
methodLogger.debug(sb);
|
||||
}
|
||||
// done
|
||||
return ret;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
Log exceptionLogger = LogFactory.getLog(className + "." + methodName + ".exception");
|
||||
if (exceptionLogger.isDebugEnabled())
|
||||
{
|
||||
StringBuffer sb = getInvocationInfo(className, methodName, invocation.getArguments());
|
||||
sb.append(" Failure: ").append(e.getClass().getName()).append(" - ").append(e.getMessage());
|
||||
exceptionLogger.debug(sb);
|
||||
}
|
||||
// rethrow
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return format:
|
||||
* <pre>
|
||||
* Method: className#methodName
|
||||
* Argument: arg0
|
||||
* Argument: arg1
|
||||
* ...
|
||||
* Argument: argN {newline}
|
||||
* </pre>
|
||||
*
|
||||
* @param className
|
||||
* @param methodName
|
||||
* @param args
|
||||
* @return Returns a StringBuffer containing the details of a method call
|
||||
*/
|
||||
private StringBuffer getInvocationInfo(String className, String methodName, Object[] args)
|
||||
{
|
||||
StringBuffer sb = new StringBuffer(250);
|
||||
sb.append("\nMethod: ").append(className).append("#").append(methodName).append("\n");
|
||||
sb.append(" Transaction: ").append(AlfrescoTransactionSupport.getTransactionId()).append("\n");
|
||||
for (Object arg : args)
|
||||
{
|
||||
sb.append(" Argument: ").append(arg).append("\n");
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
}
|
166
source/java/org/alfresco/util/debug/NodeStoreInspector.java
Normal file
166
source/java/org/alfresco/util/debug/NodeStoreInspector.java
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util.debug;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
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.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
|
||||
/**
|
||||
* Debug class that has methods to inspect the contents of a node store.
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class NodeStoreInspector
|
||||
{
|
||||
/**
|
||||
* Dumps the contents of a store to a string.
|
||||
*
|
||||
* @param nodeService the node service
|
||||
* @param storeRef the store reference
|
||||
* @return string containing textual representation of the contents of the store
|
||||
*/
|
||||
public static String dumpNodeStore(NodeService nodeService, StoreRef storeRef)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
if (nodeService.exists(storeRef) == true)
|
||||
{
|
||||
NodeRef rootNode = nodeService.getRootNode(storeRef);
|
||||
builder.append(outputNode(0, nodeService, rootNode));
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.
|
||||
append("The store ").
|
||||
append(storeRef.toString()).
|
||||
append(" does not exist.");
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the node
|
||||
*
|
||||
* @param iIndent
|
||||
* @param nodeService
|
||||
* @param nodeRef
|
||||
* @return
|
||||
*/
|
||||
private static String outputNode(int iIndent, NodeService nodeService, NodeRef nodeRef)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
try
|
||||
{
|
||||
QName nodeType = nodeService.getType(nodeRef);
|
||||
builder.
|
||||
append(getIndent(iIndent)).
|
||||
append("node: ").
|
||||
append(nodeRef.getId()).
|
||||
append(" (").
|
||||
append(nodeType.getLocalName());
|
||||
|
||||
Collection<QName> aspects = nodeService.getAspects(nodeRef);
|
||||
for (QName aspect : aspects)
|
||||
{
|
||||
builder.
|
||||
append(", ").
|
||||
append(aspect.getLocalName());
|
||||
}
|
||||
|
||||
builder.append(")\n");
|
||||
|
||||
Map<QName, Serializable> props = nodeService.getProperties(nodeRef);
|
||||
for (QName name : props.keySet())
|
||||
{
|
||||
String valueAsString = "null";
|
||||
Serializable value = props.get(name);
|
||||
if (value != null)
|
||||
{
|
||||
valueAsString = value.toString();
|
||||
}
|
||||
|
||||
builder.
|
||||
append(getIndent(iIndent+1)).
|
||||
append("@").
|
||||
append(name.getLocalName()).
|
||||
append(" = ").
|
||||
append(valueAsString).
|
||||
append("\n");
|
||||
|
||||
}
|
||||
|
||||
Collection<ChildAssociationRef> childAssocRefs = nodeService.getChildAssocs(nodeRef);
|
||||
for (ChildAssociationRef childAssocRef : childAssocRefs)
|
||||
{
|
||||
builder.
|
||||
append(getIndent(iIndent+1)).
|
||||
append("-> ").
|
||||
append(childAssocRef.getQName().toString()).
|
||||
append(" (").
|
||||
append(childAssocRef.getQName().toString()).
|
||||
append(")\n");
|
||||
|
||||
builder.append(outputNode(iIndent+2, nodeService, childAssocRef.getChildRef()));
|
||||
}
|
||||
|
||||
Collection<AssociationRef> assocRefs = nodeService.getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL);
|
||||
for (AssociationRef assocRef : assocRefs)
|
||||
{
|
||||
builder.
|
||||
append(getIndent(iIndent+1)).
|
||||
append("-> associated to ").
|
||||
append(assocRef.getTargetRef().getId()).
|
||||
append("\n");
|
||||
}
|
||||
}
|
||||
catch (InvalidNodeRefException invalidNode)
|
||||
{
|
||||
invalidNode.printStackTrace();
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the indent
|
||||
*
|
||||
* @param iIndent the indent value
|
||||
* @return the indent string
|
||||
*/
|
||||
private static String getIndent(int iIndent)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(iIndent*3);
|
||||
for (int i = 0; i < iIndent; i++)
|
||||
{
|
||||
builder.append(" ");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util.debug;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
|
||||
/**
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class OutputSpacesStoreSystemTest extends BaseSpringTest
|
||||
{
|
||||
/**
|
||||
* Dump the contents of the spaces store to standard out
|
||||
*/
|
||||
public void testDumpSpacesStore()
|
||||
{
|
||||
NodeService nodeService = (NodeService)this.applicationContext.getBean("nodeService");
|
||||
StoreRef spacesStore = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore");
|
||||
System.out.println(NodeStoreInspector.dumpNodeStore(nodeService, spacesStore));
|
||||
}
|
||||
}
|
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util.perf;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* An instance of this class keeps track of timings of method calls made against
|
||||
* a named entity. Logging can occur either after each recorded time, or only on
|
||||
* VM shutdown or both.
|
||||
* <p>
|
||||
* Logging output is managed down to either the entity or entity-invocation level as follows:
|
||||
* <p>
|
||||
* <pre>
|
||||
* performance.summary.method
|
||||
* performance.summary.vm
|
||||
* AND
|
||||
* performance.targetEntityName
|
||||
* performance.targetEntityName.methodName
|
||||
* </pre>
|
||||
* <p>
|
||||
* The following examples illustrate how it can be used:
|
||||
* <p>
|
||||
* <pre>
|
||||
* performance.summary.method=DEBUG
|
||||
* performance.myBean=DEBUG
|
||||
* --> Output method invocation statistic on each call to myBean
|
||||
*
|
||||
* performance.summary.vm=DEBUG
|
||||
* performance.myBean.doSomething=DEBUG
|
||||
* --> Output summary for doSomething() invocations on myBean when VM terminates
|
||||
*
|
||||
* performance=DEBUG
|
||||
* --> Output all performance data - after each invocation and upon VM closure
|
||||
* </pre>
|
||||
* <p>
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public abstract class AbstractPerformanceMonitor
|
||||
{
|
||||
/** logger for method level performance summaries */
|
||||
private static final Log methodSummaryLogger = LogFactory.getLog("performance.summary.method");
|
||||
/** logger for VM level performance summaries */
|
||||
private static final Log vmSummaryLogger = LogFactory.getLog("performance.summary.vm");
|
||||
|
||||
private final String entityName;
|
||||
/** VM level summary */
|
||||
private SortedMap<String, MethodStats> stats;
|
||||
|
||||
/**
|
||||
* Convenience method to check if there is some sort of performance logging enabled
|
||||
*
|
||||
* @return Returns true if there is some sort of performance logging enabled, false otherwise
|
||||
*/
|
||||
public static boolean isDebugEnabled()
|
||||
{
|
||||
return (vmSummaryLogger.isDebugEnabled() || methodSummaryLogger.isDebugEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entityName the name of the entity for which the performance is being recorded
|
||||
*/
|
||||
public AbstractPerformanceMonitor(String entityName)
|
||||
{
|
||||
this.entityName = entityName;
|
||||
stats = new TreeMap<String, MethodStats>();
|
||||
|
||||
// enable a VM shutdown hook if required
|
||||
if (vmSummaryLogger.isDebugEnabled())
|
||||
{
|
||||
Thread hook = new ShutdownThread();
|
||||
Runtime.getRuntime().addShutdownHook(hook);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the results of the method execution to:
|
||||
* <ul>
|
||||
* <li>DEBUG output if the method level debug logging is active</li>
|
||||
* <li>Performance store if required</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param methodName the name of the method against which to store the results
|
||||
* @param delayMs
|
||||
*/
|
||||
protected void recordStats(String methodName, double delayMs)
|
||||
{
|
||||
Log methodLogger = LogFactory.getLog("performance." + entityName + "." + methodName);
|
||||
if (!methodLogger.isDebugEnabled())
|
||||
{
|
||||
// no recording for this method
|
||||
return;
|
||||
}
|
||||
|
||||
DecimalFormat format = new DecimalFormat ();
|
||||
format.setMinimumFractionDigits (3);
|
||||
format.setMaximumFractionDigits (3);
|
||||
|
||||
// must we log on a per-method call?
|
||||
if (methodSummaryLogger.isDebugEnabled())
|
||||
{
|
||||
methodLogger.debug("Executed " + entityName + "#" + methodName + " in " + format.format(delayMs) + "ms");
|
||||
}
|
||||
if (vmSummaryLogger.isDebugEnabled())
|
||||
{
|
||||
synchronized(this) // only synchronize if absolutely necessary
|
||||
{
|
||||
// get stats
|
||||
MethodStats methodStats = stats.get(methodName);
|
||||
if (methodStats == null)
|
||||
{
|
||||
methodStats = new MethodStats();
|
||||
stats.put(methodName, methodStats);
|
||||
}
|
||||
methodStats.record(delayMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the execution count and total execution time for any method
|
||||
*/
|
||||
private class MethodStats
|
||||
{
|
||||
private int count;
|
||||
private double totalTimeMs;
|
||||
|
||||
/**
|
||||
* Records the time for a method to execute and bumps up the execution count
|
||||
*
|
||||
* @param delayMs the time the method took to execute in milliseconds
|
||||
*/
|
||||
public void record(double delayMs)
|
||||
{
|
||||
count++;
|
||||
totalTimeMs += delayMs;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
DecimalFormat format = new DecimalFormat ();
|
||||
format.setMinimumFractionDigits (3);
|
||||
format.setMaximumFractionDigits (3);
|
||||
double averageMs = totalTimeMs / (long) count;
|
||||
return ("Executed " + count + " times, averaging " + format.format(averageMs) + "ms per call");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the output of all recorded method statistics
|
||||
*/
|
||||
private class ShutdownThread extends Thread
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
String beanName = AbstractPerformanceMonitor.this.entityName;
|
||||
|
||||
// prevent multiple ShutdownThread instances interleaving their output
|
||||
synchronized(ShutdownThread.class)
|
||||
{
|
||||
vmSummaryLogger.debug("\n==================== " + beanName.toUpperCase() + " ===================");
|
||||
Set<String> methodNames = stats.keySet();
|
||||
for (String methodName : methodNames)
|
||||
{
|
||||
vmSummaryLogger.debug("\nMethod performance summary: \n" +
|
||||
" Bean: " + AbstractPerformanceMonitor.this.entityName + "\n" +
|
||||
" Method: " + methodName + "\n" +
|
||||
" Statistics: " + stats.get(methodName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
119
source/java/org/alfresco/util/perf/PerformanceMonitor.java
Normal file
119
source/java/org/alfresco/util/perf/PerformanceMonitor.java
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util.perf;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.vladium.utils.timing.ITimer;
|
||||
import com.vladium.utils.timing.TimerFactory;
|
||||
|
||||
/**
|
||||
* Enables <b>begin ... end</b> style performance monitoring with summarisation
|
||||
* using the <b>performance</b> logging category. It is designed to only incur
|
||||
* a minor cost when performance logging is turned on using the DEBUG logging
|
||||
* mechanism. See base class for details on enabling the <b>performance</b>
|
||||
* logging categories.
|
||||
* <p>
|
||||
* This class is thread safe.
|
||||
* <p>
|
||||
* Usage:
|
||||
* <pre>
|
||||
* private PerformanceMonitor somethingTimer = new PerformanceMonitor("mytest", "doSomething");
|
||||
* ...
|
||||
* ...
|
||||
* private void doSomething()
|
||||
* {
|
||||
* somethingTimer.start();
|
||||
* ...
|
||||
* ...
|
||||
* somethingTimer.stop();
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class PerformanceMonitor extends AbstractPerformanceMonitor
|
||||
{
|
||||
private String methodName;
|
||||
private ThreadLocal<ITimer> threadLocalTimer;
|
||||
private boolean log;
|
||||
|
||||
/**
|
||||
* @param entityName name of the entity, e.g. a test name or a bean name against which to
|
||||
* log the performance
|
||||
* @param methodName the method for which the performance will be logged
|
||||
*/
|
||||
public PerformanceMonitor(String entityName, String methodName)
|
||||
{
|
||||
super(entityName);
|
||||
this.methodName = methodName;
|
||||
this.threadLocalTimer = new ThreadLocal<ITimer>();
|
||||
|
||||
// check if logging can be eliminated
|
||||
Log methodLogger = LogFactory.getLog("performance." + entityName + "." + methodName);
|
||||
this.log = AbstractPerformanceMonitor.isDebugEnabled() && methodLogger.isDebugEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Threadsafe method to start the timer.
|
||||
* <p>
|
||||
* The timer is only started if the logging levels are enabled.
|
||||
*
|
||||
* @see #stop()
|
||||
*/
|
||||
public void start()
|
||||
{
|
||||
if (!log)
|
||||
{
|
||||
// don't bother timing
|
||||
return;
|
||||
}
|
||||
// overwrite the thread's timer
|
||||
ITimer timer = TimerFactory.newTimer();
|
||||
threadLocalTimer.set(timer);
|
||||
// start the timer
|
||||
timer.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Threadsafe method to stop the timer.
|
||||
*
|
||||
* @see #start()
|
||||
*/
|
||||
public void stop()
|
||||
{
|
||||
if (!log)
|
||||
{
|
||||
// don't bother timing
|
||||
return;
|
||||
}
|
||||
// get the thread's timer
|
||||
ITimer timer = threadLocalTimer.get();
|
||||
if (timer == null)
|
||||
{
|
||||
// begin not called on the thread
|
||||
return;
|
||||
}
|
||||
// time it
|
||||
timer.stop();
|
||||
recordStats(methodName, timer.getDuration());
|
||||
|
||||
// drop the thread's timer
|
||||
threadLocalTimer.set(null);
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util.perf;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import com.vladium.utils.timing.ITimer;
|
||||
import com.vladium.utils.timing.TimerFactory;
|
||||
|
||||
/**
|
||||
* An instance of this class keeps track of timings of method calls on a bean
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class PerformanceMonitorAdvice extends AbstractPerformanceMonitor implements MethodInterceptor
|
||||
{
|
||||
public PerformanceMonitorAdvice(String beanName)
|
||||
{
|
||||
super(beanName);
|
||||
}
|
||||
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable
|
||||
{
|
||||
// bypass all recording if performance logging is not required
|
||||
if (AbstractPerformanceMonitor.isDebugEnabled())
|
||||
{
|
||||
return invokeWithLogging(invocation);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no logging required
|
||||
return invocation.proceed();
|
||||
}
|
||||
}
|
||||
|
||||
private Object invokeWithLogging(MethodInvocation invocation) throws Throwable
|
||||
{
|
||||
// get the time prior to call
|
||||
ITimer timer = TimerFactory.newTimer ();
|
||||
|
||||
timer.start ();
|
||||
|
||||
//long start = System.currentTimeMillis();
|
||||
// execute - do not record exceptions
|
||||
Object ret = invocation.proceed();
|
||||
// get time after call
|
||||
//long end = System.currentTimeMillis();
|
||||
// record the stats
|
||||
timer.stop ();
|
||||
|
||||
recordStats(invocation.getMethod().getName(), timer.getDuration ());
|
||||
// done
|
||||
return ret;
|
||||
}
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.util.perf;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Enabled vm performance monitoring for <b>performance.summary.vm</b> and
|
||||
* <b>performance.PerformanceMonitorTest</b> to check.
|
||||
*
|
||||
* @see org.alfresco.util.perf.PerformanceMonitor
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class PerformanceMonitorTest extends TestCase
|
||||
{
|
||||
private PerformanceMonitor testTimingMonitor;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
Method testTimingMethod = PerformanceMonitorTest.class.getMethod("testTiming");
|
||||
testTimingMonitor = new PerformanceMonitor("PerformanceMonitorTest", "testTiming");
|
||||
}
|
||||
|
||||
public void testSetUp() throws Exception
|
||||
{
|
||||
assertNotNull(testTimingMonitor);
|
||||
}
|
||||
|
||||
public synchronized void testTiming() throws Exception
|
||||
{
|
||||
testTimingMonitor.start();
|
||||
|
||||
wait(50);
|
||||
|
||||
testTimingMonitor.stop();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user