Sample Tomcat Startup Scripts

General Blogs October 22, 2013 By Brett Swaim Staff

I have had many clients ask me if Liferay has management scripts for Apache Tomcat. While Liferay doesn't officially recommend any particular way to start/stop Tomcat, I have found this works really well for me on client sites.

You’ll need to make the script executable by running the chmod command:
sudo chmod 755 /etc/init.d/liferay
The last step is actually linking this script to the startup folders with a symbolic link. Execute these two commands and we should be on our way.
sudo ln -s /etc/init.d/liferay /etc/rc1.d/K99liferay
sudo ln -s /etc/init.d/liferay /etc/rc2.d/S99liferay



Using log4j to ensure each portlet has it's own log file

Company Blogs July 24, 2012 By Brett Swaim Staff

Recently I was at a client site, who had just over 30 portlets deployed. When debugging was enabled, catalina.out was so saturated with log statements that it was nearly impossible to track what needed to be tracked. I changed their portlets to log to both the console like normal, and also to log to it's own file. After looking around a bit, I see this is a somewhat common quesiton in the Liferay forums, so I've decided to paste my solution here for all to use. I always use the Liferay plugins sdk, so this example will reflect those paths. If you do something different, just keep that in mind.


To have a portlet log to both catalina.out (the console) and to it's own file, in bundles/logs/porlet-name-(date).log


Create: /path/to/plugins/sdk/portlets/myloggingexample-portlet/docroot/WEB-INF/src/

inside the src folder, I added two files: log4j.xml and log4j.dtd

I grabbed the log4j.dtd from the liferay portal source

Content of log4j.xml
<?xml version="1.0"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="">
    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}:%L] %m%n" />
    <appender name="FILE" class="org.apache.log4j.rolling.RollingFileAppender">
        <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
            <param name="FileNamePattern" value="../../logs/portlet-name.%d{yyyy-MM-dd}.log" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}:%L] %m%n" />
    <category name="com.myclient" >
        <priority value="TRACE" />
        <priority value="INFO" />
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
We have now configured log4j, but we don't have the jars yet! To get those modify and add:
Now, when the portlet is deployed those jars will automatically be taken from Liferay to ensure version consistency. 
Lastly, you need to setup your logger in your class. Add:
import org.apache.log4j.Logger;
to your imports, and inside your class (I do is as the last line), add:
private static Logger _log = Logger.getLogger(MyClassName.class);
and with that, you can call _log.fatal("test"); and see that it shows up both in the console and one directory above tomcat, in the logs folder. I set it up that way because we have bundles/logs and bundles/tomcat, so my file will show up in bundles/logs/myportlet-name-date.log
Hopefully this will make debugging and log viewing a little less messy for you!


WCS Followup

Company Blogs September 26, 2011 By Brett Swaim Staff

I just wanted to say thanks to everybody that attended my talks. I really enjoyed giving them and hope you all got something from them that was helpful! I'll be posting my files/powerpoints (or links to them) soon.

WCS 2011 Upgrade Workshop. Community input needed.

Company Blogs August 22, 2011 By Brett Swaim Staff

Hello Liferay Community!

I'll be running an upgrade workshop during WCS 2011 in Anaheim, CA. During that workshop, I'll be upgrading a Liferay 5.2.3 installation to Liferay 6.1 CE. I have data that I can use, but what fun is that?! I would like to upgrade one community members 5.2.3 installation to 6.1 CE for this.

So here is my plan, if you all send me links to a zip of your plugins sdk that contains your ext plugin, portlets, hooks, webs, and everything else I will choose one person's data set to use during the workshop. When the workshop completes, I will give that data back to the contributer so they get a free 6.1 CE upgrade! Keep in mind that this code will be made public (at least to the people participating in the workshop) so if you have code that is under NDA I can't use it. 

E-mail me a link to your zip file at and I'll pick a code set by September 2nd, 2011!

You don't have to be going to WCS to participate in the code submission!

An updated method of using the web content portlet for advanced actions

Company Blogs June 9, 2010 By Brett Swaim Staff

After viewing Bruno's blog, I decided to show it at ECS during two of my presentations. There are some changes though in trunk, and I wanted to make sure to reflect those changes to you all.

