1 19 20 package com.sslexplorer.extensions.store; 21 22 import java.io.IOException ; 23 import java.io.InputStream ; 24 import java.net.URL ; 25 import java.net.URLConnection ; 26 import java.util.ArrayList ; 27 import java.util.Arrays ; 28 import java.util.Collection ; 29 import java.util.Collections ; 30 import java.util.HashMap ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.Map ; 34 35 import org.apache.commons.logging.Log; 36 import org.apache.commons.logging.LogFactory; 37 import org.jdom.Attribute; 38 import org.jdom.DataConversionException; 39 import org.jdom.Document; 40 import org.jdom.Element; 41 import org.jdom.JDOMException; 42 import org.jdom.input.SAXBuilder; 43 44 import com.sslexplorer.boot.Util; 45 import com.sslexplorer.boot.VersionInfo; 46 import com.sslexplorer.extensions.ExtensionBundle; 47 48 51 public class ExtensionStoreDescriptor { 52 private static final Log log = LogFactory.getLog(ExtensionStoreDescriptor.class); 53 private URL descriptor; 54 private String store; 55 private Map <String , ExtensionBundle> applicationBundles; 56 private List <ExtensionBundle> applicationBundlesList; 57 private Document document; 58 59 64 public ExtensionStoreDescriptor(URL descriptor) throws IOException , JDOMException { 65 this.descriptor = descriptor; 66 load(); 67 } 68 69 72 public URL getDescriptorLocation() { 73 return descriptor; 74 } 75 76 79 public List <ExtensionBundle> getExtensionBundles() { 80 return applicationBundlesList; 81 } 82 83 86 public String getStore() { 87 return store; 88 } 89 90 94 public Document getDescriptor() throws IOException { 95 return (Document) document.clone(); 96 } 97 98 102 public ExtensionBundle getApplicationBundle(String id) { 103 return (ExtensionBundle) applicationBundles.get(id); 104 } 105 106 110 @SuppressWarnings ("unchecked") 111 public void load() throws IOException , JDOMException { 112 if (log.isInfoEnabled()) 113 log.info("Loading application descriptor " + descriptor.toExternalForm()); 114 loadDocument(); 115 116 applicationBundles = new HashMap <String , ExtensionBundle>(); 117 applicationBundlesList = new ArrayList <ExtensionBundle>(); 118 119 for (Iterator itr = document.getRootElement().getChildren().iterator(); itr.hasNext();) { 120 Element element = (Element) itr.next(); 121 if (element.getName().equalsIgnoreCase("install") || element.getName().equalsIgnoreCase("configure")) { 122 123 ExtensionBundle extensionBundle = buildExtensionBundle(element); 124 if(applicationBundles.containsKey(extensionBundle.getId())) { 125 throw new JDOMException("Duplicate application bundle id."); 126 } 127 128 applicationBundles.put(extensionBundle.getId(), extensionBundle); 129 applicationBundlesList.add(extensionBundle); 130 } else { 131 throw new JDOMException("Unknown element '" + element.getName() + "'."); 132 } 133 } 134 135 Collections.sort(applicationBundlesList); 136 } 137 138 private void loadDocument() throws IOException , JDOMException { 139 140 URLConnection conx = descriptor.openConnection(); 141 conx.setConnectTimeout(ExtensionStore.CONNECT_TIMEOUT); 142 conx.setReadTimeout(ExtensionStore.READ_TIMEOUT); 143 144 InputStream in = null; 145 try { 146 147 in = conx.getInputStream(); 148 149 SAXBuilder sax = new SAXBuilder(); 150 document = sax.build(in); 151 152 if (!document.getRootElement().getName().equalsIgnoreCase("applications")) { 153 throw new JDOMException("Application root element must be <applications>"); 154 } 155 156 store = document.getRootElement().getAttribute("store").getValue(); 157 if (store == null) { 158 throw new JDOMException("<applications> element requires attribute 'store'"); 159 } 160 } 161 finally { 162 Util.closeStream(in); 163 } 164 } 165 166 private static ExtensionBundle buildExtensionBundle(Element element) throws IOException { 167 String id = element.getAttributeValue("id"); 168 if (id == null || id.equals("")) { 169 throw new IOException ("<" + element.getName() + "> requires an 'id' attribute."); 170 } 171 String name = element.getAttributeValue("name"); 172 if (id == null || id.equals("")) { 173 throw new IOException ("<" + element.getName() + "> requires a 'name' attribute."); 174 } 175 176 String instructionsURL = element.getAttributeValue("instructionsURL"); 177 if (element.getName().equalsIgnoreCase("configure") && (instructionsURL == null || instructionsURL.equals(""))) { 178 throw new IOException ("The instructionsURL is mandatory to applications of type <configure>."); 179 } 180 181 String version = element.getAttributeValue("version"); 182 if (version == null || version.equals("")) { 183 throw new IOException ("<" + element.getName() + "> requires a 'version' attribute."); 184 } 185 186 String requiredHostVersionText = element.getAttributeValue("requiredHostVersion"); 187 VersionInfo.Version requiredHostVersion = null; 188 if (requiredHostVersionText != null && !requiredHostVersionText.equals("")) { 189 requiredHostVersion = new VersionInfo.Version(requiredHostVersionText); 190 } 191 192 String license = element.getAttributeValue("license"); 193 String productURL = element.getAttributeValue("productURL"); 194 String description = element.getText(); 195 String dependencies = element.getAttributeValue("depends"); 196 Collection <String > dependencyNames = Util.isNullOrTrimmedBlank(dependencies) ? null : Arrays.asList(dependencies.split(",")); 197 String category = element.getAttributeValue("category"); 198 boolean mandatoryUpdate = Boolean.valueOf(element.getAttributeValue("mandatoryUpdate")); 199 Attribute orderAttr = element.getAttribute("order"); 200 201 String changes = ""; 202 203 if(element.getChild("changes")!=null) { 204 changes = element.getChildText("changes"); 205 } 206 207 if(orderAttr == null) { 208 log.warn("In extension store descriptor for " + id + ", <" + element.getName() + "> requires an 'order' attribute. Assuming '99999'"); 209 } 210 int type = element.getName().equalsIgnoreCase("install") ? ExtensionBundle.TYPE_INSTALLABLE : ExtensionBundle.TYPE_CONFIGUREABLE; 211 try { 212 return new ExtensionBundle(new VersionInfo.Version(version), type, id, name, description, license, productURL, instructionsURL, requiredHostVersion, dependencyNames, category, mandatoryUpdate, orderAttr == null ? 99999 : orderAttr.getIntValue(), changes); 213 } 214 catch(DataConversionException dce) { 215 throw new IOException ("Invalid order attribute. " + dce.getMessage()); 216 } 217 } 218 } | Popular Tags |