Revision: 103 http://mvn-infix.svn.sourceforge.net/mvn-infix/?rev=103&view=rev Author: bindul Date: 2010-12-22 01:57:20 +0000 (Wed, 22 Dec 2010)
Log Message: ----------- We can generate the PHP script now Modified Paths: -------------- plugins/sfnet-mvnrepo-plugin/trunk/src/main/java/com/mindtree/techworks/infix/plugins/sfnetmvnrepo/actions/RepoHandlerGenAction.java plugins/sfnet-mvnrepo-plugin/trunk/src/test/java/com/mindtree/techworks/infix/plugins/sfnetmvnrepo/actions/RepoHandlerGenActionTest.java Added Paths: ----------- plugins/sfnet-mvnrepo-plugin/trunk/src/main/resources/includes/ plugins/sfnet-mvnrepo-plugin/trunk/src/main/resources/includes/repo-handler.php plugins/sfnet-mvnrepo-plugin/trunk/src/main/resources/velocity/repositories.inc.vm Modified: plugins/sfnet-mvnrepo-plugin/trunk/src/main/java/com/mindtree/techworks/infix/plugins/sfnetmvnrepo/actions/RepoHandlerGenAction.java =================================================================== --- plugins/sfnet-mvnrepo-plugin/trunk/src/main/java/com/mindtree/techworks/infix/plugins/sfnetmvnrepo/actions/RepoHandlerGenAction.java 2010-12-22 01:48:15 UTC (rev 102) +++ plugins/sfnet-mvnrepo-plugin/trunk/src/main/java/com/mindtree/techworks/infix/plugins/sfnetmvnrepo/actions/RepoHandlerGenAction.java 2010-12-22 01:57:20 UTC (rev 103) @@ -21,12 +21,15 @@ package com.mindtree.techworks.infix.plugins.sfnetmvnrepo.actions; import java.io.File; +import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.Map; import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.io.URLInputStreamFacade; import com.mindtree.techworks.infix.plugins.sfnetmvnrepo.SfNetMvnMojoInfo; import com.mindtree.techworks.infix.plugins.sfnetmvnrepo.mapper.MapGenerationException; @@ -46,6 +49,16 @@ * The htaccess template */ private static final String TEMPLATE_HTACCESS = "/velocity/htaccess.vm"; + + /** + * The template to write the repositories include + */ + private static final String TEMPLATE_REPOSITORIES_INC = "/velocity/repositories.inc.vm"; + + /** + * The repository handler file + */ + private static final String REPO_HANDLER_FILE = "/includes/repo-handler.php"; private MojoInfo mojoInfo; @@ -83,15 +96,46 @@ } createHtAccess(redirectBase); - - // TODO Auto-generated method stub - + createRepositoryInclude(); + copyRepoHandler(); } /** + * Copies the repository handler script to the output directory + * @throws MapGenerationException If there is an IO exception copying the file + */ + private void copyRepoHandler () throws MapGenerationException { + URL repoHandlerloc = getClass().getResource(REPO_HANDLER_FILE); + File outputFile = new File (mojoInfo.getWorkDirectory(), "repo-handler.php"); + try { + FileUtils.copyStreamToFile(new URLInputStreamFacade(repoHandlerloc), outputFile); + } catch (IOException e) { + mojoInfo.getLog().error("Error copying repo-handler script", e); + throw new MapGenerationException("Error copying repo-handler script", e); + } + } + + /** * Creates the htaccess file * @throws MapGenerationException For velocity exceptions */ + private void createRepositoryInclude () throws MapGenerationException { + File repoIncOutput = new File (mojoInfo.getWorkDirectory(), "repositories.inc"); + + Map<String, Object> contextInfo = new HashMap<String, Object>(2); + contextInfo.put("mojoInfo", mojoInfo); + try { + processVelocityTemplate(TEMPLATE_REPOSITORIES_INC, contextInfo, repoIncOutput, true); + } catch (Exception e) { + mojoInfo.getLog().error("Error generating repositories.inc script", e); + throw new MapGenerationException("Error generating repositories.inc script", e); + } + } + + /** + * Creates the htaccess file + * @throws MapGenerationException For velocity exceptions + */ private void createHtAccess (String redirectBase) throws MapGenerationException { File htAccessOutput = new File (mojoInfo.getWorkDirectory(), ".htaccess"); Added: plugins/sfnet-mvnrepo-plugin/trunk/src/main/resources/includes/repo-handler.php =================================================================== --- plugins/sfnet-mvnrepo-plugin/trunk/src/main/resources/includes/repo-handler.php (rev 0) +++ plugins/sfnet-mvnrepo-plugin/trunk/src/main/resources/includes/repo-handler.php 2010-12-22 01:57:20 UTC (rev 103) @@ -0,0 +1,508 @@ +<!-- + | + | Copyright (c) 2010, MindTree Ltd. + | All rights reserved. + | + | Redistribution and use in source and binary forms, with or without + | modification, are permitted provided that the following conditions are met: + | - Redistributions of source code must retain the above copyright + | notice, this list of conditions and the following disclaimer. + | - Redistributions in binary form must reproduce the above copyright + | notice, this list of conditions and the following disclaimer in the + | documentation and/or other materials provided with the distribution. + | - Neither the name of MindTree Ltd. nor the names of its contributors + | may be used to endorse or promote products derived from this software + | without specific prior written permission. + | + | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + | POSSIBILITY OF SUCH DAMAGE. + | + | $Id$ +--> +<?php + +/** + * Represents a file, directory or 404 Not found node returned by the repository + * that sends a response to the user + * + * @author Bindul Bhowmik + * @version 1.0 + * @access public + * @copyright MindTree Ltd. + */ +interface Node { + + /** + * Executes the logic in the node + */ + public function execute (); +} + +/** + * Returned when the requested tree axis is not found in the repository + * + * @author Bindul Bhowmik + * @version 1.0 + * @access public + * @copyright MindTree Ltd. + */ +class E404NotFound implements Node { + + /** + * The requested path that was requested + * @var string + */ + private $path; + + public function __construct( $pathNotFound ) { + $this->path = $pathNotFound; + } + + /** + * (non-PHPdoc) + * @see Node::execute() + */ + public function execute() { + $message = 'Requested path ['.$this->path.'] is not available on this server.'; + HttpUtils::sendError($message); + } +} + +/** + * Represents a file node that is sent using a 302 Found redirect + * + * @author Bindul Bhowmik + * @version 1.0 + * @access public + * @copyright MindTree Ltd. + */ +class FileNode implements Node { + + /** + * The redirect URL for the file + * @var string + */ + private $fileUrl; + + public function __construct( $fileUrl ) { + $this->fileUrl = $fileUrl; + } + + /** + * (non-PHPdoc) + * @see Node::execute() + */ + public function execute() { + HttpUtils::redirect($this->fileUrl); + } +} + +/** + * Represents a directory tree that is displayed + * + * @author Bindul Bhowmik + * @version 1.0 + * @access public + * @copyright MindTree Ltd. + */ +class DirNode implements Node { + + /** + * The repository map object + * @var SimpleXMLElement + */ + private $directory; + + /** + * The repository object + * @var MvnRepository + */ + private $repository; + + /** + * The complete path to the location + * @var string + */ + private $completePath; + + public function __construct( $directory, $repository, $completePath ) { + $this->directory = $directory; + $this->repository = $repository; + $this->completePath = $completePath; + } + + private function writeHeader () { + print '<?xml version="1.0" encoding="UTF-8" ?>'; + print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'; + print '<html xmlns="http://www.w3.org/1999/xhtml">'; + print ' <head>'; + print ' <meta http-equiv="Cache-control" content="no-cache"/>'; + print ' <meta http-equiv="pragma" content="no-cache" />'; + print ' <style type="text/css">'; + print ' body {'; + print ' font-family: "trebuchet ms", sans-serif;'; + print ' font-size: 11pt;'; + print ' background-color: #fff;'; + print ' color: #555;'; + print ' }'; + print ' a,a:active,a:hover,a:visited {'; + print ' text-decoration: none;'; + print ' }'; + print ' #header {'; + print ' margin-bottom: 2em;'; + print ' padding-bottom: 0.5em;'; + print ' border-bottom: 2px double gray;'; + print ' width: 100%;'; + print ' }'; + print ' #content ul {'; + print ' list-style: none;'; + print ' }'; + print ' .parentDir {'; + print ' margin-bottom: 0.5em;'; + print ' margin-left: -1em;'; + print ' }'; + print ' #footer {'; + print ' width: 100%;'; + print ' font-size: 0.8em;'; + print ' margin-top: 1em;'; + print ' padding-top: 1em;'; + print ' border-top: 1px solid gray;'; + print ' }'; + print ' </style>'; + print ' <meta http-equiv="Content-Type" content="text/html; charset=UTF-8 />'; + print ' <title>' . $this->repository->getRepositoryName() . '</title>'; + print ' </head>'; + } + + private function writeBodyHeader () { + print ' <body>'; + print ' <div id="container">'; + print ' <div id="header">'; + print ' <h1>' . $this->repository->getRepositoryName() . '</h1>'; + print ' <h2>' . $this->completePath . '</h2>'; + print ' </div>'; + print ' <div id="content">'; + print ' <ul>'; + print ' <li class="parentDir"><a href="../">Parent Directory</a></li>'; + } + + private function writeFooter () { + print ' </ul>'; + print ' </div>'; + print ' <div id="footer">'; + // TODO Implement this +// print ' ${footerHtml}'; + print ' <br />'; + print ' Powered by MindTree Infix SFNet Mvn Repo Plugin'; + print ' </div>'; + print ' </div>'; + print ' </body>'; + print '</html>'; + } + + private function writeChildren ( $element, $suffix = '' ) { + if (!is_null($element)) { + foreach ($element->children() as $child) { + print ' <li><a href="' . $child['nodeId'] . $suffix . '">' . $child['name'] . $suffix . '</a></li>'; + } + } + + } + + /** + * (non-PHPdoc) + * @see Node::execute() + */ + public function execute() { + $this->writeHeader(); + $this->writeBodyHeader(); + + foreach ($this->directory->children() as $child) { + if ($child->getName() == 'directories') { + $this->writeChildren($child, '/'); + } else if ($child->getName() == 'files') { + $this->writeChildren($child); + } + } + + $this->writeFooter(); + } +} + +/** + * The repository class, represents a single repository handled by + * the generated repository handler + * + * @author Bindul Bhowmik + * @version 1.0 + * @access public + * @copyright MindTree Ltd. + */ +class MvnRepository { + /** + * The Id of the repository it is also the path element + * + * @var string + * @access private + */ + private $repositoryId; + + /** + * The index file for the repository + * + * @var string + * @access private + */ + private $repositoryIndex; + + /** + * The name of the repository, is identified at runtime parsing the + * repo index + * @var string + * @access private + */ + private $repositoryName; + + /** + * The base redirect URL for this directory, used for file download + * calculations + * @var string + */ + private $baseRedirectUrl; + + /** + * Checks if the object has been initialized + * @var boolean + * @access private + */ + private $isInitialized; + + /** + * The repository map object + * @var SimpleXMLElement + */ + private $repositoryMap; + + /** + * Creates a new Repository object + * @param string $repoId The repository id + * @param string $repoIndex Path to the repository map file + */ + public function __construct( $repoId, $repoIndex ) { + $this->repositoryId = $repoId; + $this->repositoryIndex = $repoIndex; + $this->isInitialized = false; + } + + public function getRepositoryName () { + if (!$this->isInitialized) { + $this->initialize(); + } + return $this->repositoryName; + } + + /** + * Initializes the object. Checks to see that the repository index is + * present, if not throws an exception. + * + * @throws Exception If the index file is not present or is not valid + */ + private function initialize () { + if ($this->isInitialized) { + return ; + } + if (file_exists($this->repositoryIndex)) { + $this->repositoryMap = simplexml_load_file($this->repositoryIndex); + $this->repositoryName = $this->repositoryMap['name']; + $this->baseRedirectUrl = $this->repositoryMap['redirectBase']; + } else { + throw new Exception("Repository map is unavailable for repository: ".$this->repositoryId, 500); + } + } + + private function findChild ($currentNode, $childName) { + foreach ($currentNode->children() as $child) { + if ($child->count() > 0) { + foreach ($child->children() as $grandChild) { + if ($grandChild['nodeId'] == $childName) { + return $grandChild; + } + } + } + } + return NULL; + } + + /** + * Finds a node in the repository. Returns a Node object. May throw an + * exception + * + * @param string $relativePath The relative path within the repository + * @return Node object + * @throws Exception if the index file is not present or is not valid + */ + public function find ( $relativePath, $completePath ) { + if (!$this->isInitialized) { + $this->initialize(); + } + + $pathElems = explode ("/", $relativePath); + if (is_array($pathElems) && count ($pathElems) == 1 && $pathElems[0] == "") { + // Special case, someone requested the root... send a directory browse + return new DirNode($this->repositoryMap, $this, $completePath); + } + + // Loop through till we find the node + $redirectUrl = rtrim($this->baseRedirectUrl, "/"); + $currentNode = $this->repositoryMap; + + // Start going down the tree... + foreach ($pathElems as $pathElem) { + + // Find the child + $currentNode = $this->findChild ($currentNode, $pathElem); + if ($currentNode == NULL) { + break; + } + + if (!is_null($currentNode['redirectBase'])) { + $redirectUrl = rtrim($currentNode['redirectBase'], "/"); + } else { + $redirectUrl = $redirectUrl.'/'.$currentNode['nodeId']; + } + } + + if ($currentNode != NULL) { + // We found something - get the type + + if ($currentNode->getName() == 'directory') { + return new DirNode($currentNode, $this, $completePath); + } else if ($currentNode->getName() == 'file') { + $fileUrl = $redirectUrl; + if (!is_null($currentNode['urlSuffix'])) { + $fileUrl = $fileUrl.$currentNode['urlSuffix']; + } + return new FileNode($fileUrl); + } else { + throw new Exception('Invalid repository configuration', 500); + } + } else { + return new E404NotFound($completePath); + } + } +} + +/** + * HTTP Utility methods for use in the Repository handling + * + * @author Bindul Bhowmik + * @version 0.1 + * @copyright MindTree Ltd. + * @access public + */ +class HttpUtils { + + /** + * HTTP Status Code constants + * + * @var array + * @access public + */ + public static $HTTP_STATUS_CODES = array( + 301 => 'Moved Permanently', + 302 => 'Found', + 303 => 'See Other', + 404 => 'Not Found', + 500 => 'Internal Server Error'); + + /** + * Utility function to write the common headers + * + * @param integer $httpStatus The HTTP status code + * @param string $httpStatusMsg The HTTP Status message + * @param string $contentType The content type + */ + private static function writeCommonHeaders ( $httpStatus, $httpStatusMsg, $contentType ) { + + $statusLine = $_SERVER['SERVER_PROTOCOL'] . ' ' . $httpStatus . ' ' . $httpStatusMsg; + header ( $statusLine, true, $httpStatus ); + header( 'Content-Type: text/html; charset=' . $contentType ); + header( 'Connection: close' ); + } + + /** + * Sends a HTTP 301/302 redirect + * + * @param string $url The URL to send the redirect to + * @param integer $redirectType The redirection code to use, defaults to 302. + * @param string $statusMsg The status message for the HTTP response. Defaults to values defined in the $HTTP_STATUS_CODES constant + * @param string $contentType Character encoding in the response, defaults to 'UTF-8' + */ + public static function redirect( $url, $redirectType = 302, $statusMsg = false, $contentType = 'UTF-8' ) { + + if ( $statusMsg ) { + self::writeCommonHeaders ( $redirectType, $statusMsg, $contentType ); + } else { + self::writeCommonHeaders ( $redirectType, self::$HTTP_STATUS_CODES[$redirectType], $contentType ); + } + + header( 'Location: ' . $url ); + + // RFC 2616 Section 10.3 + print 'Redirecting to <a href="' . $url . '">' . $url . '</a>.'; + + exit (0); + } + + /** + * Sends an error message to the user agent + * + * @param string $errorMessage The error message + * @param integer $httpStatus The error code, defaults to 404 Not Found + * * @param string $statusMsg The status message for the HTTP response. Defaults to values defined in the $HTTP_STATUS_CODES constant + * @param string $contentType Character encoding in the response, defaults to 'UTF-8' + */ + public static function sendError( $errorMessage, $httpStatus = 404, $httpStatusMsg = false, $contentType = 'UTF-8') { + + if ($httpStatusMsg) { + self::writeCommonHeaders ( $httpStatus, $httpStatusMsg, $contentType ); + } else { + self::writeCommonHeaders ( $httpStatus, self::$HTTP_STATUS_CODES[$httpStatus], $contentType ); + } + + print $errorMessage; + exit(1); + } +} + +include "repositories.inc"; + +// Now the actual logic +$repoId = $_GET['repo']; +$relativePath = rtrim($_GET['relpath'], "/"); +$completePath = $_GET['compPath']; + +// Check if we can find the repository +if (array_key_exists($repoId, $REPOSITORIES)) { + // Repository exists + $repository = $REPOSITORIES[$repoId]; + try { + $node = $repository->find($relativePath, $completePath); + // Now execute the node + $node->execute(); + } catch (Exception $e) { + HttpUtils::sendError($e->getMessage(), $e->getCode()); + } +} else { + HttpUtils::sendError("Requested repository [".$repoId."] not available on the server"); +} +?> \ No newline at end of file Property changes on: plugins/sfnet-mvnrepo-plugin/trunk/src/main/resources/includes/repo-handler.php ___________________________________________________________________ Added: svn:mime-type + text/x-php-source Added: svn:keywords + Date Author Id Revision HeadURL Added: svn:eol-style + native Added: plugins/sfnet-mvnrepo-plugin/trunk/src/main/resources/velocity/repositories.inc.vm =================================================================== --- plugins/sfnet-mvnrepo-plugin/trunk/src/main/resources/velocity/repositories.inc.vm (rev 0) +++ plugins/sfnet-mvnrepo-plugin/trunk/src/main/resources/velocity/repositories.inc.vm 2010-12-22 01:57:20 UTC (rev 103) @@ -0,0 +1,29 @@ +#* + * + * Copyright (c) 2010 MindTree Ltd. + * + * This file is part of Infix Maven Plugins. + * + * Infix Maven Plugins is free software: you can redistribute + * it and/or modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Infix Maven Plugins is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * Infix Maven Plugins. If not, see <http://www.gnu.org/licenses/>. + * + * $Id$ + *# + +<?php +$REPOSITORIES = array( +#foreach($repo in ${mojoInfo.RepositoryConfigs}) + '${repo.id}' => new MvnRepository('${repo.id}', '${repo.id}-repomap.xml') +#end +); +?> \ No newline at end of file Property changes on: plugins/sfnet-mvnrepo-plugin/trunk/src/main/resources/velocity/repositories.inc.vm ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Date Author Id Revision HeadURL Added: svn:eol-style + native Modified: plugins/sfnet-mvnrepo-plugin/trunk/src/test/java/com/mindtree/techworks/infix/plugins/sfnetmvnrepo/actions/RepoHandlerGenActionTest.java =================================================================== --- plugins/sfnet-mvnrepo-plugin/trunk/src/test/java/com/mindtree/techworks/infix/plugins/sfnetmvnrepo/actions/RepoHandlerGenActionTest.java 2010-12-22 01:48:15 UTC (rev 102) +++ plugins/sfnet-mvnrepo-plugin/trunk/src/test/java/com/mindtree/techworks/infix/plugins/sfnetmvnrepo/actions/RepoHandlerGenActionTest.java 2010-12-22 01:57:20 UTC (rev 103) @@ -85,6 +85,23 @@ assertEquals(2, parsedHtaccess.countLines("RewriteRule.*", true)); assertTrue(parsedHtaccess.hasLine("RewriteRule ^mvnrepo2/(.*) repo-handler.php?repo=mvnrepo2&relpath=$1&compPath=$0", false)); + // Check repositories.inc + File repoInc = new File(tempFolder.getRoot(), "repositories.inc"); + assertTrue(repoInc.exists()); + + ParsedTextFile parsedRepoInc = new ParsedTextFile(repoInc, ParsedTextFile.TRIM_LINES + | ParsedTextFile.SKIP_EMPTY_LINES); + assertTrue(parsedRepoInc.hasLine("<?php", false)); + assertTrue(parsedRepoInc.hasLine("$REPOSITORIES = array(", false)); + assertTrue(parsedRepoInc.hasLine("'mvnrepo' => new MvnRepository('mvnrepo', 'mvnrepo-repomap.xml')", false)); + assertTrue(parsedRepoInc.hasLine("'mvnrepo2' => new MvnRepository('mvnrepo2', 'mvnrepo2-repomap.xml')", false)); + assertTrue(parsedRepoInc.hasLine(");", false)); + assertTrue(parsedRepoInc.hasLine("?>", false)); + + // Check repo-handler.php + File repoHandler = new File(tempFolder.getRoot(), "repo-handler.php"); + assertTrue(repoHandler.exists()); + } catch (ComponentLookupException e) { getLog().warn("Component lookup exception", e); fail("Component lookup exception"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Forrester recently released a report on the Return on Investment (ROI) of Google Apps. They found a 300% ROI, 38%-56% cost savings, and break-even within 7 months. Over 3 million businesses have gone Google with Google Apps: an online email calendar, and document program that's accessible from your browser. Read the Forrester report: http://p.sf.net/sfu/googleapps-sfnew _______________________________________________ mvn-Infix-commits mailing list mvn-Infix-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mvn-infix-commits