Everything is the same except his FAQ-PORTLET.vm file which I have attached here: VM File

Thanks to everybody who attended my talks!


Blogs Entry Navigation Improved

Company Blogs April 20, 2009 By Brett Swaim Staff

As of trunk revision 29951, there is now a way to get to the next and previous blog entry from the blogs entry view page.

What is the communities thoughts on the previous and next button placement? I'm open to suggestions if it's not obvious enough. Perhaps move it to the top?


Configure your file upload settings from control panel

Company Blogs April 14, 2009 By Brett Swaim Staff

You can now configure your File Upload settings from control panel (5.2.3+), including allowed extensions and max file sizes!


New way to change pop/smtp settings

Company Blogs April 14, 2009 By Brett Swaim Staff

In the never ending effort to make Liferay easier to configure, mail settings can now be set in the control panel (5.2.3+). To do so, go to the control panel and click server administration, then click the Mail tab. Enter your data and go from there!

Users can now specify a password at account creation

Company Blogs April 14, 2009 By Brett Swaim Staff

I made a slight change to the login portlet that gives the user the option to create their own password, instead of always having a random password emailed to them at creation time. To enable this new functionality, edit and paste this line:


Keep in mind that this is for 5.2.3+, or trunk revision 26905+.

Message Board Searching

Company Blogs April 14, 2009 By Brett Swaim Staff

After some time of using our message boards, I have realized that when you are searching for something it isn't very clear what scope you are in. I have made some changes ( that will help clear up the ambiguity a little bit.

This is how searching looks now:


Notice the search button text, how it is now clear if you are searching in a specific category, or all categories. I hope the community likes it!

The Hardest Part of Coding

Company Blogs December 3, 2007 By Brett Swaim Staff

What is the hardest part about programming? I've heard many suggestions by peers, bosses, employees, students and professors. I've heard algorithms, front end (html/javascript), backend (database connections, classes), code analysis, and reading/decifering other peoples code just to name a few.

While I would agree that all these things can have their hard parts, I don't believe that any of those are really the hardest things to do. Yes, javascript is awkward, especially if you are used to strongly typed objects. Absolutely java can be off if you are used to loosly type (or not even typed at all) code. Algorithms can be confusing, especially when you start nesting loops. Understanding somebody elses code can be VERY difficult at times. These things still don't make me think that any of them are the hardest part of our job.

So what do I think the hardest part of coding is? I don't think it's the coding at all! I think the hardest part is decifering requirements sent down from business, especially if business is new to the game or in general doesn't know how web programming works. Depending on your management structure this may or may not be an issue, but over the years that I've been coding I think this is the most prevelant problem in coding today.

Maybe you are lucky and most of your requirements actually make sense. If that's the case then I would say the next hardest thing for most programmers would be attention to detail. In my experiance, programmers tend to gloss over requirements, see the general look and feel, and dive in. I know I've been guilty of this, and I know others have been as well. The problem isn't really that we do a once over and start setting up a skeleton and maybe some basic obvious actions. The issues arise when we stop looking at the requirements because we "see how it's supposed to go". I would say seven out of ten times I have to take a portlet or action back to the programmer that did it and show him/her four or five things that were missed. These things tend to not be big, and they also tend to not lend themselves to a story title. Here is an example:

A login flow story is presented to the programmer. It gives the programmer a few criteria for login/logout actions like when somebody logs in, they must stay on their current page. When somebody logs out the should be left on the current page in guest mode. If they logout on a secure screen it should give them a login screen. If they login, it should take them back to the secure page they were on.

This makes sense, and feels like a login/logout flow. The issue is that the requirements weren't closely read, and the checkbox for "Remember Me" that was supposed to be added at the same time was missed. It was also missed that there must now be a forgot password and create account link. I really believe this was missed because of the word "flow" in the story title. Adding those items doesn't really feel like flow to me, it seems like a login action requirement. I hear flow, and I think okay, you are already logged in... now what? Or, you are logging out, where should you go?

