Saturday, January 13, 2007

Tomahawk Bridge 0.9.1 released

Tomahawk Bridge 0.9.1 was released! It supports Tomahawk 1.1.3 on any portal servers. Using this portlet filter with Faces Resonse Filter, you can use Upload component and some components that uses JavaScript and CSS. In this release, synchronized issue was fixed.

To use Tomahawk Bridge:
1) Add faces-response-filter-0.2.jar, portals-bridges-portletfilter-1.0.jar, tomahawk-bridge-0.9.1.jar, commons-fileupload-1.1.jar and commons-io-1.1.jar to /WEB-INF/lib
2) Modify portlet.xml

For example, if you use the following portlet.xml,

<portlet-app id="vfs-portlets" version="1.0">
<portlet id="VFSNavigator">
<description>VFS Navigator</description>
<portlet-name>VFSNavigator</portlet-name>
<display-name>VFS Navigator</display-name>
<portlet-class>
jp.sf.pal.vfs.portlets.VFSPortlet
</portlet-class>
<init-param>
<name>view-page</name>
<value>/jsp/ListView.jsp</value>
</init-param>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>VFS Navigator</title>
<short-title>VFS</short-title>
</portlet-info>
</portlet>
</portlet-app>

change it to:

<portlet-app id="vfs-portlets" version="1.0">
<portlet id="VFSNavigator">
<description>VFS Navigator</description>
<portlet-name>VFSNavigator</portlet-name>
<display-name>VFS Navigator</display-name>
<portlet-class>org.apache.portals.bridges.portletfilter.FilterPortlet</portlet-class>
<init-param>
<name>portlet-class</name>
<value>jp.sf.pal.vfs.portlets.VFSPortlet</value>
</init-param>
<init-param>
<name>portlet-filters</name>
<value>jp.sf.pal.facesresponse.FacesResponseFilter,jp.sf.pal.tomahawk.filter.ExtensionsPortletFilter</value>
</init-param>
<init-param>
<name>view-page</name>
<value>/jsp/ListView.jsp</value>
</init-param>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>VFS Navigator</title>
<short-title>VFS</short-title>
</portlet-info>
</portlet>
</portlet-app>

Note: you need to set "server" as javax.faces.STATE_SAVING_METHOD in web.xml. Currently, "client" is not supported.

For Portals Portlet Filter, please see Apache Portals Bridges.

Tohamawk Bridge depends on Faces Response Filter. Faces Response Filter provides a feature to rewrite JSF resonse. So, if you create a new other filter, such as Ajax4JSF filter, I think that you can use both Tomahawk and Ajax4JSF components.

Thanks!

27 Comments:

Anonymous Anonymous said...

Hi Shinsuke,

Does it solve the Tomahawk t:InputCalendar issue? Calendar was not working as popup in 0.9.0 release. I get the following error when click the button to popup the calendar.

Error: frm1_3Aic1CalendarVar is not defined
Source File: http://localhost:9898/c/portal/layout?p_l_id=PRI.15.2
Line: 1

Thanks,

Raj

8:43 PM  
Anonymous Anonymous said...

Hi Shinsuke,

This looks great, but I'm having one or two problems.

I've configured my portlets as you suggest, but when I load them in liferay, I get "An error occurs on loading style. STATUS=404" for each of my portlets on the page.

Would you suggest what I might be doing wrong?

Also, how do I configure max file upload size etc for the tomahawk bridge?

Thanks,

Dave

9:56 PM  
Anonymous Anonymous said...

Hi Shinsuke,

I'm also regularly getting the following error and am unable to resolve it:


ERROR [jsp:52] java.lang.IllegalStateException: BufferedResponseStream is null.
at jp.sf.pal.facesresponse.io.BufferedResponseStreamFactory.render(BufferedResponseStreamFactory.java:121)
at jp.sf.pal.facesresponse.FacesResponseFilter.renderFilter(FacesResponseFilter.java:78)
at org.apache.portals.bridges.portletfilter.PortletFilterChain.renderFilter(PortletFilterChain.java:114)
at org.apache.portals.bridges.portletfilter.FilterPortlet.render(FilterPortlet.java:141)
at com.liferay.portal.kernel.servlet.PortletServlet.service(PortletServlet.java:94)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:368)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:672)
at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:574)
at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:499)
at com.liferay.portlet.CachePortlet._invoke(CachePortlet.java:333)
at com.liferay.portlet.CachePortlet.render(CachePortlet.java:182)
at org.apache.jsp.html.portal.render_005fportlet_jsp._jspService(render_005fportlet_jsp.java:949)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:332)



Any ideas?

Thanks,

Dave

(p.s. Is there somewhere else I should be posting this stuff?)

12:21 AM  
Anonymous Anonymous said...

