Powered By Blogger

Thursday, December 30, 2010

Company home specific to Tenant

/**
* Gets the Company Home
*
* @return company home node ref
*/
public NodeRef getCompanyHome()
{
String tenantDomain = tenantAdminService.getCurrentUserDomain();
NodeRef companyHomeRef = companyHomeRefs.get(tenantDomain);
if (companyHomeRef == null)
{
companyHomeRef = AuthenticationUtil.runAs(new RunAsWork()
{
public NodeRef doWork() throws Exception
{
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback()
{
public NodeRef execute() throws Exception
{
List refs = searchService.selectNodes(nodeService.getRootNode(companyHomeStore), companyHomePath, null, namespaceService, false);
if (refs.size() != 1)
{
throw new IllegalStateException("Invalid company home path: " + companyHomePath + " - found: " + refs.size());
}
return refs.get(0);
}
}, true);
}
}, AuthenticationUtil.getSystemUserName());
companyHomeRefs.put(tenantDomain, companyHomeRef);
}
return companyHomeRef;
}



The above code can be found in the class Repository.class

Sunday, December 26, 2010

Changing the content Type of existing content

/**
* Code for specialising the content Type
* @param registry
* @param actionedUponNodeRef
* @param destinationType
* @return
*/
public static boolean specialiseType(ServiceRegistry registry, NodeRef actionedUponNodeRef ,QName destinationType )
{
boolean specialise = false;
if (registry.getNodeService().exists(actionedUponNodeRef) == true)
{
// Get the type of the node
QName currentType = registry.getNodeService().getType(actionedUponNodeRef);

// Ensure that we are performing a specialise
if (currentType.equals(destinationType) == false &&
registry.getDictionaryService().isSubClass(destinationType, currentType) == true)
{
// Specialise the type of the node
registry.getNodeService().setType(actionedUponNodeRef, destinationType);
specialise = true;
}
}
return specialise;
}

Monday, December 20, 2010

Why company Home is referred as app:company_home in the path queries

# Spaces Configuration
spaces.store=workspace://SpacesStore
spaces.company_home.childname=app:company_home
spaces.guest_home.childname=app:guest_home
spaces.dictionary.childname=app:dictionary
spaces.templates.childname=app:space_templates
spaces.imapConfig.childname=app:imap_configs
spaces.imap_templates.childname=app:imap_templates
spaces.emailActions.childname=app:email_actions
spaces.searchAction.childname=cm:search
spaces.templates.content.childname=app:content_templates
spaces.templates.email.childname=app:email_templates
spaces.templates.email.invite1.childname=app:invite_email_templates
spaces.templates.email.notify.childname=app:notify_email_templates
spaces.templates.rss.childname=app:rss_templates
spaces.savedsearches.childname=app:saved_searches
spaces.scripts.childname=app:scripts
spaces.wcm.childname=app:wcm
spaces.wcm_content_forms.childname=app:wcm_forms
spaces.content_forms.childname=app:forms
spaces.user_homes.childname=app:user_homes
spaces.sites.childname=st:sites
spaces.templates.email.invite.childname=cm:invite
spaces.rendition.rendering_actions.childname=app:rendering_actions
spaces.wcm_deployed.childname=cm:wcm_deployed
spaces.transfers.childname=app:transfers
spaces.transfer_groups.childname=app:transfer_groups
spaces.transfer_temp.childname=app:temp
spaces.inbound_transfer_records.childname=app:inbound_transfer_records
spaces.outbound_transfer_records.childname=app:outbound_transfer_records



The above are the keys found in repository.properties.
Since companyhome is referred in property file with app:company_home and in the spring configuration files it is used.

Thursday, December 16, 2010

Default objects of WebScript

Alfresco webscript provides some the fields access in the ftl i,e response.
like webscript,format,args,argsM,headers,url,msg.


This is achieved in the class AbstractWebScript. That is the reason our webscript should extend the DeclarativeWebScript, DeclarativeWebScript in turn extends the AbstractWebScript.