So the question that I would present is: Who's fault is it that this was missed? Obviously the issue lies on the coders shoulders as the coder was given the document. The problems with this is the coder was given a 5 page document and one paragraph in the middle added the new login links. Once again, I'm not relieving the coder of blame, but I do believe that the writer of the specs could have broken that up into two stories. Sometimes we get requirements where you can actually see the train of thought that went into a meeting. Business is talking about login flow and perhaps in our sandbox environment playing with it. They are talking about what happens once you login and logout, and somebody in the back of the room has a brainstorm... "Let's add forgot password, remember me, and create account on this portlet!" Cheers are heard throughout the building as this person is praised for their wisdom, and they just write down that requirement right then and there. Clearly it is a good idea, but nobody stood up and said "Hey, maybe this is out of scope for this story?". As programmers or tech leads we can't be in every business meeting and still have any time to code, so we can't police these things and fix it right then and there. Once we recieve that requirement it's like an afterthough, an idea shoved in between two more seperate ideas. Idea A and C are highly coupled, idea B snuck in like a green beret and is hiding between the lines.

I think the solution here falls on the tech lead. We all know that PMs and SMEs (Subject Matter Experts) don't have to code the ideas they come up with. They can mix whatever they want into their cauldren of requirements and just toss it over the preverbial wall for the coders. The tech lead needs to thoroughly read the requirements before they ever even get to the coders and try to rip out the stuff that doesn't fit. I say this as the current tech lead, and this is what I'm going to try to start doing from now on. I know all the other leads are sneering at this right now, because frankly that's crap work. It's not fun, nobody really wants to do it, but somebody has to. I would rather my team of coders spent 100% of their time coding instead of parsing through requirements and coming to me or the PM and asking if we can rip requirements out of this or that and move them somewhere else. Having the tech lead to this also moves blame off of the devs and to the lead. Once again, I realize that kindof sucks, but there is a reason he is tech lead and they are programmers.... he is okay at leadership, he usually has some sort of people skills, and he can take more hits from the upper management. That is a generalization, but I honestly believe it to be true in more cases than not.

There is a large side benefit to this strategy. If the TL goes through all the reqs line by line before the planning meetins where things are assigned, he could answer most questions that the devs might have without having to ask business. If he doesn't understand something himself, he should have asked business before the meeting... this has the plus of getting things fixed before a dev spends two days coding a zip code lookup when it turns out that we really need the full address. Clearly not everything can be caught, and things will slip through the cracks, but I'm pretty confident that this would lower the go-back rate to about three in ten.

There is also a downside to this strategy; however, in that this effectively kills the tech leads ability to code for about a week before the meeting. This also doesn't catch last minute changes done by business (I know, I know, they would never do that). It is for this reason alone that I love using a wiki or Confluence (Altassian) to hold requirements. I can read a requirement and then set a watch on the page. If that page changes I will get an email immediately about it, thus I will at least know something has changed, and at best I will have the time to go over the changes and make sure that they didn't add "Create living kittens from the HP Inkjet" to the requirements page. That's a shoutout to Penny Arcade for those that didn't catch it.

JUGs in Ohio (Columbus)

Company Blogs December 3, 2007 By Brett Swaim Staff

Since there are now six Liferay developers living in Columbus, Ohio Monday through Thursday I was thinking that we could start showing up the JUGs if anybody is interested. I have done quite a bit of training on Liferay, and we would have a few guys there that really know the Liferay architecture well. If anybody would be interested in having us show up one night and speak on Liferay, OSS, java, and webapps in general we would be happy to oblige. We tend to be available Monday, Tuesday, and Wednesday evenings from 6pm - midnight. Please e-mail me at bswaim at liferay dot com and we can set something up.

Topics we would love to chat about:

  • Liferay installation
  • IDE setup and debugging (Eclipse, Intellij)
  • Creating new portlets in Liferay
  • Working with current code in Liferay, overriding code to change default portal features
  • Liferay architecture
  • The OSS community, and what role Liferay plays in OSS
  • Portal technology in general
  • General support for problems in Liferay
  • AJAX in Liferay using service builder, jQuery, and JSON.

We would love to see problems people are having with their installations or running portals and try to help out with that as well.

Why I use IntelliJ instead of Eclipse

Company Blogs December 3, 2007 By Brett Swaim Staff

