On 10/01/2009 12:16 PM, Anca Paula Luca wrote:
> Hi Vincent,
>
> On 10/01/2009 11:18 AM, Vincent Massol wrote:
>> Hi Anca,
>>
>> Be very very careful with ThreadLocal. It's very easy to make mistakes
>> and cause memory leaks. Actually I think you may have introduced one
>> already ;) (please do some web research on ThreadLocal you'll see it
>> has some caveats and they must absolutely be freed when the thread
>> exits).
>
> I wasn't aware of that (I just found extensive complains and references in a
> lucene issue). However, I could ensure that the threadlocal is removed after 
> the
> call is done.
>
>>
>> I believe this needs to be discussed more to ensure it's the right way
>> and doesn't cause pbs.
>>
>> Also we already have an ExecutionContext so I'm not sure why we need
>> this.
>
> indeed we don't. Seems that all initialization (execution context et all,
> XWikiContext set on execution context) is done in:
>
> XWikiServiceImpl.initializeContainerComponent
>
> and here, in the service, we should just do:
>
> protected XWikiContext getXWikiContext() {
>       return (XWikiContext)
> Utils.getComponent(Execution.class).getContext().getProperty("xwikicontext");
> }

fyi, commited this fix in r24172. I tested this on local and the functions that 
use the context don't seem to be affected. I cannot test the thread safety 
though.

Happy coding,
Anca

