1 7 package fr.jayasoft.ivy.external.m2; 8 9 import java.io.File ; 10 import java.io.IOException ; 11 import java.io.InputStream ; 12 import java.net.URL ; 13 import java.text.ParseException ; 14 import java.util.ArrayList ; 15 import java.util.Date ; 16 import java.util.HashMap ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Map ; 20 import java.util.Stack ; 21 22 import javax.xml.parsers.ParserConfigurationException ; 23 24 import org.xml.sax.Attributes ; 25 import org.xml.sax.SAXException ; 26 27 import fr.jayasoft.ivy.ArtifactId; 28 import fr.jayasoft.ivy.Configuration; 29 import fr.jayasoft.ivy.DefaultArtifact; 30 import fr.jayasoft.ivy.DefaultDependencyArtifactDescriptor; 31 import fr.jayasoft.ivy.DefaultDependencyDescriptor; 32 import fr.jayasoft.ivy.Ivy; 33 import fr.jayasoft.ivy.ModuleDescriptor; 34 import fr.jayasoft.ivy.ModuleId; 35 import fr.jayasoft.ivy.ModuleRevisionId; 36 import fr.jayasoft.ivy.Configuration.Visibility; 37 import fr.jayasoft.ivy.matcher.ExactPatternMatcher; 38 import fr.jayasoft.ivy.matcher.PatternMatcher; 39 import fr.jayasoft.ivy.parser.AbstractModuleDescriptorParser; 40 import fr.jayasoft.ivy.parser.ModuleDescriptorParser; 41 import fr.jayasoft.ivy.repository.Resource; 42 import fr.jayasoft.ivy.util.IvyPatternHelper; 43 import fr.jayasoft.ivy.util.Message; 44 import fr.jayasoft.ivy.util.XMLHelper; 45 import fr.jayasoft.ivy.xml.XmlModuleDescriptorWriter; 46 47 public class PomModuleDescriptorParser extends AbstractModuleDescriptorParser { 48 public static final Configuration[] MAVEN2_CONFIGURATIONS = new Configuration[] { 49 new Configuration("default", Visibility.PUBLIC, "runtime dependencies and master artifact can be used with this conf", new String [] {"runtime", "master"}), 50 new Configuration("master", Visibility.PUBLIC, "contains only the artifact published by this module itself, with no transitive dependencies", new String [0]), 51 new Configuration("compile", Visibility.PUBLIC, "this is the default scope, used if none is specified. Compile dependencies are available in all classpaths.", new String [0]), 52 new Configuration("provided", Visibility.PUBLIC, "this is much like compile, but indicates you expect the JDK or a container to provide it. It is only available on the compilation classpath, and is not transitive.", new String [0]), 53 new Configuration("runtime", Visibility.PUBLIC, "this scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath.", new String [] {"compile"}), 54 new Configuration("test", Visibility.PRIVATE, "this scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases.", new String [0]), 55 new Configuration("system", Visibility.PUBLIC, "this scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository.", new String [0]), 56 }; 57 private static final Configuration OPTIONAL_CONFIGURATION = new Configuration("optional", Visibility.PUBLIC, "contains all optional dependencies", new String [0]); 58 private static final Map MAVEN2_CONF_MAPPING = new HashMap (); 59 60 static { 61 MAVEN2_CONF_MAPPING.put("compile", "compile->@(*),master(*);runtime->@(*)"); 62 MAVEN2_CONF_MAPPING.put("provided", "provided->compile(*),provided(*),runtime(*),master(*)"); 63 MAVEN2_CONF_MAPPING.put("runtime", "runtime->compile(*),runtime(*),master(*)"); 64 MAVEN2_CONF_MAPPING.put("test", "test->compile(*),runtime(*),master(*)"); 65 MAVEN2_CONF_MAPPING.put("system", "system->master(*)"); 66 } 67 68 private static final class Parser extends AbstractParser { 69 private Ivy _ivy; 70 private Stack _contextStack = new Stack (); 71 private String _organisation; 72 private String _module; 73 private String _revision; 74 private String _scope; 75 private boolean _optional = false; 76 private List _exclusions = new ArrayList (); 77 private DefaultDependencyDescriptor _dd; 78 private Map _properties = new HashMap (); 79 80 public Parser(ModuleDescriptorParser parser, Ivy ivy, Resource res) { 81 super(parser); 82 _ivy = ivy; 83 setResource(res); 84 _md.setResolvedPublicationDate(new Date (res.getLastModified())); 85 for (int i = 0; i < MAVEN2_CONFIGURATIONS.length; i++) { 86 _md.addConfiguration(MAVEN2_CONFIGURATIONS[i]); 87 } 88 } 89 90 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { 91 _contextStack.push(qName); 92 if ("optional".equals(qName)) { 93 _optional = true; 94 } else if ("exclusions".equals(qName)) { 95 if (_dd == null) { 96 _dd = new DefaultDependencyDescriptor(_md, ModuleRevisionId.newInstance(_organisation, _module, _revision), true, false, true); 98 _organisation = null; 99 _module = null; 100 _revision = null; 101 } 102 } else if (_md.getModuleRevisionId() == null && ("project/dependencies/dependency".equals(getContext()))) { 103 fillMrid(); 104 } 105 } 106 107 private void fillMrid() throws SAXException { 108 if (_organisation == null) { 109 throw new SAXException ("no groupId found in pom"); 110 } 111 if (_module == null) { 112 throw new SAXException ("no artifactId found in pom"); 113 } 114 if (_revision == null) { 115 _revision = "SNAPSHOT"; 116 } 117 ModuleRevisionId mrid = ModuleRevisionId.newInstance(_organisation, _module, _revision); 118 _properties.put("pom.version", _revision); 119 _md.setModuleRevisionId(mrid); 120 _md.addArtifact("master", new DefaultArtifact(mrid, getDefaultPubDate(),_module, "jar", "jar")); 121 _organisation = null; 122 _module = null; 123 _revision = null; 124 } 125 126 public void endElement(String uri, String localName, String qName) throws SAXException { 127 if (_md.getModuleRevisionId() == null && ("project".equals(getContext()))) { 128 fillMrid(); 129 } else if (((_organisation != null && _module != null && _revision != null) || _dd != null) && "project/dependencies/dependency".equals(getContext())) { 130 if (_dd == null) { 131 _dd = new DefaultDependencyDescriptor(_md, ModuleRevisionId.newInstance(_organisation, _module, _revision), true, false, true); 132 } 133 _scope = _scope == null ? "compile" : _scope; 134 if (_optional && "compile".equals(_scope)) { 135 _scope = "runtime"; 136 } 137 String mapping = (String )MAVEN2_CONF_MAPPING.get(_scope); 138 if (mapping == null) { 139 Message.verbose("unknown scope "+_scope+" in "+getResource()); 140 mapping = (String )MAVEN2_CONF_MAPPING.get("compile"); 141 } 142 if (_optional) { 143 mapping = mapping.replaceAll(_scope+"\\-\\>", "optional->"); 144 if (_md.getConfiguration("optional") == null) { 145 _md.addConfiguration(OPTIONAL_CONFIGURATION); 146 } 147 } 148 parseDepsConfs(mapping, _dd); 149 150 for (Iterator iter = _exclusions.iterator(); iter.hasNext();) { 151 ModuleId mid = (ModuleId)iter.next(); 152 String [] confs = _dd.getModuleConfigurations(); 153 for (int i = 0; i < confs.length; i++) { 154 _dd.addDependencyArtifactExcludes(confs[i], new DefaultDependencyArtifactDescriptor(_dd, new ArtifactId(mid, PatternMatcher.ANY_EXPRESSION, PatternMatcher.ANY_EXPRESSION, PatternMatcher.ANY_EXPRESSION), false, ExactPatternMatcher.getInstance())); 155 } 156 } 157 _md.addDependency(_dd); 158 _dd = null; 159 } else if ((_organisation != null && _module != null) && "project/dependencies/dependency/exclusions/exclusion".equals(getContext())) { 160 _exclusions.add(new ModuleId(_organisation, _module)); 161 _organisation = null; 162 _module = null; 163 } 164 if ("dependency".equals(qName)) { 165 _organisation = null; 166 _module = null; 167 _revision = null; 168 _scope = null; 169 _optional = false; 170 _exclusions.clear(); 171 } 172 _contextStack.pop(); 173 } 174 175 public void characters(char[] ch, int start, int length) throws SAXException { 176 String txt = IvyPatternHelper.substituteVariables(new String (ch, start, length).trim(), _properties); 177 if (txt.trim().length() == 0) { 178 return; 179 } 180 String context = getContext(); 181 if (context.equals("project/parent/groupId") && _organisation == null) { 182 _organisation = txt; 183 return; 184 } 185 if (context.startsWith("project/parent")) { 186 return; 187 } 188 if (_md.getModuleRevisionId() == null || context.startsWith("project/dependencies/dependency")) { 189 if (context.equals("project/groupId")) { 190 _organisation = txt; 191 } else if (_organisation == null && context.endsWith("groupId")) { 192 _organisation = txt; 193 } else if (_module == null && context.endsWith("artifactId")) { 194 _module = txt; 195 } else if (_revision == null && context.endsWith("version")) { 196 _revision = txt; 197 } else if (_scope == null && context.endsWith("scope")) { 198 _scope = txt; 199 } 200 } 201 } 202 203 204 205 private String getContext() { 206 StringBuffer buf = new StringBuffer (); 207 for (Iterator iter = _contextStack.iterator(); iter.hasNext();) { 208 String ctx = (String )iter.next(); 209 buf.append(ctx).append("/"); 210 } 211 if (buf.length() > 0) { 212 buf.setLength(buf.length() - 1); 213 } 214 return buf.toString(); 215 } 216 217 public ModuleDescriptor getDescriptor() { 218 if (_md.getModuleRevisionId() == null) { 219 return null; 220 } 221 return _md; 222 } 223 } 224 225 private static PomModuleDescriptorParser INSTANCE = new PomModuleDescriptorParser(); 226 227 public static PomModuleDescriptorParser getInstance() { 228 return INSTANCE; 229 } 230 231 private PomModuleDescriptorParser() { 232 233 } 234 235 public ModuleDescriptor parseDescriptor(Ivy ivy, URL descriptorURL, Resource res, boolean validate) throws ParseException , IOException { 236 Parser parser = new Parser(this, ivy, res); 237 try { 238 XMLHelper.parse(descriptorURL, null, parser); 239 } catch (SAXException ex) { 240 ParseException pe = new ParseException (ex.getMessage()+" in "+descriptorURL, 0); 241 pe.initCause(ex); 242 throw pe; 243 } catch (ParserConfigurationException ex) { 244 IllegalStateException ise = new IllegalStateException (ex.getMessage()+" in "+descriptorURL); 245 ise.initCause(ex); 246 throw ise; 247 } 248 return parser.getDescriptor(); 249 } 250 251 public void toIvyFile(InputStream is, Resource res, File destFile, ModuleDescriptor md) throws ParseException , IOException { 252 try { 253 XmlModuleDescriptorWriter.write(md, destFile); 254 } finally { 255 if (is != null) { 256 is.close(); 257 } 258 } 259 } 260 261 public boolean accept(Resource res) { 262 return res.getName().endsWith(".pom") || res.getName().endsWith("pom.xml") || res.getName().endsWith("project.xml"); 263 } 264 265 public String toString() { 266 return "pom parser"; 267 } 268 } 269 | Popular Tags |