When I first started at Liferay I started using Eclipse. After about six months I found the Web Toolkit for Eclipse. I used that for about a year and a half total, until I got staffed consulting for the current company I'm consulting for. Once I got here I saw that all the in house developers were using IntelliJ Idea. As we are an open source software company, we qualify for free IntelliJ licenses so I decided to give it a shot. I've now been using IntelliJ for about ten months, and I must say that I love this thing.

What is the difference?


  • Can be a little faster on the debug side, although to be fair I switched to a Macbook Pro nearly the same time I switched to IntelliJ, so it could be that.
  • Lots of plugins
  • Hot deploying classes and jsps into Liferay (no tomcat bounce required)
  • Can be faster when reindexing deployed files
  • Open Source
  • Ctrl+Shift+O for optimizing imports easily. I have yet to find the equivilant in IntelliJ. it will remove unused imports for you, but not import ones you need.
  • Free
  • No licensing concerns
  • Did I mention free?


  • Amazing configurations for ignore lists, no indexing and searching compiled classes unless you want to.
  • In windows the debugger can use shared memory, in OS X I can only get socket working which can be slower
  • Expression evaluations on the fly
  • Intellisense is really great once you get used to it
  • Auto import of classes in JSPs
  • Steller JSP support overall, ability to jump into a java class from a jsp just like you can from a java file
  • Great javascript support, I even got my IntelliJ to autocomplete jQuery statements for me.
  • Facets are really cool, you can very easily change relative paths
  • Find useages of a method by clicking it and holding Shift+F7
  • XML Auto completion from a DTD
  • Code coloring of Velocity
  • Local history
  • While Ctrl+Shift+O doesn't do what I want, 99% of the time when you copy/paste code it automatically adds the imports for you so you shouldn't have to Ctrl+shift+o

I want to talk a few of these for a minute, as Facets, JSP integration, and local history were the deciding factors in me staying with IntelliJ over eclipse. Overall they are both good IDEs, I even built a few plugins for Eclipse, but IntelliJ just does a few things so much better that it tips the scales.

Local history can actually be trusted in IntelliJ. I had so many problems with Eclipse where I would change something, close eclipse for some reason, and need to see what I changed again. Short of going to SVN I could never get this to reliably work in Eclipse... with IntelliJ it just works, every single time.

Liferay has a somewhat strange layout for it's web-inf and html folders. In Eclipse I never really code path completion to work well in JSPs because it always looked at the wrong spot for files. In IntelliJ I just setup different facets that will help the IDE help me. Here is an example. I have a facet called WEB-INF. In Liferay, when you reference a file in WEB-INF (tagfiles are a GREAT example here) you do it like this:

<%@ taglib prefix="showMore" tagdir="/WEB-INF/tags/wj/showmore" %>

The problem there is that by default, the IDE wants to autocomplete like this:

<%@ taglib prefix="showMore" tagdir="/docroot/WEB-INF/tags/wj/showmore" %>

I simply made a web facet and said that when I type /WEB-INF I really want you to look at /docroot/WEB-INF. This small change saves me so much headache throughout the day. I also did the same thing with /html instead of /docroot/html.

You know how in eclipse when you go to an init.jsp file in the ext environment it always freaks about the init.jsp includes from portal because it can't find it? I once again used a web facet (called portal-web) and I linked / to /liferay/builds/4.3.x/portal-web/docroot. Now when I say:

<%@ include file="/

right there it starts autocompleting. It lists out everything in both portal-web and ext-web for me, because I have access to both inside Liferay! Doing this then:

<%@ include file="/html/common/init.jsp" %>

it's a problem, I can even click init.jsp and press ctrl (cmd) + b and it will jump me right into the init file in portal.

I tend to run IntelliJ with one "Module" and two "Content Roots". One content root is portal, the other is ext. The plus here is that the debugger knows about the portal source files, and I can easily jump between jsp files as well.

As for the Intellisense a great example of why it's so cool is the following:

I can go to a view.jsp and type "WCLSU" and ctrl+alt+space and it will gve me a dropdown that asks which class I want. In my case I create WhatCountsLocaServiceUtil and WhatCountsLocalServiceUtilTest (You do make jUnit tests for your code, right?). I hit enter and then ctrl+space, which gives me a list of it's methods to choose from. Once I choose one, it adds the import statement for me at a specified position in the page (you can set this in project settings). See screenshots below for what it looks like.

