1 17 package org.apache.geronimo.console.car; 18 19 import java.io.BufferedInputStream ; 20 import java.io.File ; 21 import java.io.FileInputStream ; 22 import java.io.IOException ; 23 import java.io.InputStream ; 24 import java.io.OutputStream ; 25 import java.io.PrintWriter ; 26 import java.util.Iterator ; 27 import java.util.List ; 28 import java.util.Set ; 29 import javax.servlet.ServletException ; 30 import javax.servlet.http.HttpServlet ; 31 import javax.servlet.http.HttpServletRequest ; 32 import javax.servlet.http.HttpServletResponse ; 33 import javax.xml.parsers.DocumentBuilder ; 34 import javax.xml.parsers.DocumentBuilderFactory ; 35 import javax.xml.parsers.ParserConfigurationException ; 36 import javax.xml.transform.OutputKeys ; 37 import javax.xml.transform.Transformer ; 38 import javax.xml.transform.TransformerException ; 39 import javax.xml.transform.TransformerFactory ; 40 import javax.xml.transform.dom.DOMSource ; 41 import javax.xml.transform.stream.StreamResult ; 42 import org.apache.commons.logging.Log; 43 import org.apache.commons.logging.LogFactory; 44 import org.apache.geronimo.gbean.AbstractName; 45 import org.apache.geronimo.gbean.AbstractNameQuery; 46 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 47 import org.apache.geronimo.kernel.Kernel; 48 import org.apache.geronimo.kernel.KernelRegistry; 49 import org.apache.geronimo.kernel.util.XmlUtil; 50 import org.apache.geronimo.kernel.config.ConfigurationInfo; 51 import org.apache.geronimo.kernel.config.ConfigurationManager; 52 import org.apache.geronimo.kernel.config.ConfigurationStore; 53 import org.apache.geronimo.kernel.config.ConfigurationUtil; 54 import org.apache.geronimo.kernel.config.NoSuchStoreException; 55 import org.apache.geronimo.kernel.config.NoSuchConfigException; 56 import org.apache.geronimo.kernel.repository.Artifact; 57 import org.apache.geronimo.kernel.repository.Repository; 58 import org.apache.geronimo.kernel.repository.Version; 59 import org.apache.geronimo.system.plugin.PluginInstaller; 60 import org.apache.geronimo.system.plugin.PluginMetadata; 61 import org.w3c.dom.Document ; 62 import org.w3c.dom.Element ; 63 import org.w3c.dom.Text ; 64 65 70 public class GeronimoAsMavenServlet extends HttpServlet { 71 private final static Log log = LogFactory.getLog(GeronimoAsMavenServlet.class); 72 73 protected void doHead(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException , IOException { 74 handleRequest(httpServletRequest, httpServletResponse, false); 75 } 76 77 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException , IOException { 78 handleRequest(request, response, true); 79 } 80 protected void handleRequest(HttpServletRequest request, HttpServletResponse response, boolean reply) throws ServletException , IOException { 81 String path = request.getPathInfo(); 82 if(path == null) { 83 throw new ServletException ("No configId specified for CAR download"); 84 } 85 Kernel kernel = KernelRegistry.getSingleKernel(); 86 if(path.equals("/geronimo-plugins.xml")) { 87 response.setContentType("text/xml"); 88 if(reply) { 89 try { 90 generateConfigFile(request, kernel, response.getWriter()); 91 } catch (Exception e) { 92 throw new ServletException ("Unable to generate Geronimo configuration list", e); 93 } 94 } 95 } else if(path.endsWith("/maven-metadata.xml")) { 96 response.setContentType("text/xml"); 97 try { 98 String start = path.substring(0, path.lastIndexOf('/')); 99 if(start.charAt(0) == '/') { 100 start = start.substring(1); 101 } 102 String [] parts = start.split("/"); 103 if(parts.length > 2) { 104 StringBuffer buf = new StringBuffer (); 105 for (int i = 0; i < parts.length-1; i++) { 106 String part = parts[i]; 107 if(i > 0) buf.append('.'); 108 buf.append(part); 109 } 110 generateMavenFile(kernel, response.getWriter(), buf.toString(), parts[parts.length-1], reply); 111 } else { 112 generateMavenFile(kernel, response.getWriter(), parts[0], parts[1], reply); 113 } 114 } catch (Exception e) { 115 throw new ServletException ("Unable to generate Geronimo configuration list", e); 116 } 117 } else { 118 if(path.startsWith("/")) { 119 path = path.substring(1); 120 } 121 String configId = parsePath(path, response); 122 if(configId == null) { return; 124 } 125 if(!produceDownloadFile(kernel, Artifact.create(configId), response, reply)) { 126 response.sendError(404, "Cannot locate download file "+path); 127 } 128 } 129 } 130 131 private static String parsePath(String path, HttpServletResponse response) throws IOException { 132 String [] parts = path.split("/"); 133 String groupId, artifactId, version, type; 134 if(parts.length < 4) { 135 response.sendError(404, "Unrecognized path form "+path); 136 return null; 137 } else { groupId = parts[0]; 139 for(int i=4; i<parts.length; i++) { 140 groupId = groupId+"."+parts[i-3]; 141 } 142 artifactId = parts[parts.length-3]; 143 version = parts[parts.length-2]; 144 if(!parts[parts.length-1].startsWith(artifactId+"-"+version)) { 145 response.sendError(404, "Unrecognized path structure "+path); 146 return null; 147 } 148 type = parts[parts.length-1].substring(artifactId.length()+version.length()+2); 149 } 150 return groupId+"/"+artifactId+"/"+version+"/"+type; 151 } 152 153 private boolean produceDownloadFile(Kernel kernel, Artifact configId, HttpServletResponse response, boolean reply) throws IOException { 154 ConfigurationManager mgr = ConfigurationUtil.getConfigurationManager(kernel); 157 if(mgr.isConfiguration(configId)) { 158 ConfigurationStore store = mgr.getStoreForConfiguration(configId); 159 response.setContentType("application/zip"); 160 if(!reply) { 161 return true; 162 } 163 try { 164 store.exportConfiguration(configId, response.getOutputStream()); 165 return true; 166 } catch (NoSuchConfigException e) { 167 log.error("Inconsistent ConfigurationStore data; ConfigManager claims it has configuration "+configId+" but store claims it doesn't",e); 168 throw new IOException ("Unable to write ZIP file; see server log for details"); 169 } 170 } 171 Set repos = kernel.listGBeans(new AbstractNameQuery(Repository.class.getName())); 173 for (Iterator it = repos.iterator(); it.hasNext();) { 174 AbstractName name = (AbstractName) it.next(); 175 Repository repo = (Repository) kernel.getProxyManager().createProxy(name, Repository.class); 176 if(repo.contains(configId)) { 177 File path = repo.getLocation(configId); 178 if(!path.exists()) throw new IllegalStateException ("Can't find file '"+path.getAbsolutePath()+"' though repository said there's an artifact there!"); 179 response.setContentType("application/zip"); 180 if(!reply) { 181 return true; 182 } 183 InputStream in = new BufferedInputStream (new FileInputStream (path)); 184 response.setContentLength((int)path.length()); 185 OutputStream out = response.getOutputStream(); 186 byte[] buf = new byte[1024]; 187 int count; 188 while((count = in.read(buf)) > -1) { 189 out.write(buf, 0, count); 190 } 191 in.close(); 192 return true; 193 } 194 } 195 return false; 197 } 198 199 private void generateConfigFile(HttpServletRequest request, Kernel kernel, PrintWriter out) throws ParserConfigurationException , NoSuchStoreException, TransformerException { 200 ConfigurationManager mgr = ConfigurationUtil.getConfigurationManager(kernel); 201 PluginInstaller installer = getInstaller(kernel); 202 DocumentBuilderFactory factory = XmlUtil.newDocumentBuilderFactory(); 203 factory.setNamespaceAware(true); 204 DocumentBuilder builder = factory.newDocumentBuilder(); 205 Document doc = builder.newDocument(); 206 Element root = doc.createElementNS("http://geronimo.apache.org/xml/ns/plugins-1.1", "geronimo-plugin-list"); 207 root.setAttribute("xmlns", "http://geronimo.apache.org/xml/ns/plugins-1.1"); 208 doc.appendChild(root); 209 List stores = mgr.listStores(); 210 for (int i = 0; i < stores.size(); i++) { 211 AbstractName name = (AbstractName) stores.get(i); 212 List configs = mgr.listConfigurations(name); 213 for (int j = 0; j < configs.size(); j++) { 214 ConfigurationInfo info = (ConfigurationInfo) configs.get(j); 215 PluginMetadata data = installer.getPluginMetadata(info.getConfigID()); 216 Element config = doc.createElement("plugin"); 217 root.appendChild(config); 218 createText(doc, config, "name", data.getName()); 219 createText(doc, config, "module-id", data.getModuleId().toString()); 220 createText(doc, config, "category", "Geronimo Deployments"); 221 createText(doc, config, "description", data.getCategory().equals("Unknown") ? "Automatically generated plugin metadata" : data.getDescription()); 222 if(data.getPluginURL() != null) { 223 createText(doc, config, "url", data.getPluginURL()); 224 } 225 if(data.getAuthor() != null) { 226 createText(doc, config, "author", data.getAuthor()); 227 } 228 for (int k = 0; k < data.getLicenses().length; k++) { 229 PluginMetadata.License license = data.getLicenses()[k]; 230 Element lic = doc.createElement("license"); 231 lic.setAttribute("osi-approved", Boolean.toString(license.isOsiApproved())); 232 createText(doc, lic, license.getName()); 233 config.appendChild(lic); 234 } 235 String [] versions = data.getGeronimoVersions(); 237 for (int k = 0; k < versions.length; k++) { 238 String ver = versions[k]; 239 createText(doc, config, "geronimo-version", ver); 240 } 241 versions = data.getJvmVersions(); 242 for (int k = 0; k < versions.length; k++) { 243 String ver = versions[k]; 244 createText(doc, config, "jvm-version", ver); 245 } 246 for (int k = 0; k < data.getPrerequisites().length; k++) { 247 PluginMetadata.Prerequisite prereq = data.getPrerequisites()[k]; 248 writePrerequisite(doc, config, prereq); 249 } 250 for (int k = 0; k < data.getDependencies().length; k++) { 251 String dep = data.getDependencies()[k]; 252 createText(doc, config, "dependency", dep); 253 } 254 for (int k = 0; k < data.getObsoletes().length; k++) { 255 String obs = data.getObsoletes()[k]; 256 createText(doc, config, "obsoletes", obs); 257 } 258 } 260 } 261 String repo = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+request.getServletPath(); 262 if(!repo.endsWith("/")) repo += "/"; 263 createText(doc, root, "default-repository", repo); 264 TransformerFactory xfactory = XmlUtil.newTransformerFactory(); 265 Transformer xform = xfactory.newTransformer(); 266 xform.setOutputProperty(OutputKeys.INDENT, "yes"); 267 xform.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); 268 xform.transform(new DOMSource (doc), new StreamResult (out)); 269 } 270 271 private PluginInstaller getInstaller(Kernel kernel) { 272 Set names = kernel.listGBeans(new AbstractNameQuery(PluginInstaller.class.getName())); 273 if(names.size() == 0) { 274 return null; 275 } 276 return (PluginInstaller) kernel.getProxyManager().createProxy((AbstractName) names.iterator().next(), PluginInstaller.class); 277 } 278 279 private void generateMavenFile(Kernel kernel, PrintWriter writer, String groupId, String artifactId, boolean reply) throws ParserConfigurationException , TransformerException { 280 ConfigurationManager mgr = ConfigurationUtil.getConfigurationManager(kernel); 281 Artifact[] artifacts = mgr.getArtifactResolver().queryArtifacts(new Artifact(groupId, artifactId, (Version)null, null)); 282 if(!reply) { 283 return; 284 } 285 286 DocumentBuilderFactory factory = XmlUtil.newDocumentBuilderFactory(); 287 DocumentBuilder builder = factory.newDocumentBuilder(); 288 Document doc = builder.newDocument(); 289 Element root = doc.createElement("metadata"); 290 doc.appendChild(root); 291 createText(doc, root, "groupId", groupId); 292 createText(doc, root, "artifactId", artifactId); 293 if(artifacts.length > 0) { 294 createText(doc, root, "version", artifacts[0].getVersion().toString()); 295 } 296 Element versioning = doc.createElement("versioning"); 297 root.appendChild(versioning); 298 Element versions = doc.createElement("versions"); 299 versioning.appendChild(versions); 300 for (int i = 0; i < artifacts.length; i++) { 301 Artifact artifact = artifacts[i]; 302 createText(doc, versions, "version", artifact.getVersion().toString()); 303 } 304 TransformerFactory xfactory = XmlUtil.newTransformerFactory(); 305 Transformer xform = xfactory.newTransformer(); 306 xform.setOutputProperty(OutputKeys.INDENT, "yes"); 307 xform.transform(new DOMSource (doc), new StreamResult (writer)); 308 } 309 310 private void writePrerequisite(Document doc, Element config, PluginMetadata.Prerequisite req) { 311 Element prereq = doc.createElement("prerequisite"); 312 config.appendChild(prereq); 313 createText(doc, prereq, "id", req.getModuleId().toString()); 314 createText(doc, prereq, "resource-type", req.getResourceType()); 315 createText(doc, prereq, "description", req.getDescription()); 316 } 317 318 private void createText(Document doc, Element parent, String name, String text) { 319 Element child = doc.createElement(name); 320 parent.appendChild(child); 321 Text node = doc.createTextNode(text); 322 child.appendChild(node); 323 } 324 325 private void createText(Document doc, Element parent, String text) { 326 Text node = doc.createTextNode(text); 327 parent.appendChild(node); 328 } 329 } 330 | Popular Tags |