BufferedResponseStream problem:

try it with myfaces 1.1.4. (1.1.5 does not seem to be compatible with tomahawk bridge)

11:47 PM  
Anonymous Anonymous said...

Hi Shinsuke,

first said:Great Work, your bridge works just fine for me. My question may be not that smart: How can I get rid of all the System.out's? My log file shows the whole rendering and scipr information, and I've got a hard time discovering my own loggin.

9:46 PM  
Anonymous shinsuke said...

please check your configuration for commons-logging, log4j or the like.

1:59 AM  
Anonymous Anonymous said...

I had the same bufferedresponse stream problem in jboss portal 2.2.1 sp3 with myfaces 1.1.4 and tomahawk 1.1.3, i had to make some minor changes in the code of facesresponsefilter to make it work.

Using the patched facesresponse i got the tomahawak 1.1.3 client side tree2 and the upload component to work nicely inside a myfaces portlet. thanks shinsuke for your great work.

the original code of BufferedResponseStreamFactory.java
if (FacesResponseUtil.isMyFacesFacesContext()) {
// for MyFaces
// MyFaces needs this workaround code because of the implementation
// issue..
return (BufferedResponseStream) context.getExternalContext()
.getSessionMap().get(
FacesResponseConstants.BUFFERED_RESPONSE_STREAM);
} else {
// for JSF implementation whice does not pass FacesContext from
// processAction to render
return (BufferedResponseStream) context.getExternalContext()
.getRequestMap().get(
FacesResponseConstants.BUFFERED_RESPONSE_STREAM);


i had to change it to return context.getExternalContext()
.getRequestMap().get(
FacesResponseConstants.BUFFERED_RESPONSE_STREAM);

everytime,seems theres no need for the if (FacesResponseUtil.isMyFacesFacesContext()) atleast in my env.

8:08 AM  
Anonymous Anonymous said...

to add to the above post, i did not have to do the mods that shinsuke had earlier mentioned to get the bridge working in jboss portal like removing the jsf-lib dir etc.

8:11 AM  
Blogger Shinsuke said...

Thank you for the info! I'll apply it at a next update.

9:17 AM  
Anonymous Anonymous said...

Hi Shinsuke,

I'm using Tomahawk Bridge 0.9.1 ant MyFaces-Core-1.1.4 and getting the following Error, any Idea?

thans in advance,
omid

ERROR
2007-04-16 11:08:42,593 DEBUG [jp.sf.pal.facesresponse.FacesResponseFilter] - called renderFilter.
2007-04-16 11:08:42,656 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/MileStoneBeta]] - Exception in FacesServlet
java.lang.NullPointerException
at org.apache.myfaces.portlet.MyFacesGenericPortlet.facesRender(MyFacesGenericPortlet.java:392)
at org.apache.myfaces.portlet.MyFacesGenericPortlet.doView(MyFacesGenericPortlet.java:265)
at javax.portlet.GenericPortlet.doDispatch(GenericPortlet.java:133)
at javax.portlet.GenericPortlet.render(GenericPortlet.java:306)
at org.apache.portals.bridges.portletfilter.PortletFilterChain.renderFilter(PortletFilterChain.java:121)
at jp.sf.pal.tomahawk.filter.ExtensionsPortletFilter.renderFilter(ExtensionsPortletFilter.java:163)
at org.apache.portals.bridges.portletfilter.PortletFilterChain.renderFilter(PortletFilterChain.java:116)
at jp.sf.pal.facesresponse.FacesResponseFilter.renderFilter(FacesResponseFilter.java:76)
at org.apache.portals.bridges.portletfilter.PortletFilterChain.renderFilter(PortletFilterChain.java:116)
at org.apache.portals.bridges.portletfilter.FilterPortlet.render(FilterPortlet.java:144)
at org.jboss.portal.portlet.container.PortletContainer.invokeRender(PortletContainer.java:518)
at org.jboss.portal.portlet.container.PortletContainer.dispatch(PortletContainer.java:434)
at org.jboss.portal.portlet.container.PortletContainerInvoker$1.dispatch(PortletContainerInvoker.java:144)
at org.jboss.portal.portlet.invocation.PortletInvocation.dispatch(PortletInvocation.java:223)
at org.jboss.portal.common.invocation.Invocation.invokeNext(Invocation.java:141)
....
....
2007-04-16 11:08:42,671 ERROR [jp.sf.pal.facesresponse.FacesResponseFilter] - javax.portlet.PortletException: java.lang.NullPointerException
2007-04-16 11:08:42,671 ERROR [org.jboss.portal.portlet.container.org_apache_portals_bridges_portletfilter_FilterPortlet] - The portlet threw an exception
javax.portlet.PortletException: javax.portlet.PortletException: java.lang.NullPointerException
at jp.sf.pal.facesresponse.FacesResponseFilter.renderFilter(FacesResponseFilter.java:81)
at org.apache.portals.bridges.portletfilter.PortletFilterChain.renderFilter(PortletFilterChain.java:116)
at org.apache.portals.bridges.portletfilter.FilterPortlet.render(FilterPortlet.java:144)
at org.jboss.portal.portlet.container.PortletContainer.invokeRender(PortletContainer.java:518)
at org.jboss.portal.portlet.container.PortletContainer.dispatch(PortletContainer.java:434)
at org.jboss.portal.portlet.container.PortletContainerInvoker$1.dispatch(PortletContainerInvoker.java:144)
at org.jboss.portal.portlet.invocation.PortletInvocation.dispatch(PortletInvocation.java:223)
at org.jboss.portal.common.invocation.Invocation.invokeNext(Invocation.java:141)
...