Johnny Rockets

Company Blogs November 29, 2007 By Brett Swaim Staff

I love Johnny Rockets

Here is a pic of the Ohio crew in the new Johnny Rockets in CMH

Exchange 2003

Company Blogs November 13, 2007 By Brett Swaim Staff

How do I love thee? Let me count the ways.

  1. Push mail
  2. Sync'd Calendars
  3. Sync'd Todos
  4. Sync'd Mail
  5. Sync'd Contacts

I love that when somebody sends me an email, Exchange 2003 pushes said mail right to my phone.. no waiting! I love that when said email contains a calendar invite I can accept it and not only does it add the appointment to my phone, I see it in Outlook Web Access and on all my computers (Office 2004 for my mac, Office 2007 for Vista). I love that when I put a todo on my Vista machine to get milk, I can walk right out the door, go to the store, and see on my phone exactly what to get... I love that on a high priority message my HTC Wizard reads the email to me immediately! I love that I can start an email from my phone, go to my computer, open drafts, and finish the email!!

What's that? You sent me an email a week ago and I need data from it while I'm on the road? That's okay, it's on exchange I can grab it!! I need a phone number for a co-worker but don't have it saved in my contacts? That's okay, when I start dialing my exchange server will use LDAP to hit my companies LDAP and search for anyone there AS I DIAL!!!

I weep as I realize that one day I may have to get rid of my Exchange server or my HTC Wizard... that day will be such a sad day...


Company Blogs November 13, 2007 By Brett Swaim Staff

So last night as I sat in my hotel room in Ohio I was reading a thread about Android, Google's open handset OS. I decided to download the SDK and give it a crack. The first things I noticed were the steller documentation and the ease of constructing a basic app... I had created a simple hello world app in about 15 minutes, 13 of those being reading the doc. It made me realize a few things, first off I could parrot the age old "Liferay's documentation isn't that great" which we all know, but I feel I shouldn't. There is a significant difference between creating a basic app in Android and creating a portlet in Liferay. I would actually argue that it's much easier to modify Liferay code in the EXT environment than it is to create an app in Android. If you need to change a jsp, simply duplicate the path in ext and change what you need to... it's that easy. Of course creating portlets and DAO stuff will be harder than a phone app... it's a lot more robust. The second thing that I realized is that Android is very very basic at this point, the SDK isn't there yet.. but when it does get there I hope we as a team can learn from what they have done and perhaps integrate their ideas into our core.

In my free time when I get stuck on some Liferay stuff I'm working on I'm thinking about clearing my mind by working on an Android app... but what should it be? It could be a Liferay app (webdav access anyone?) or something along those lines... but I'm unsure.. give me suggestions!

Tagfiles VS Taglibs

Company Blogs November 8, 2007 By Brett Swaim Staff

I recently had the realization that I was duplicating a certain set of code across multiple portlets. For those who know me, they will attest that my work motto is to work smart not hard. I hate code duplication with a fiery passion, thus something had to be done. The question was what? After some thought, I decided that I needed to make a taglib. I started coding it, and had a realization... a tagfile would be much easier!

So what is a tagfile? Tagfiles were introduced with JSP 2.0. They were created because sometimes a taglib is jsut too much work for what it does. For many simple and even some complex operations, tagfiles are like coding magic.  Let's compare the two:

  • Taglibs:
  • Class driven
  • Uses a tld that can be from any site
  • JSP 1.1 compatible.
  • Tagfiles
    • JSP driven
    • No tld required
    • Works immediately without any compile
    • Really easy!

So if you can't guess, I chose to use a tagfile. Before I show you the code, let's do a high level overview of what is required for tagfiles.

  1. You
  2. A tags folder under WEB-INF (/WEB-INF/tags)
  3. A folder under that with the name of the tag
  4. a .tag file

So lets make a basic Hello World tagfile that outputs the text "Hello World in (Insert Year Here)".


Step 1: create /WEB-INF/tags/hello-world/hello.tag
Step 2: enter the following in hello.tag:

<%@attribute name="year" required="true"%>

Hello World in <%=year%>

