1 19 20 package org.netbeans.modules.convertor; 21 22 import java.io.IOException ; 23 import java.io.InputStream ; 24 import java.net.URL ; 25 import java.util.Enumeration ; 26 import java.util.HashSet ; 27 import java.util.Iterator ; 28 import java.util.Map ; 29 import java.util.Set ; 30 import java.util.jar.Attributes ; 31 import java.util.jar.Manifest ; 32 import org.netbeans.api.convertor.ConvertorDescriptor; 33 import org.netbeans.api.convertor.ConvertorException; 34 import org.netbeans.api.convertor.Convertors; 35 import org.netbeans.spi.convertor.Convertor; 36 import org.openide.ErrorManager; 37 import org.openide.modules.ModuleInfo; 38 import org.openide.util.Lookup; 39 import org.openide.util.LookupEvent; 40 import org.openide.util.LookupListener; 41 import org.w3c.dom.Document ; 42 import org.w3c.dom.Element ; 43 44 48 public class ConvertorsPool implements LookupListener { 49 50 public static final String NETBEANS_CONVERTOR = "NetBeans-Convertor"; public static final String NETBEANS_SIMPLY_CONVERTIBLE = "NetBeans-Simply-Convertible"; public static final String PROPERTIES_CONVERTOR = "PropertiesConvertor"; 54 private static final ConvertorsPool DEFAULT = new ConvertorsPool(); 55 56 private Set convertorDescriptors = new HashSet (); 57 58 private boolean initialized = false; 59 60 private Lookup.Result modules; 61 62 private ConvertorsPool() { 63 modules = Lookup.getDefault().lookup(new Lookup.Template(ModuleInfo.class)); 64 modules.allItems(); 65 modules.addLookupListener(this); 66 } 67 68 public static ConvertorsPool getDefault() { 69 return DEFAULT; 70 } 71 72 public ConvertorDescriptor getReadConvertor(String namespace, String element) { 73 assert namespace != null && element != null; 74 initConvertors(); 75 Iterator it = convertorDescriptors.iterator(); 76 while (it.hasNext()) { 77 ConvertorDescriptor cd = (ConvertorDescriptor)it.next(); 78 if (namespace.equals(cd.getNamespace()) && 79 element.equals(cd.getElementName())) { 80 return cd; 81 } 82 } 83 return null; 84 } 85 86 public ConvertorDescriptor getWriteConvertor(Object o) { 87 initConvertors(); 88 Convertor convertor = null; 89 Class clazz = o.getClass(); 90 Iterator it = convertorDescriptors.iterator(); 91 while (it.hasNext()) { 92 ConvertorDescriptor cd = (ConvertorDescriptor)it.next(); 93 if (cd.getClassName() == null || (!cd.getClassName().equals(o.getClass().getName()))) { 94 continue; 95 } 96 Class cls; 97 try { 98 cls = InstanceUtils.findClass(cd.getClassName()); 99 100 ClassLoader clsLoader = cls.getClassLoader(); 103 if (clsLoader != null && !(clsLoader.loadClass(o.getClass().getName()) == o.getClass())) { 104 ErrorManager.getDefault().log(ErrorManager.WARNING, "Object "+o+" cannot be stored by convertor "+cd+", because of classloader mismatch. Skipping convertor."); continue; 106 } 107 } catch (Exception e) { 108 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 109 continue; 110 } 111 112 if (clazz.equals(cls)) { 113 return cd; 114 } 115 } 116 return null; 117 } 118 119 public Set getDescriptors() { 120 initConvertors(); 121 return new HashSet (convertorDescriptors); 122 } 123 124 private synchronized void initConvertors() { 125 if (initialized) { 126 return; 127 } 128 loadConvertors(); 129 initialized = true; 130 } 131 132 public synchronized void resultChanged(LookupEvent ev) { 133 loadConvertors(); 134 } 135 136 private void loadConvertors() { 137 Set old = convertorDescriptors; 138 139 ClassLoader currentClassLoader = (ClassLoader )Lookup.getDefault().lookup(ClassLoader .class); 140 Set convs = new HashSet (); 141 Enumeration en = null; 142 try { 143 en = currentClassLoader.getResources("META-INF/MANIFEST.MF"); } catch (IOException ex) { 145 ex.printStackTrace(); 146 ErrorManager.getDefault().notify(ErrorManager.ERROR, ex); 147 return; 148 } 149 while (en.hasMoreElements ()) { 150 URL u = (URL )en.nextElement(); 151 Manifest mf; 152 153 try { 154 InputStream is = u.openStream(); 155 try { 156 mf = new Manifest (is); 157 loadConvertors(mf, convs); 158 } finally { 159 is.close(); 160 } 161 } catch (IOException ex) { 162 ErrorManager.getDefault().log(ErrorManager.ERROR, "Cannot read file "+u+". The file will be ignored."); } 164 165 } 166 convertorDescriptors = convs; 167 168 Accessor.DEFAULT.firePropertyChange(Convertors.CONVERTOR_DESCRIPTORS, old, new HashSet (convertorDescriptors)); 169 } 170 171 private void loadConvertors(Manifest m, Set convs) { 172 Iterator it = m.getEntries().entrySet().iterator(); while (it.hasNext()) { 174 Map.Entry entry = (Map.Entry )it.next(); 175 String name = (String )entry.getKey(); 176 Attributes attrs = (Attributes )entry.getValue(); 177 if (attrs.getValue(NETBEANS_CONVERTOR) != null) { 178 String convertor = getClassName(name); 179 String conv; 180 int index = 0; 181 while (null != (conv = attrs.getValue(appendNumber(NETBEANS_CONVERTOR, index)))) { 182 int endOfNamespace = conv.indexOf('}'); 184 if (endOfNamespace == -1) { 185 ErrorManager.getDefault().log(ErrorManager.WARNING, "Attribute "+ appendNumber(NETBEANS_CONVERTOR, index)+ 187 " of convertor "+convertor+ " does not contain namespace: "+conv); break; 190 } 191 int startOfClass = conv.indexOf(','); 192 String namespace = conv.substring(1, endOfNamespace); 193 String rootElement; 194 if (startOfClass == -1) { 195 rootElement = conv.substring(endOfNamespace+1); 196 } else { 197 rootElement = conv.substring(endOfNamespace+1, startOfClass); 198 } 199 rootElement = rootElement.trim(); 200 if (rootElement.length() == 0) { 201 ErrorManager.getDefault().log(ErrorManager.WARNING, "Attribute "+ appendNumber(NETBEANS_CONVERTOR, index)+ 203 " of convertor "+convertor+ " does not contain element: "+conv); break; 206 } 207 String writes = null; 208 if (startOfClass != -1) { 209 writes = conv.substring(startOfClass+1).trim(); 210 } 211 212 convs.add(Accessor.DEFAULT.createConvertorDescriptor( 213 new ProxyConvertor(convertor, namespace, rootElement, writes), namespace, rootElement, writes)); 214 index++; 215 } 216 } 217 if (attrs.getValue(NETBEANS_SIMPLY_CONVERTIBLE) != null) { 218 String conv = attrs.getValue(NETBEANS_SIMPLY_CONVERTIBLE); 219 String convertor = PROPERTIES_CONVERTOR; 220 int endOfNamespace = conv.indexOf('}'); 222 if (endOfNamespace == -1) { 223 ErrorManager.getDefault().log(ErrorManager.WARNING, "Attribute "+ NETBEANS_SIMPLY_CONVERTIBLE+ 225 " for class "+name+ " does not contain namespace: "+conv); continue; 228 } 229 String namespace = conv.substring(1, endOfNamespace); 230 String rootElement = conv.substring(endOfNamespace+1); 231 rootElement = rootElement.trim(); 232 if (rootElement.length() == 0) { 233 ErrorManager.getDefault().log(ErrorManager.WARNING, "Attribute "+ NETBEANS_SIMPLY_CONVERTIBLE+ 235 " for class "+name+ " does not contain element: "+conv); continue; 238 } 239 String writes = getClassName(name); 240 convs.add(Accessor.DEFAULT.createConvertorDescriptor( 241 new ProxyConvertor(convertor, namespace, rootElement, writes), namespace, rootElement, writes)); 242 } 243 } 244 } 245 246 private String getClassName(String className) { 247 className = className.replace('/', '.'); 248 className = className.substring(0, className.indexOf(".class")); return className; 251 } 252 253 private String appendNumber(String name, int number) { 254 if (number == 0) { 255 return name; 256 } else { 257 return name + "-" + Integer.toString(number+1); 258 } 259 } 260 261 private static class ProxyConvertor implements Convertor { 262 263 private String convertor; 264 private String namespace; 265 private String rootElement; 266 private String writes; 267 268 private Convertor delegate; 269 270 public ProxyConvertor(String convertor, String namespace, String rootElement, String writes) { 271 this.convertor = convertor; 272 this.namespace = namespace; 273 this.rootElement = rootElement; 274 this.writes = writes; 275 } 276 277 public Object read(Element e) { 278 loadRealConvertor(); 279 if (delegate == null) { 280 throw new ConvertorException("Cannot read element. The convertor class "+convertor+" cannot be instantiated."); } 282 return delegate.read(e); 283 } 284 285 public Element write(Document doc, Object inst) { 286 loadRealConvertor(); 287 if (delegate == null) { 288 throw new ConvertorException("Cannot persist object. The convertor class "+convertor+" cannot be instantiated."); } 290 return delegate.write(doc, inst); 291 } 292 293 private synchronized void loadRealConvertor() { 294 if (delegate == null) { 295 if (convertor.equals(PROPERTIES_CONVERTOR)) { 296 delegate = new PropertiesConvertor(namespace, rootElement, writes); 297 } else { 298 try { 299 Class c = InstanceUtils.findClass(convertor); 300 delegate = (Convertor)c.newInstance(); 301 } catch (Exception e) { 302 ErrorManager.getDefault().log(ErrorManager.WARNING, e.toString()); 303 } 304 } 305 } 306 } 307 308 public String toString() { 309 return "ProxyConvertor[convertor="+convertor+", namespace="+namespace+", rootElement="+ rootElement+", writes="+writes+", delegate="+delegate+"] " + super.toString(); } 312 313 } 314 315 } 316 | Popular Tags |