2:46 PM  
Blogger Shinsuke said...

The line 392 "if (facesContext.getResponseComplete()) return;". facesContext might be null in your application. In FacesResponseFilter and Tomahawk bridge, I think that it just caught the exception.

9:43 AM  
Anonymous Omid said...

Hi Shinsuke,

thank you very much for the hint...
I have overwritten the facesRenderer with these:

@Override
protected void facesRender(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
if(logger.isDebugEnabled())
logger.debug("called facesRender");

setContentType(request, response);

String viewId = request.getParameter(VIEW_ID);
if ((viewId == null) || sessionTimedOut(request))
{
setPortletRequestFlag(request);
nonFacesRequest(request, response);
return;
}

setPortletRequestFlag(request);

try
{
ServletFacesContextImpl facesContext = (ServletFacesContextImpl)request.
getPortletSession().
getAttribute(CURRENT_FACES_CONTEXT);

if (facesContext == null) // processAction was not called
{
logger.warn("facesContext is null");
facesContext = (ServletFacesContextImpl)facesContext(request, response);
setViewRootOnFacesContext(facesContext, viewId);
}

// TODO: not sure if this can happen. Also double check this against spec section 2.1.3
if (facesContext.getResponseComplete()) return;

facesContext.setExternalContext(makeExternalContext(request, response));
lifecycle.render(facesContext);
}
catch (Throwable e)
{
handleExceptionFromLifecycle(e);
}
}

// Set the view root on a FacesContext to prepare for rendering
private void setViewRootOnFacesContext(FacesContext facesContext, String view)
{
ApplicationFactory appFactory =
(ApplicationFactory)FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
Application application = appFactory.getApplication();
ViewHandler viewHandler = application.getViewHandler();
UIViewRoot viewRoot = viewHandler.createView(facesContext, view);
viewRoot.setViewId(view);
facesContext.setViewRoot(viewRoot);
}

now it works for me so far.
But now I have another problem.
When I try to load a tabbedPane I get the following Error:
An Error occures on loading style. STATUS=500
in my log I get the following message:
2007-04-17 10:00:26,984 DEBUG [jp.sf.pal.facesresponse.io.BufferedResponseStream] - commit()- byteArrayOutputStream=null
2007-04-17 10:00:26,984 DEBUG [jp.sf.pal.facesresponse.io.BufferedResponseStream] - getReader()
2007-04-17 10:00:26,984 DEBUG [jp.sf.pal.facesresponse.io.BufferedResponseStream] - getInputStream()
2007-04-17 10:00:27,906 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Returning cached instance of singleton bean 'portletSessionContextIntegrationInterceptor'
2007-04-17 10:00:27,906 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/MileStoneBeta].[default]] - Servlet.service() for servlet default threw exception
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'portletSessionContextIntegrationInterceptor' must be of type [javax.servlet.Filter], but was actually of type [org.acegisecurity.context.PortletSessionContextIntegrationInterceptor]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:313)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:165)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:646)
at org.acegisecurity.util.FilterChainProxy.obtainAllDefinedFilters(FilterChainProxy.java:220)
at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:135)
at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
at java.lang.Thread.run(Thread.java:619)
2007-04-17 10:00:27,984 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Returning cached instance of singleton bean 'portletSessionContextIntegrationInterceptor'
2007-04-17 10:00:27,984 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/MileStoneBeta].[default]] - Servlet.service() for servlet default threw exception
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'portletSessionContextIntegrationInterceptor' must be of type [javax.servlet.Filter], but was actually of type [org.acegisecurity.context.PortletSessionContextIntegrationInterceptor]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:313)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:165)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:646)
at org.acegisecurity.util.FilterChainProxy.obtainAllDefinedFilters(FilterChainProxy.java:220)
at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:135)
at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
at java.lang.Thread.run(Thread.java:619)

Thanks again for your help,

Omid