Step 3: Edit your JSP that you want the hello world to show up in. Enter this code:

<%@ taglib prefix="showMore" tagdir="/WEB-INF/tags/hello-world" %>
<showMore:hello />

That should be all that's required. Refresh your jsp. Eat cake.

So sure, that's cool and all... but you could EASILY accomplish the same this with a simple file include. Where is the excitement? The drama? It's right here, you just don't know it yet.

Let's do a more useful example. Let's say that you hate using our <portlet:actionURL /> taglib... you want something easier and cleaner. I know in my IDE it always breaks my <a href's /> when I put it in. Time to fix that. This tagfile will do the following: create a Struts url (maximized or minimized) to a struts path, if a clean way that IDEs understand.

Step 1: create init.tag under hello-world
Step 2: enter the following in init.tag

<%@ tag import="" %>
<%@ tag import="com.liferay.portal.kernel.util.StringPool" %>
<%@ tag import="com.liferay.portal.service.permission.PortletPermissionUtil" %>

<%@ taglib uri="" prefix="c" %>
<%@ taglib uri="" prefix="portlet" %>
<%@ taglib uri="" prefix="liferay-theme" %>
<%@ taglib uri="" prefix="liferay-ui" %>

<%@ taglib uri="" prefix="bean" %>
<%@ taglib uri="" prefix="html" %>
<%@ taglib uri="" prefix="logic" %>
<%@ taglib uri="" prefix="nested" %>
<%@ taglib uri="" prefix="tiles" %>

<%@ tag import="com.liferay.portal.util.PortalUtil" %>
<%@ tag import="com.liferay.portal.util.PortletKeys" %>
<%@ tag import="javax.portlet.WindowState" %>
<%@ tag import="java.text.DateFormat" %>
<%@ tag import="java.util.List" %>

<%@attribute name="maximized" type="java.lang.Boolean"%>
<%@attribute name="struts_path" required="true" %>
<%@attribute name="actionUrl" type="java.lang.Boolean"%>

<portlet:defineObjects />
<liferay-theme:defineObjects />

    String currentURL = PortalUtil.getCurrentURL(request);

Notice that this looks a lot like a regular liferay init.jsp... that's because it almost is! We just replace <%@page %> with <%@tag %>.

Step 3: edit hello.tag with the following code:

<%@include file="init.tag"%>

    String windowState=null;
    if (maximized != null) {
        windowState = WindowState.MAXIMIZED.toString();
    else {
        windowState = WindowState.NORMAL.toString();
    if (actionUrl != null) {
    <portlet:actionURL windowState="<%=windowState%>">
        <portlet:param name="struts_action" value="<%=struts_path%>" />
    else {
    <portlet:renderURL windowState="<%=windowState%>">
        <portlet:param name="struts_action" value="<%=struts_path%>" />

Step 4: Lastly, enter this into your jsp.

<showMore:hello struts_path="/a/view" maximized="true" actionUrl="true"/>

Take note that your struts path will change, and that struts_path is the only one required...

Step 5: Reload your page, enjoy your beautiful link.

Step 6: Enjoy more cake.

Introducing the Ohio crew!

Company Blogs November 6, 2007 By Brett Swaim Staff

This is a picture of the Liferay crew that has invaded ohio.


From left to right:

David Rison
Brett Swaim
David Truong
Brian Kim
Sten Martinez

It's getting cold!!! Notice how BKim has his ski jacket on.

Flight Regulations 2

Company Blogs October 21, 2007 By Brett Swaim Staff

I got through gate security just fine. Next time I know that flying without ID is called flying "selectee". I can simply go to the agent and the ticket counter and tell them I am flying selectee and I'm good to go. As an aside, since the TSA takes you aside and searches your carryons and such they take you right to the front. On a busy day, that has to be faster than actually flying regular! I was almost through faster than my coworker, and it was a pretty short line!

Flight Regulations

Company Blogs October 18, 2007 By Brett Swaim Staff

Today is the day I will try to fly home with no ID. I will be handing my ID to my co-worker and he will walk through security with it. I will keep you updated as time goes on with the status of my flight plans, and in the end if I succeed or not.
Showing 20 results.
Items 20
of 1