/** * Copyright (C) 2005 - 2012 Eric Van Dewoestine * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package org.eclim.plugin.maven.command.dependency; import java.io.FileInputStream; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.xml.parsers.DocumentBuilderFactory; import org.eclim.annotation.Command; import org.eclim.command.CommandLine; import org.eclim.command.Options; import org.eclim.logging.Logger; import org.eclim.plugin.core.command.AbstractCommand; import org.eclim.plugin.core.util.ProjectUtils; import org.eclim.plugin.core.util.XmlUtils; import org.eclim.util.IOUtils; import org.w3c.dom.NodeList; import net.htmlparser.jericho.Element; import net.htmlparser.jericho.Source; /** * Command for searching online maven repository. * * @author Eric Van Dewoestine */ @Command( name = "maven_dependency_search", options = "REQUIRED p project ARG," + "REQUIRED f file ARG," + "REQUIRED t type ARG," + "REQUIRED s search ARG" ) public class SearchCommand extends AbstractCommand { private static final Logger logger = Logger.getLogger(SearchCommand.class); // Note: Experienced connections issues not long after switching to jarvana. // If these continue, consider switching to another alternate or possibly // implement primary secondary support. // http://www.mavensearch.net/search?q=junit private static final String URL = "http://www.jarvana.com/jarvana/search?search_type=project&project="; private static final String GROUP_ID = "Group Id"; private static final String ARTIFACT_ID = "Artifact Id"; private static final String VERSION = "Version"; private static final String IVY = "ivy"; private static final String DEPENDENCIES = "dependencies"; private static final String DEPENDENCY = "dependency"; /** * {@inheritDoc} */ public Object execute(CommandLine commandLine) throws Exception { String search = commandLine.getValue(Options.SEARCH_OPTION); // existing dependencies List<Dependency> existing = null; try{ String project = commandLine.getValue(Options.PROJECT_OPTION); String file = commandLine.getValue(Options.FILE_OPTION); String type = commandLine.getValue(Options.TYPE_OPTION); existing = getExistingDependencies(project, file, type); }catch(Exception e){ logger.warn("Unable to get existing dependencies.", e); existing = new ArrayList<Dependency>(); } return searchRepositories(search, existing); } /** * Searches the repositories supported by maven.ozacc.com. * * @param query The search query. * @return Possibly empty List of results. */ private List<Dependency> searchRepositories( String query, List<Dependency> existing) throws Exception { ArrayList<Dependency> dependencies = new ArrayList<Dependency>(); Source source = new Source(new URL(URL + query)); Element table = source.getElementById("resulttable"); if (table == null){ return dependencies; } // get header column indexes int groupIndex = -1; int artifactIndex = -1; int versionIndex = -1; List<Element> ths = table.getAllElements("th"); for (int ii = 0; ii < ths.size(); ii++){ Element th = ths.get(ii); String text = th.getTextExtractor().toString().trim(); if(groupIndex == -1 && GROUP_ID.equals(text)){ groupIndex = ii; }else if(artifactIndex == -1 && ARTIFACT_ID.equals(text)){ artifactIndex = ii; }else if(versionIndex == -1 && VERSION.equals(text)){ versionIndex = ii; } if(groupIndex >= 0 && artifactIndex >= 0 && versionIndex >= 0){ break; } } Iterator<Element> rows = table.getAllElements("tr").iterator(); // skip header row rows.next(); while (rows.hasNext()){ Element row = rows.next(); List<Element> cells = row.getAllElements("td"); Dependency dependency = new Dependency(); dependency.setGroupId( cells.get(groupIndex).getTextExtractor().toString().trim()); dependency.setArtifactId( cells.get(artifactIndex).getTextExtractor().toString().trim()); dependency.setVersion( cells.get(versionIndex).getTextExtractor().toString().trim()); if (existing.contains(dependency)){ dependency.setExisting(true); } dependencies.add(dependency); } return dependencies; } /** * Get the project file's current dependencies. * * @param project The eclipse project name. * @param filename The project file. * @param type The file type (ivy, maven, mvn). * @return List of dependencies. */ private List<Dependency> getExistingDependencies( String project, String filename, String type) throws Exception { ArrayList<Dependency> list = new ArrayList<Dependency>(); InputStream in = null; try{ String file = ProjectUtils.getFilePath(project, filename); org.w3c.dom.Element root = DocumentBuilderFactory .newInstance() .newDocumentBuilder() .parse(in = new FileInputStream(file)) .getDocumentElement(); NodeList depends = root.getElementsByTagName(DEPENDENCIES); if (depends.getLength() > 0){ NodeList nodes = ((org.w3c.dom.Element)depends.item(0)).getElementsByTagName(DEPENDENCY); for (int ii = 0; ii < nodes.getLength(); ii++){ org.w3c.dom.Element element = (org.w3c.dom.Element)nodes.item(ii); Dependency dependency = new Dependency(); if(IVY.equals(type)){ dependency.setGroupId(element.getAttribute(Dependency.ORG)); dependency.setArtifactId(element.getAttribute(Dependency.NAME)); dependency.setVersion(element.getAttribute(Dependency.REV)); }else{ dependency.setGroupId( XmlUtils.getElementValue(element, Dependency.GROUP_ID)); dependency.setArtifactId( XmlUtils.getElementValue(element, Dependency.ARTIFACT_ID)); dependency.setVersion( XmlUtils.getElementValue(element, Dependency.VERSION)); } list.add(dependency); } } }finally{ IOUtils.closeQuietly(in); } return list; } }