1:38 PM  
Blogger Shinsuke said...

I think that it's better to check your spring configuration.

2:38 PM  
Anonymous Omid said...

Hi Shinsuke,
I played a little with the Tomahawk Bridge 0.9.1 and now it seems to run with Tomahawk 1.1.5. Let's say: at the moment i don't get any Error messages but these One:

2007-04-26 16:05:47,218 ERROR [org.apache.myfaces.config.FacesConfigurator] - You are using the MyFaces-package : tomahawk in different versions; first (and probably used) version is : 1.1.5, currently encountered version is : bridge-0.9.1. This will cause undesired behaviour. Please clean out your class-path. The first encountered version is loaded from : file:/C:/jboss-4.0.4.GA/server/default/tmp/deploy/tmp2674MileStoneBeta-exp.war/WEB-INF/lib/tomahawk-1.1.5.jar. The currently encountered version is loaded from : jar:file:/C:/jboss-4.0.4.GA/server/default/tmp/deploy/tmp2674MileStoneBeta-exp.war/WEB-INF/lib/tomahawk-bridge-0.9.1.jar!/META-INF/MANIFEST.MF

any suggestions?

by the way I would like to use t:panedTab and t:inputCalender. It seems to load all these stuff but I have the Impression that javaScripts are'nt run...


ps.: if I am posting to much and to big, then I want to excuse myself. Just a word and I will not do that again ;)

regards,
Omid

8:05 PM  
Anonymous Andy said...

I've managed to get the extensions filter working within pluto but the included resources (javascript, css, etc) are all posted after the content of the portlet and hence the javascript will not run. The call to chain.renderFilter within the renderFilter method of the filter seams to write the content of the portlet out to the response immediately and the it is followed by the resources. Is there something I am missing.

Thanks,

Andy

8:13 PM  
Anonymous shinsuke said...

Tomahawk Bridge depends on Faces Resonse Filter,

8:58 AM  
Blogger Shrinidhi said...

Hi Sinsuke,

I have managed to use tomahawk fileUpload component in Jboss portal 2.4.2 with the help of tomahawk bridge 0.9.1
The only problem is that I am stuck with myfaces 1.1.4 because and not able to use myfaces 1.1.5 (for its fixes). If I use myfaces 1.1.5, like everybody I am getting the following error :

java.lang.IllegalStateException: BufferedResponseStream is null

Is there a fix for this? Can anyone please help me here. I am really running short of time. Thanks.

Regards,
Shrinidhi

2:00 AM  
Blogger Shrinidhi said...

Any hope of an answer?? I am still waiting anxiously ...

11:36 PM  
Anonymous shinsuke said...

Currently, since I'm using Teeda as JSF implementation, I do not use myfaces. So, I'm not sure when I have time to look into that..

8:32 AM  
Blogger Ben said...

This is extremely useful. Thanks.

I'm finding that getBufferedResponseStream returns NULL for processAction. I'm using MyFaces 1.1.5 and it seems that FacesResponseUtil.isMyFacesFacesContext isn't working. I changed the code to this:

BufferedResponseStream stream = (BufferedResponseStream) request.getPortletSession() .getAttribute(FacesResponseConstants.BUFFERED_RESPONSE_STREAM);

if (stream != null)
return stream;

return (BufferedResponseStream) request .getAttribute(FacesResponseConstants.BUFFERED_RESPONSE_STREAM);

which fixes the problem.

4:54 AM  
Anonymous free ps3 said...

Thanks for the nice post!

7:49 AM  
Anonymous Anonymous said...

Hi Sugaya-San,

For info, this works fine with MyFaces 1.1.6 + Tomahawk 1.1.7-SNAPSHOT on WebSphere Portal Server 6.0.

Thanks!

6:43 PM  
Anonymous David said...

Does the FacesResponseFilter and the ExtensionsPortletFilter need mapping in the webapp's web.xml ?

7:54 PM  
Blogger shinsuke said...

No. They are a portlet filter. You do not need to put them into web.xml.

6:43 PM  
Anonymous website design New York City said...

nice post

3:00 PM  
Blogger seo expert said...

it very useful



website design New York City website design nyc

3:00 PM  
Blogger buy wow gold said...

When the Wow Gold wolf finally found the wow gold cheap hole in the chimney he crawled cheap wow gold down and KERSPLASH right into that kettle of water and that was cheapest wow gold the end of his troubles with the big bad wolf.

game4power.
The next day the Buy Wow Goldlittle pig invited hisbuy gold wow mother over . She said "You see it is just as mttgamingI told you. The way to get along in the world is to do world of warcraft gold things as well as you can." Fortunately for that little pig, he buy cheap wow gold learned that lesson. And he just agamegold lived happily ever after!.

9:07 PM  

Post a Comment

<< Home