>
>>
>> Can you please explain?
>
> I wrongly remembered we have a good reason to not use the execution context
> mechanism to get context data, such as "not initialized in the GWT Service", 
> but
> it seems it's not the case.
>
> In an ideal threadlocal impl, this solution shouldn't have been buggy, just
> suboptimal.
>
> Thanks a lot,
> Anca
>
>>
>> Thanks
>> -Vincent
>>
>>
>> On Oct 1, 2009, at 10:13 AM, lucaa (SVN) wrote:
>>
>>> Author: lucaa
>>> Date: 2009-10-01 10:13:20 +0200 (Thu, 01 Oct 2009)
>>> New Revision: 24158
>>>
>>> Modified:
>>>     platform/web/trunk/gwt/src/main/java/com/xpn/xwiki/gwt/api/server/
>>> XWikiServiceImpl.java
>>>     platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/
>>> server/DefaultWysiwygService.java
>>> Log:
>>> XWIKI-4411: XWikiServiceImpl's xwiki context is not handled threadsafe
>>> * handled the prepared context in a ThreadLocal member.
>>>
>>>
>>> Modified: platform/web/trunk/gwt/src/main/java/com/xpn/xwiki/gwt/api/
>>> server/XWikiServiceImpl.java
>>> ===================================================================
>>> --- platform/web/trunk/gwt/src/main/java/com/xpn/xwiki/gwt/api/
>>> server/XWikiServiceImpl.java        2009-09-30 21:49:09 UTC (rev 24157)
>>> +++ platform/web/trunk/gwt/src/main/java/com/xpn/xwiki/gwt/api/
>>> server/XWikiServiceImpl.java        2009-10-01 08:13:20 UTC (rev 24158)
>>> @@ -66,7 +66,7 @@
>>> {
>>>       private static final Log LOG = LogFactory.getLog(XWiki.class);
>>>
>>> -    private XWikiContext context;
>>> +    private ThreadLocal<XWikiContext>   context;
>>>
>>>       /**
>>>        * We override the default processCall method in order to
>>> provide XWiki initialization before
>>> @@ -131,7 +131,7 @@
>>>           }
>>>
>>>           context.put("ajax", new Boolean(true));
>>> -        this.context = context;
>>> +        this.context.set(context);
>>>       }
>>>
>>>       private void initializeContainerComponent(XWikiContext context)
>>> @@ -168,7 +168,7 @@
>>>
>>>       protected XWikiContext getXWikiContext()
>>>       {
>>> -        return this.context;
>>> +        return this.context.get();
>>>       }
>>>
>>>       protected XWikiGWTException getXWikiGWTException(Exception e) {
>>>
>>> Modified: platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/
>>> wysiwyg/server/DefaultWysiwygService.java
>>> ===================================================================
>>> --- platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/
>>> server/DefaultWysiwygService.java   2009-09-30 21:49:09 UTC (rev 24157)
>>> +++ platform/web/trunk/wysiwyg/src/main/java/com/xpn/xwiki/wysiwyg/
>>> server/DefaultWysiwygService.java   2009-10-01 08:13:20 UTC (rev 24158)
>>> @@ -302,14 +302,8 @@
>>>                   getXWikiContext().setDatabase(wikiName);
>>>               }
>>>               spaceNamesList =
>>> getXWikiContext().getWiki().getSpaces(getXWikiContext());
>>> -            // get the blacklisted spaces from the session as
>>> they've been set in xwikivars.vm, when the page edited
>>> -            // with this wysiwyg was loaded
>>> -            // TODO: remove this when the public API will exclude
>>> them by default, or they'll be set in the config
>>> -            List<String>   blacklistedSpaces =
>>> -                (ArrayList<String>)
>>> getThreadLocalRequest
>>> ().getSession().getAttribute("blacklistedSpaces");
>>> -            if (blacklistedSpaces != null&&
>>> blacklistedSpaces.size()>   0) {
>>> -                spaceNamesList.removeAll(blacklistedSpaces);
>>> -            }
>>> +            // remove the blacklisted spaces from the all spaces list
>>> +            spaceNamesList.removeAll(getBlackListedSpaces());
>>>               Collections.sort(spaceNamesList);
>>>           } catch (XWikiException e) {
>>>               e.printStackTrace();
>>> @@ -322,6 +316,26 @@
>>>       }
>>>
>>>       /**
>>> +     * Helper function to retrieve the blacklisted spaces in this
>>> session, as they've been set in xwikivars.vm, when the
>>> +     * page edited with this wysiwyg was loaded.<br />
>>> +     * TODO: remove this when the public API will exclude them by
>>> default, or they'll be set in the config.
>>> +     *
>>> +     * @return the list of blacklisted spaces from the session
>>> +     */
>>> +    @SuppressWarnings("unchecked")
>>> +    private List<String>   getBlackListedSpaces()
>>> +    {
>>> +        // get the blacklisted spaces from the session
>>> +        List<String>   blacklistedSpaces =
>>> +            (ArrayList<String>)
>>> getThreadLocalRequest
>>> ().getSession().getAttribute("blacklistedSpaces");
>>> +        // always return a list, even if blacklisted spaces
>>> variable wasn't set
>>> +        if (blacklistedSpaces == null) {
>>> +            blacklistedSpaces = new ArrayList<String>();
>>> +        }
>>> +        return blacklistedSpaces;
>>> +    }
>>> +
>>> +    /**
>>>        * {...@inheritdoc}
>>>        *
>>>        * @see WysiwygService#getPageNames(String, String)
>>> @@ -379,12 +393,31 @@
>>>           throws XWikiGWTException
>>>       {
>>>           try {
>>> +            String quote = "'";
>>> +            String doubleQuote = "''";
>>>               // FIXME: this fullname comparison with the keyword does
>>> not contain the wiki name
>>> -            String escapedKeyword = keyword.replaceAll("'",
>>> "''").toLowerCase();
>>> +            String escapedKeyword = keyword.replaceAll(quote,
>>> doubleQuote).toLowerCase();
>>> +            // add condition for the doc to not be in the list of
>>> blacklisted spaces.
>>> +            // TODO: might be a pb with scalability of this
>>> +            String noBlacklistedSpaces = "";
>>> +            List<String>   blackListedSpaces = getBlackListedSpaces();
>>> +            if (!blackListedSpaces.isEmpty()) {
>>> +                StringBuffer spacesList = new StringBuffer();
>>> +                for (String bSpace : blackListedSpaces) {
>>> +                    if (spacesList.length()>   0) {
>>> +                        spacesList.append(", ");
>>> +                    }
>>> +                    spacesList.append(quote);
>>> +                    spacesList.append(bSpace.replaceAll(quote,
>>> doubleQuote));
>>> +                    spacesList.append(quote);
>>> +                }
>>> +                noBlacklistedSpaces = "doc.web not in (" +
>>> spacesList.toString() + ")";
>>> +            }
>>>               List<XWikiDocument>   docs =
>>>                   getXWikiContext().getWiki().search(
>>> -                    "select distinct doc from XWikiDocument as doc
>>> where lower(doc.title) like '%" + escapedKeyword
>>> -                        + "%' or lower(doc.fullName) like '%" +
>>> escapedKeyword + "%'", count, start, getXWikiContext());
>>> +                    "select distinct doc from XWikiDocument as doc
>>> where " + noBlacklistedSpaces
>>> +                        + " and (lower(doc.title) like '%" +
>>> escapedKeyword + "%' or lower(doc.fullName) like '%"
>>> +                        + escapedKeyword + "%')", count, start,
>>> getXWikiContext());
>>>               return prepareDocumentResultsList(docs);
>>>           } catch (XWikiException e) {
>>>               throw getXWikiGWTException(e);
>>> @@ -406,7 +439,7 @@
>>>           for (XWikiDocument doc : docs) {
>>>               com.xpn.xwiki.gwt.api.client.Document xwikiDoc = new
>>> com.xpn.xwiki.gwt.api.client.Document();
>>>               xwikiDoc.setFullName(doc.getFullName());
>>> -
>>> xwikiDoc.setTitle(doc.getDisplayTitle(getXWikiContext()));
>>> +
>>> xwikiDoc.setTitle(doc.getRenderedTitle(Syntax.XHTML_1_0,
>>> getXWikiContext()));
>>>               // FIXME: shouldn't use upload URL here, but since we
>>> don't want to add a new field...
>>>               xwikiDoc.setUploadURL(doc.getURL(VIEW_ACTION,
>>> getXWikiContext()));
>>>               results.add(xwikiDoc);
>>>
>>> _______________________________________________
>>> notifications mailing list
>>> [email protected]
>>> http://lists.xwiki.org/mailman/listinfo/notifications
>>
>> _______________________________________________
>> devs mailing list
>> [email protected]
>> http://lists.xwiki.org/mailman/listinfo/devs
> _______________________________________________
> devs mailing list
> [email protected]
> http://lists.xwiki.org/mailman/listinfo/devs
_______________________________________________
devs mailing list
[email protected]
http://lists.xwiki.org/mailman/listinfo/devs

Reply via email to