*/
protected Map createScriptParameters(WebScriptRequest req, WebScriptResponse res, ScriptDetails script, Map customParams)
{
Map params = new HashMap(32, 1.0f);

// add web script parameters
params.put("webscript", req.getServiceMatch().getWebScript().getDescription());
params.put("format", new FormatModel(container.getFormatRegistry(), req.getFormat()));
params.put("args", createArgs(req));
params.put("argsM", createArgsM(req));
params.put("headers", createHeaders(req));
params.put("headersM", createHeadersM(req));
params.put("guest", req.isGuest());
params.put("url", new URLModel(req));
params.put("msg", getScriptMessage());

// If there is a request type specific script (e.g. *.json.js), parse
// the request according to its MIME type and add request specific
// parameters. Use the FormatReader for the generalised mime type
// corresponding to the script - not necessarily the request mime type
final String contentType = req.getContentType();

Tuesday, December 7, 2010

Builoding advanced Search Query . Refer SearchContenxt class

public String buildQuery(int minimum)
{
String query;
boolean validQuery = false;

// the QName for the well known "name" attribute
String nameAttr = Repository.escapeQName(QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, ELEMENT_NAME));

// match against content text
String text = this.text.trim();

StringBuilder fullTextBuf = new StringBuilder(64);
StringBuilder nameAttrBuf = new StringBuilder(128);
StringBuilder additionalAttrsBuf = new StringBuilder(128);

if (text.length() != 0 && text.length() >= minimum)
{
if (text.indexOf(' ') == -1 && text.charAt(0) != '"')
{
// check for existance of a special operator
boolean operatorAND = (text.charAt(0) == OP_AND);
boolean operatorNOT = (text.charAt(0) == OP_NOT);
// strip operator from term if one was found
if (operatorAND || operatorNOT)
{
text = text.substring(1);
}

if (text.length() != 0)
{
// prepend NOT operator if supplied
if (operatorNOT)
{
fullTextBuf.append(OP_NOT);
nameAttrBuf.append(OP_NOT);
}

processSearchTextAttribute(nameAttr, text, nameAttrBuf, fullTextBuf);
for (QName qname : this.simpleSearchAdditionalAttrs)
{
processSearchAttribute(qname, text, additionalAttrsBuf, false, operatorNOT);
}
}
}
else
{
// multiple word search
if (text.charAt(0) == '"' && text.charAt(text.length() - 1) == '"')
{
// as a single quoted phrase
String quotedSafeText = '"' + text.substring(1, text.length() - 1) + '"';
fullTextBuf.append("TEXT:").append(quotedSafeText);
nameAttrBuf.append("@").append(nameAttr).append(":").append(quotedSafeText);
for (QName qname : this.simpleSearchAdditionalAttrs)
{
additionalAttrsBuf.append(" @").append(
Repository.escapeQName(qname)).append(":").append(quotedSafeText);
}
}
else
{
// as individual search terms
StringTokenizer t = new StringTokenizer(text, " ");

fullTextBuf.append('(');
nameAttrBuf.append('(');
additionalAttrsBuf.append('(');

int termCount = 0;
int tokenCount = t.countTokens();
for (int i=0; i {
String term = t.nextToken();

// check for existance of a special operator
boolean operatorAND = (term.charAt(0) == OP_AND);
boolean operatorNOT = (term.charAt(0) == OP_NOT);
// strip operator from term if one was found
if (operatorAND || operatorNOT)
{
term = term.substring(1);
}

// special case for AND all terms if set (apply after operator character removed)
// note that we can't force AND if NOT operator has been set
if (operatorNOT == false)
{
operatorAND = operatorAND | this.forceAndTerms;
}

if (term.length() != 0)
{
// prepend NOT operator if supplied
if (operatorNOT)
{
fullTextBuf.append(OP_NOT);
nameAttrBuf.append(OP_NOT);
}

// prepend AND operator if supplied
if (operatorAND)
{
fullTextBuf.append(OP_AND);
nameAttrBuf.append(OP_AND);
}

processSearchTextAttribute(nameAttr, term, nameAttrBuf, fullTextBuf);
for (QName qname : this.simpleSearchAdditionalAttrs)
{
processSearchAttribute(qname, term, additionalAttrsBuf, operatorAND, operatorNOT);
}

fullTextBuf.append(' ');
nameAttrBuf.append(' ');
additionalAttrsBuf.append(' ');

termCount++;
}
}
fullTextBuf.append(')');
nameAttrBuf.append(')');
additionalAttrsBuf.append(')');
}
}

validQuery = true;
}

// match a specific PATH for space location or categories
StringBuilder pathQuery = null;
if (location != null || (categories != null && categories.length !=0))
{
pathQuery = new StringBuilder(128);
if (location != null)
{
pathQuery.append(" PATH:\"").append(location).append("\" ");
if (categories != null && categories.length != 0)
{
pathQuery.append("AND (");
}
}
if (categories != null && categories.length != 0)
{
for (int i=0; i {
pathQuery.append(" PATH:\"").append(categories[i]).append("\" ");
}
if (location != null)
{
pathQuery.append(") ");
}
}
}

// match any extra query attribute values specified
StringBuilder attributeQuery = null;
if (queryAttributes.size() != 0)
{
attributeQuery = new StringBuilder(queryAttributes.size() << 6);
for (QName qname : queryAttributes.keySet())
{
String value = queryAttributes.get(qname).trim();
if (value.length() >= minimum)
{
processSearchAttribute(qname, value, attributeQuery);
}
}

// handle the case where we did not add any attributes due to minimum length restrictions
if (attributeQuery.length() == 0)
{
attributeQuery = null;
}
}

// match any extra fixed value attributes specified
if (queryFixedValues.size() != 0)
{
if (attributeQuery == null)
{
attributeQuery = new StringBuilder(queryFixedValues.size() << 6);
}
for (QName qname : queryFixedValues.keySet())
{
String escapedName = Repository.escapeQName(qname);
String value = queryFixedValues.get(qname);
attributeQuery.append(" +@").append(escapedName)
.append(":\"").append(value).append('"');
}
}

// range attributes are a special case also
if (rangeAttributes.size() != 0)
{
if (attributeQuery == null)
{
attributeQuery = new StringBuilder(rangeAttributes.size() << 6);
}
for (QName qname : rangeAttributes.keySet())
{
String escapedName = Repository.escapeQName(qname);
RangeProperties rp = rangeAttributes.get(qname);
String value1 = LuceneQueryParser.escape(rp.lower);
String value2 = LuceneQueryParser.escape(rp.upper);
attributeQuery.append(" +@").append(escapedName)
.append(":").append(rp.inclusive ? "[" : "{").append(value1)
.append(" TO ").append(value2).append(rp.inclusive ? "]" : "}");
}
}

// mimetype is a special case - it is indexed as a special attribute it comes from the combined
// ContentData attribute of cm:content - ContentData string cannot be searched directly
if (mimeType != null && mimeType.length() != 0)
{
if (attributeQuery == null)
{
attributeQuery = new StringBuilder(64);
}
String escapedName = Repository.escapeQName(QName.createQName(ContentModel.PROP_CONTENT + ".mimetype"));
attributeQuery.append(" +@").append(escapedName)
.append(":").append(mimeType);
}

// match against appropriate content type
String fileTypeQuery;
if (contentType != null)
{
fileTypeQuery = " TYPE:\"" + contentType + "\" ";
}
else
{
// default to cm:content
fileTypeQuery = " TYPE:\"{" + NamespaceService.CONTENT_MODEL_1_0_URI + "}content\" ";
}

// match against appropriate folder type
String folderTypeQuery;
if (folderType != null)
{
folderTypeQuery = " TYPE:\"" + folderType + "\" ";
}
else
{
folderTypeQuery = " TYPE:\"{" + NamespaceService.CONTENT_MODEL_1_0_URI + "}folder\" ";
}

String fullTextQuery = fullTextBuf.toString();
String nameAttrQuery = nameAttrBuf.toString();
String additionalAttrsQuery =
(this.simpleSearchAdditionalAttrs.size() != 0) ? additionalAttrsBuf.toString() : "";

if (text.length() != 0 && text.length() >= minimum)
{
// text query for name and/or full text specified
switch (mode)
{
case SearchContext.SEARCH_ALL:
query = '(' + fileTypeQuery + " AND " + '(' + nameAttrQuery + ' ' + additionalAttrsQuery + ' ' + fullTextQuery + ')' + ')' +
' ' +
'(' + folderTypeQuery + " AND " + '(' + nameAttrQuery + ' ' + additionalAttrsQuery + "))";
break;

case SearchContext.SEARCH_FILE_NAMES:
query = fileTypeQuery + " AND " + nameAttrQuery;
break;

case SearchContext.SEARCH_FILE_NAMES_CONTENTS:
query = fileTypeQuery + " AND " + '(' + nameAttrQuery + ' ' + fullTextQuery + ')';
break;

case SearchContext.SEARCH_SPACE_NAMES:
query = folderTypeQuery + " AND " + nameAttrQuery;
break;

default:
throw new IllegalStateException("Unknown search mode specified: " + mode);
}
}
else
{
// no text query specified - must be an attribute/value query only
switch (mode)
{
case SearchContext.SEARCH_ALL:
query = '(' + fileTypeQuery + ' ' + folderTypeQuery + ')';
break;

case SearchContext.SEARCH_FILE_NAMES:
case SearchContext.SEARCH_FILE_NAMES_CONTENTS:
query = fileTypeQuery;
break;

case SearchContext.SEARCH_SPACE_NAMES:
query = folderTypeQuery;
break;

default:
throw new IllegalStateException("Unknown search mode specified: " + mode);
}
}

// match entire query against any additional attributes specified
if (attributeQuery != null)
{
query = attributeQuery + " AND (" + query + ')';
}

// match entire query against any specified paths
if (pathQuery != null)
{
query = "(" + pathQuery + ") AND (" + query + ')';
}

// check that we have a query worth executing - if we have no attributes, paths or text/name search
// then we'll only have a search against files/type TYPE which does nothing by itself!
validQuery = validQuery | (attributeQuery != null) | (pathQuery != null);
if (validQuery == false)
{
query = null;
}

if (logger.isDebugEnabled())
logger.debug("Query:\r\n" + query);

return query;
}

Example to use the SearchParameters in Alfresco with maximum limit and the permission evaluation

/**
* Search for a list of nodes using the specific search context
*
* @param searchContext To use to perform the search
*/
private void searchBrowseNodes(SearchContext searchContext)
{
long startTime = 0;
if (logger.isDebugEnabled())
startTime = System.currentTimeMillis();

// get the searcher object to build the query
String query = searchContext.buildQuery(getMinimumSearchLength());
if (query == null)
{
// failed to build a valid query, the user probably did not enter the
// minimum text required to construct a valid search
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), MSG_SEARCH_MINIMUM),
new Object[] {getMinimumSearchLength()}));
this.containerNodes = Collections.emptyList();
this.contentNodes = Collections.emptyList();
return;
}

