
<!--
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   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.
-->

<project xmlns="http://maven.apache.org/DECORATION/1.3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/DECORATION/1.3.0 http://maven.apache.org/xsd/decoration-1.3.0.xsd"
         name="Apache Tez">
  <skin>
    <groupId>org.apache.maven.skins</groupId>
    <artifactId>maven-fluido-skin</artifactId>
    <version>1.3.0</version>
  </skin>
  <custom>
    <fluidoSkin>
      <topBarEnabled>true</topBarEnabled>
      <sideBarEnabled>true</sideBarEnabled>
      <leftColumnClass>span2</leftColumnClass>
      <bodyColumnClass>span10</bodyColumnClass>
      <twitter>
        <user>ApacheTez</user>
        <showUser>true</showUser>
      </twitter>
    </fluidoSkin>
  </custom>

  <bannerLeft>
    <name>Apache Tez</name>
    <src>./images/ApacheTezLogo_lowres.png</src>
    <width>25%</width>
    <height>25%</height>
    <href>http://tez.apache.org/</href>
  </bannerLeft>

  <bannerRight>
    <name>Apache Software Foundation</name>
    <src>http://www.apache.org/images/asf_logo.gif</src>
    <href>http://www.apache.org/</href>
  </bannerRight>

  <publishDate position="right"/>
  <version position="none"/>

  <body>
    <head>
       <!-- Start of Google analytics 
       <script type="text/javascript">
         var _gaq = _gaq || [];
         _gaq.push(['_setAccount', '']);
         _gaq.push(['_trackPageview']);

         (function() {
            var ga = document.createElement('script'); 
            ga.type = 'text/javascript'; ga.async = true;
            ga.src = ('https:' == document.location.protocol ? 
                      'https://ssl' : 'http://www') + 
                     '.google-analytics.com/ga.js';
            var s = document.getElementsByTagName('script')[0]; 
            s.parentNode.insertBefore(ga, s);
          })();
       </script>
       End of Google analytics -->
       <style>
           .well.sidebar-nav {
             background-color: #fff;
           }
           a.externalLink[href^=http] {
             background-image: none;
             padding-right: 0;
           }
           body.topBarEnabled {
             padding-top: 40px;
           }
           #leftColumn .nav-list .active a {
             background-color: #a0a0a0;
           }
           .nav-list .active a:hover {
             background-color: #a0a0a0;
           }
       </style>
    </head>

    <breadcrumbs>
      <item name="Apache TEZ&#174;" href="http://tez.apache.org/"/>
    </breadcrumbs>

    <menu name="Getting Started">
      <item name="Overview" href="index.html"/>
      <item name="Talks and Meetup Recordings" href="talks.html"/>
      <item name="Project License" href="http://www.apache.org/licenses/LICENSE-2.0.txt"/>
    </menu>

    <menu name="Documentation">
      <item name="Install Guide" href="install.html"/>
      <item name="Local Mode" href="localmode.html"/>
      <item name="Tez UI" href="tez-ui.html"/>
      <item name="Tez Shuffle Handler" href="shuffle-handler.html"/>
      <item name="User Guides" href="user_guides.html"/>
    </menu>

    <menu name="Community">
      <item name="Mailing Lists" href="mail-lists.html"/>
      <item name="Issue Tracking" href="issue-tracking.html"/>
      <item name="Project Team" href="team-list.html"/>
      <item name="Project By-Laws" href="by-laws.html"/>
      <item name="User Meetup Group" href="http://www.meetup.com/Apache-Tez-User-Group"/>
      <item name="Tez Wiki" href="https://cwiki.apache.org/confluence/display/TEZ"/>
    </menu>

    <menu name="Download Apache TEZ&#174; Releases">
      <item name="0.4.1-incubating" href="http://archive.apache.org/dist/incubator/tez/tez-0.4.1-incubating/"/>
      <item name="0.5.4" href="./releases/apache-tez-0-5-4.html"/>
      <item name="0.6.2" href="./releases/apache-tez-0-6-2.html"/>
      <item name="0.7.1" href="./releases/apache-tez-0-7-1.html"/>
      <item name="0.8.5" href="./releases/apache-tez-0-8-5.html"/>
      <item name="0.9.0" href="./releases/apache-tez-0-9-0.html"/>
      <item name="0.9.1" href="./releases/apache-tez-0-9-1.html"/>
      <item name="All Releases" href="./releases/index.html"/>
    </menu>

    <menu name="Contribute">
      <item name="JIRA" href="https://issues.apache.org/jira/browse/TEZ" />
      <item name="Git (Read/Write)" href="https://gitbox.apache.org/repos/asf/tez.git" alt="Use git clone https://gitbox.apache.org/repos/asf/tez.git" />
      <item name="Git (Read-only)" href="git://git.apache.org/tez.git" alt="Use git clone git://git.apache.org/tez.git" />
      <item name="How to Contribute" href="https://cwiki.apache.org/confluence/display/TEZ/How+to+Contribute+to+Tez" alt="Detailed guide on how to contribute to Tez" />
    </menu>

    <menu name="ASF">
      <item name="License" href="http://www.apache.org/licenses/" />
      <item name="Donate" href="http://www.apache.org/foundation/sponsorship.html" />
      <item name="Thanks" href="http://www.apache.org/foundation/thanks.html" />
      <item name="Security" href="http://www.apache.org/security/" />
    </menu>

    <footer>
      <div class="row span12">
        Apache Tez, Apache, the Apache feather logo, and the Apache Tez project logos are trademarks of The Apache Software Foundation.
        All other marks mentioned may be trademarks or registered trademarks of their respective owners.
      </div>
      <br/>
      <div class="row span12">
        <a href="privacy-policy.html">Privacy Policy</a>
      </div>
    </footer>

  </body>
</project>