// perform the search against the repo
UserTransaction tx = null;
ResultSet results = null;
try
{
tx = Repository.getUserTransaction(FacesContext.getCurrentInstance(), true);
tx.begin();

// build up the search parameters
SearchParameters sp = new SearchParameters();
sp.setLanguage(SearchService.LANGUAGE_LUCENE);
sp.setQuery(query);
sp.addStore(Repository.getStoreRef());

// limit search results size as configured
int searchLimit = Application.getClientConfig(FacesContext.getCurrentInstance()).getSearchMaxResults();
if (searchLimit > 0)
{
sp.setLimitBy(LimitBy.FINAL_SIZE);
sp.setLimit(searchLimit);
}

results = this.getSearchService().query(sp);
if (logger.isDebugEnabled())
logger.debug("Search results returned: " + results.length());

// create a list of items from the results
this.containerNodes = new ArrayList(results.length());
this.contentNodes = new ArrayList(results.length());
if (results.length() != 0)
{
// in case of dynamic config, only lookup once
Set nodeEventListeners = getNodeEventListeners();

for (ResultSetRow row: results)
{
NodeRef nodeRef = row.getNodeRef();

if (this.getNodeService().exists(nodeRef))
{
// find it's type so we can see if it's a node we are interested in
QName type = this.getNodeService().getType(nodeRef);

// make sure the type is defined in the data dictionary
TypeDefinition typeDef = this.getDictionaryService().getType(type);

if (typeDef != null)
{
MapNode node = null;

// look for Space or File nodes
if (this.getDictionaryService().isSubClass(type, ContentModel.TYPE_FOLDER) &&
this.getDictionaryService().isSubClass(type, ContentModel.TYPE_SYSTEM_FOLDER) == false)
{
// create our Node representation
node = new MapNode(nodeRef, this.getNodeService(), false);

node.addPropertyResolver("path", this.resolverPath);
node.addPropertyResolver("displayPath", this.resolverDisplayPath);
node.addPropertyResolver("icon", this.resolverSpaceIcon);
node.addPropertyResolver("smallIcon", this.resolverSmallIcon);

this.containerNodes.add(node);
}
else if (this.getDictionaryService().isSubClass(type, ContentModel.TYPE_CONTENT))
{
// create our Node representation
node = new MapNode(nodeRef, this.getNodeService(), false);

setupCommonBindingProperties(node);

node.addPropertyResolver("path", this.resolverPath);
node.addPropertyResolver("displayPath", this.resolverDisplayPath);

this.contentNodes.add(node);
}
// look for File Link object node
else if (ApplicationModel.TYPE_FILELINK.equals(type))
{
// create our File Link Node representation
node = new MapNode(nodeRef, this.getNodeService(), false);
// only display the user has the permissions to navigate to the target of the link
NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION);
if (new Node(destRef).hasPermission(PermissionService.READ) == true)
{
node.addPropertyResolver("url", this.resolverLinkUrl);
node.addPropertyResolver("downloadUrl", this.resolverLinkDownload);
node.addPropertyResolver("webdavUrl", this.resolverLinkWebdavUrl);
node.addPropertyResolver("cifsPath", this.resolverLinkCifsPath);
node.addPropertyResolver("fileType16", this.resolverFileType16);
node.addPropertyResolver("fileType32", this.resolverFileType32);
node.addPropertyResolver("size", this.resolverSize);
node.addPropertyResolver("lang", this.resolverLang);
node.addPropertyResolver("path", this.resolverPath);
node.addPropertyResolver("displayPath", this.resolverDisplayPath);

this.contentNodes.add(node);
}
}
else if (ApplicationModel.TYPE_FOLDERLINK.equals(type))
{
// create our Folder Link Node representation
node = new MapNode(nodeRef, this.getNodeService(), false);
// only display the user has the permissions to navigate to the target of the link
NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION);
if (new Node(destRef).hasPermission(PermissionService.READ) == true)
{
node.addPropertyResolver("icon", this.resolverSpaceIcon);
node.addPropertyResolver("smallIcon", this.resolverSmallIcon);
node.addPropertyResolver("path", this.resolverPath);
node.addPropertyResolver("displayPath", this.resolverDisplayPath);

this.containerNodes.add(node);
}
}

// inform any listeners that a Node wrapper has been created
if (node != null)
{
for (NodeEventListener listener : nodeEventListeners)
{
listener.created(node, type);
}
}
}
else
{
if (logger.isWarnEnabled())
logger.warn("Found invalid object in database: id = " + nodeRef + ", type = " + type);
}
}
else
{
if (logger.isWarnEnabled())
logger.warn("Missing object returned from search indexes: id = " + nodeRef + " search query: " + query);
}
}
}

// commit the transaction
tx.commit();
}
catch (InvalidNodeRefException refErr)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {refErr.getNodeRef()}), refErr );
this.containerNodes = Collections.emptyList();
this.contentNodes = Collections.emptyList();
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
}
catch (SearcherException serr)
{
logger.info("Search failed for: " + query, serr);
Utils.addErrorMessage(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_QUERY));
this.containerNodes = Collections.emptyList();
this.contentNodes = Collections.emptyList();
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_SEARCH), new Object[] {err.getMessage()}), err );
this.containerNodes = Collections.emptyList();
this.contentNodes = Collections.emptyList();
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
}
finally
{
if (results != null)
{
results.close();
}
}

if (logger.isDebugEnabled())
{
long endTime = System.currentTimeMillis();
logger.debug("Time to query and build map nodes: " + (endTime - startTime) + "ms");
}
}


This code you can find in BrowseBean class.

org.alfresco.repo.web.scripts WebScript package

org.alfresco.repo.web.scripts

Above package is having the information related to the discussion,facebook intgration,blog,portlet , rule deletion, rule creation and Some test cases for jsonRest post etc