[maven-release-plugin] copy for tag maven-scr-plugin-0.2.0
git-svn-id: https://svn.apache.org/repos/asf/felix/releases/maven-scr-plugin-0.2.0@569282 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index 612e83c..99b2440 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,25 +1,4 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@@ -31,7 +10,7 @@
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
- <version>0.2.0-SNAPSHOT</version>
+ <version>0.2.0</version>
<packaging>maven-plugin</packaging>
<name>Maven Scr Plugin</name>
@@ -40,9 +19,9 @@
</description>
<scm>
- <connection>scm:svn:http://svn.apache.org/repos/asf/felix/trunk/scrplugin</connection>
- <developerConnection>scm:svn:http://svn.apache.org/repos/asf/felix/trunk/scrplugin</developerConnection>
- <url>http://svn.apache.org/repos/asf/felix/scrplugin</url>
+ <connection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/maven-scr-plugin-0.2.0</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/maven-scr-plugin-0.2.0</developerConnection>
+ <url>scm:svn:https://svn.apache.org/repos/asf/felix/releases/maven-scr-plugin-0.2.0</url>
</scm>
<dependencies>
diff --git a/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java b/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
index 61ca81d..c0d9d8d 100644
--- a/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
+++ b/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
@@ -19,21 +19,11 @@
package org.apache.felix.scrplugin.xml;
import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.StringTokenizer;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.sax.SAXResult;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TransformerHandler;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.transform.stream.StreamSource;
import org.apache.felix.scrplugin.om.Component;
import org.apache.felix.scrplugin.om.Components;
@@ -87,15 +77,11 @@
private static final String INTERFACE_QNAME = PREFIX + ':' + INTERFACE;
- private static final SAXTransformerFactory FACTORY = (SAXTransformerFactory) TransformerFactory.newInstance();
-
public static Components read(File file)
throws MojoExecutionException {
try {
- final Transformer transformer = FACTORY.newTransformer();
final XmlHandler xmlHandler = new XmlHandler();
- transformer.transform(new StreamSource(new FileReader(file)),
- new SAXResult(xmlHandler));
+ IOUtils.parse(file, xmlHandler);
return xmlHandler.components;
} catch (TransformerException e) {
throw new MojoExecutionException("Unable to read xml.", e);
@@ -113,16 +99,7 @@
public static void write(Components components, File file)
throws MojoExecutionException {
try {
- FileWriter writer = new FileWriter(file);
- final TransformerHandler transformerHandler = FACTORY.newTransformerHandler();
- final Transformer transformer = transformerHandler.getTransformer();
- transformer.setOutputProperty(OutputKeys.METHOD, "xml");
- transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
- transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
- transformer.setOutputProperty(OutputKeys.INDENT, "yes");
- transformerHandler.setResult(new StreamResult(writer));
-
- generateXML(components, transformerHandler);
+ generateXML(components, IOUtils.getSerializer(file));
} catch (TransformerException e) {
throw new MojoExecutionException("Unable to write xml to " + file, e);
} catch (SAXException e) {
diff --git a/src/main/java/org/apache/felix/scrplugin/xml/IOUtils.java b/src/main/java/org/apache/felix/scrplugin/xml/IOUtils.java
new file mode 100644
index 0000000..40cbe5c
--- /dev/null
+++ b/src/main/java/org/apache/felix/scrplugin/xml/IOUtils.java
@@ -0,0 +1,378 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scrplugin.xml;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * Utility class for xml/sax handling.
+ * It provides support for "older" sax implementations (like the default one shipped with JDK 1.4.2)
+ * which have bugs in the namespace handling.
+ */
+public class IOUtils {
+
+ /** The transformer factory. */
+ private static final SAXTransformerFactory FACTORY = (SAXTransformerFactory) TransformerFactory.newInstance();
+
+ /** The URI for xml namespaces */
+ private static final String XML_NAMESPACE_URI = "http://www.w3.org/XML/1998/namespace";
+
+ /**
+ * Parse a file and send the sax events to the content handler.
+ * @param file
+ * @param handler
+ * @throws IOException
+ * @throws TransformerException
+ */
+ public static final void parse(File file, ContentHandler handler)
+ throws IOException, TransformerException {
+ final Transformer transformer = FACTORY.newTransformer();
+ transformer.transform(new StreamSource(new FileReader(file)),
+ new SAXResult(handler));
+ }
+
+ public static ContentHandler getSerializer(File file)
+ throws IOException, TransformerException {
+ final FileWriter writer = new FileWriter(file);
+
+ final TransformerHandler transformerHandler = FACTORY.newTransformerHandler();
+ final Transformer transformer = transformerHandler.getTransformer();
+
+ final Properties format = new Properties();
+ format.put(OutputKeys.METHOD, "xml");
+ format.put(OutputKeys.OMIT_XML_DECLARATION, "no");
+ format.put(OutputKeys.ENCODING, "UTF-8");
+ format.put(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperties(format);
+
+ transformerHandler.setResult(new StreamResult(writer));
+
+ try {
+ if ( needsNamespacesAsAttributes(format) ) {
+ return new NamespaceAsAttributes(transformerHandler);
+ }
+ } catch (SAXException se) {
+ throw new TransformerException("Unable to detect of namespace support for sax works properly.", se);
+ }
+ return transformerHandler;
+ }
+
+ /**
+ * Checks if the used Trax implementation correctly handles namespaces set using
+ * <code>startPrefixMapping()</code>, but wants them also as 'xmlns:' attributes.
+ * <p>
+ * The check consists in sending SAX events representing a minimal namespaced document
+ * with namespaces defined only with calls to <code>startPrefixMapping</code> (no
+ * xmlns:xxx attributes) and check if they are present in the resulting text.
+ */
+ protected static boolean needsNamespacesAsAttributes(Properties format)
+ throws TransformerException, SAXException {
+ // Serialize a minimal document to check how namespaces are handled.
+ final StringWriter writer = new StringWriter();
+
+ final String uri = "namespaceuri";
+ final String prefix = "nsp";
+ final String check = "xmlns:" + prefix + "='" + uri + "'";
+
+ final TransformerHandler handler = FACTORY.newTransformerHandler();
+
+ handler.getTransformer().setOutputProperties(format);
+ handler.setResult(new StreamResult(writer));
+
+ // Output a single element
+ handler.startDocument();
+ handler.startPrefixMapping(prefix, uri);
+ handler.startElement(uri, "element", "element", new AttributesImpl());
+ handler.endElement(uri, "element", "element");
+ handler.endPrefixMapping(prefix);
+ handler.endDocument();
+
+ final String text = writer.toString();
+
+ // Check if the namespace is there (replace " by ' to be sure of what we search in)
+ boolean needsIt = (text.replace('"', '\'').indexOf(check) == -1);
+
+ return needsIt;
+ }
+
+ /**
+ * A pipe that ensures that all namespace prefixes are also present as
+ * 'xmlns:' attributes. This used to circumvent Xalan's serialization behaviour
+ * which is to ignore namespaces if they're not present as 'xmlns:xxx' attributes.
+ */
+ public static class NamespaceAsAttributes implements ContentHandler {
+
+ /** The wrapped content handler. */
+ private final ContentHandler contentHandler;
+
+ /**
+ * The prefixes of startPrefixMapping() declarations for the coming element.
+ */
+ private List prefixList = new ArrayList();
+
+ /**
+ * The URIs of startPrefixMapping() declarations for the coming element.
+ */
+ private List uriList = new ArrayList();
+
+ /**
+ * Maps of URI<->prefix mappings. Used to work around a bug in the Xalan
+ * serializer.
+ */
+ private Map uriToPrefixMap = new HashMap();
+ private Map prefixToUriMap = new HashMap();
+
+ /**
+ * True if there has been some startPrefixMapping() for the coming element.
+ */
+ private boolean hasMappings = false;
+
+ public NamespaceAsAttributes(ContentHandler ch) {
+ this.contentHandler = ch;
+ }
+
+ public void startDocument() throws SAXException {
+ // Cleanup
+ this.uriToPrefixMap.clear();
+ this.prefixToUriMap.clear();
+ clearMappings();
+ this.contentHandler.startDocument();
+ }
+
+ /**
+ * Track mappings to be able to add <code>xmlns:</code> attributes
+ * in <code>startElement()</code>.
+ */
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ // Store the mappings to reconstitute xmlns:attributes
+ // except prefixes starting with "xml": these are reserved
+ // VG: (uri != null) fixes NPE in startElement
+ if (uri != null && !prefix.startsWith("xml")) {
+ this.hasMappings = true;
+ this.prefixList.add(prefix);
+ this.uriList.add(uri);
+
+ // append the prefix colon now, in order to save concatenations later, but
+ // only for non-empty prefixes.
+ if (prefix.length() > 0) {
+ this.uriToPrefixMap.put(uri, prefix + ":");
+ } else {
+ this.uriToPrefixMap.put(uri, prefix);
+ }
+
+ this.prefixToUriMap.put(prefix, uri);
+ }
+ this.contentHandler.startPrefixMapping(prefix, uri);
+ }
+
+ /**
+ * Ensure all namespace declarations are present as <code>xmlns:</code> attributes
+ * and add those needed before calling superclass. This is a workaround for a Xalan bug
+ * (at least in version 2.0.1) : <code>org.apache.xalan.serialize.SerializerToXML</code>
+ * ignores <code>start/endPrefixMapping()</code>.
+ */
+ public void startElement(String eltUri, String eltLocalName, String eltQName, Attributes attrs)
+ throws SAXException {
+
+ // try to restore the qName. The map already contains the colon
+ if (null != eltUri && eltUri.length() != 0 && this.uriToPrefixMap.containsKey(eltUri)) {
+ eltQName = this.uriToPrefixMap.get(eltUri) + eltLocalName;
+ }
+ if (this.hasMappings) {
+ // Add xmlns* attributes where needed
+
+ // New Attributes if we have to add some.
+ AttributesImpl newAttrs = null;
+
+ int mappingCount = this.prefixList.size();
+ int attrCount = attrs.getLength();
+
+ for (int mapping = 0; mapping < mappingCount; mapping++) {
+
+ // Build infos for this namespace
+ String uri = (String) this.uriList.get(mapping);
+ String prefix = (String) this.prefixList.get(mapping);
+ String qName = prefix.length() == 0 ? "xmlns" : ("xmlns:" + prefix);
+
+ // Search for the corresponding xmlns* attribute
+ boolean found = false;
+ for (int attr = 0; attr < attrCount; attr++) {
+ if (qName.equals(attrs.getQName(attr))) {
+ // Check if mapping and attribute URI match
+ if (!uri.equals(attrs.getValue(attr))) {
+ throw new SAXException("URI in prefix mapping and attribute do not match");
+ }
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ // Need to add this namespace
+ if (newAttrs == null) {
+ // Need to test if attrs is empty or we go into an infinite loop...
+ // Well know SAX bug which I spent 3 hours to remind of :-(
+ if (attrCount == 0) {
+ newAttrs = new AttributesImpl();
+ } else {
+ newAttrs = new AttributesImpl(attrs);
+ }
+ }
+
+ if (prefix.length() == 0) {
+ newAttrs.addAttribute(XML_NAMESPACE_URI, "xmlns", "xmlns", "CDATA", uri);
+ } else {
+ newAttrs.addAttribute(XML_NAMESPACE_URI, prefix, qName, "CDATA", uri);
+ }
+ }
+ } // end for mapping
+
+ // Cleanup for the next element
+ clearMappings();
+
+ // Start element with new attributes, if any
+ this.contentHandler.startElement(eltUri, eltLocalName, eltQName, newAttrs == null ? attrs : newAttrs);
+ } else {
+ // Normal job
+ this.contentHandler.startElement(eltUri, eltLocalName, eltQName, attrs);
+ }
+ }
+
+
+ /**
+ * Receive notification of the end of an element.
+ * Try to restore the element qName.
+ */
+ public void endElement(String eltUri, String eltLocalName, String eltQName) throws SAXException {
+ // try to restore the qName. The map already contains the colon
+ if (null != eltUri && eltUri.length() != 0 && this.uriToPrefixMap.containsKey(eltUri)) {
+ eltQName = this.uriToPrefixMap.get(eltUri) + eltLocalName;
+ }
+ this.contentHandler.endElement(eltUri, eltLocalName, eltQName);
+ }
+
+ /**
+ * End the scope of a prefix-URI mapping:
+ * remove entry from mapping tables.
+ */
+ public void endPrefixMapping(String prefix) throws SAXException {
+ // remove mappings for xalan-bug-workaround.
+ // Unfortunately, we're not passed the uri, but the prefix here,
+ // so we need to maintain maps in both directions.
+ if (this.prefixToUriMap.containsKey(prefix)) {
+ this.uriToPrefixMap.remove(this.prefixToUriMap.get(prefix));
+ this.prefixToUriMap.remove(prefix);
+ }
+
+ if (hasMappings) {
+ // most of the time, start/endPrefixMapping calls have an element event between them,
+ // which will clear the hasMapping flag and so this code will only be executed in the
+ // rather rare occasion when there are start/endPrefixMapping calls with no element
+ // event in between. If we wouldn't remove the items from the prefixList and uriList here,
+ // the namespace would be incorrectly declared on the next element following the
+ // endPrefixMapping call.
+ int pos = prefixList.lastIndexOf(prefix);
+ if (pos != -1) {
+ prefixList.remove(pos);
+ uriList.remove(pos);
+ }
+ }
+
+ this.contentHandler.endPrefixMapping(prefix);
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#endDocument()
+ */
+ public void endDocument() throws SAXException {
+ // Cleanup
+ this.uriToPrefixMap.clear();
+ this.prefixToUriMap.clear();
+ clearMappings();
+ this.contentHandler.endDocument();
+ }
+
+ private void clearMappings() {
+ this.hasMappings = false;
+ this.prefixList.clear();
+ this.uriList.clear();
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#characters(char[], int, int)
+ */
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ contentHandler.characters(ch, start, length);
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
+ */
+ public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
+ contentHandler.ignorableWhitespace(ch, start, length);
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String)
+ */
+ public void processingInstruction(String target, String data) throws SAXException {
+ contentHandler.processingInstruction(target, data);
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
+ */
+ public void setDocumentLocator(Locator locator) {
+ contentHandler.setDocumentLocator(locator);
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)
+ */
+ public void skippedEntity(String name) throws SAXException {
+ contentHandler.skippedEntity(name);
+ }
+ }
+
+}
diff --git a/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java b/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java
index c033b94..bfc3058 100644
--- a/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java
+++ b/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java
@@ -19,18 +19,11 @@
package org.apache.felix.scrplugin.xml;
import java.io.File;
-import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TransformerHandler;
-import javax.xml.transform.stream.StreamResult;
import org.apache.felix.scrplugin.om.metatype.AttributeDefinition;
import org.apache.felix.scrplugin.om.metatype.Designate;
@@ -51,8 +44,6 @@
*/
public class MetaTypeIO {
- private static final SAXTransformerFactory FACTORY = (SAXTransformerFactory) TransformerFactory.newInstance();
-
public static final String NAMESPACE_URI = "http://www.osgi.org/xmlns/metatype/v1.0.0";
public static final String PREFIX = "metatype";
@@ -75,16 +66,7 @@
public static void write(MetaData metaData, File file)
throws MojoExecutionException {
try {
- FileWriter writer = new FileWriter(file);
- final TransformerHandler transformerHandler = FACTORY.newTransformerHandler();
- final Transformer transformer = transformerHandler.getTransformer();
- transformer.setOutputProperty(OutputKeys.METHOD, "xml");
- transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
- transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
- transformer.setOutputProperty(OutputKeys.INDENT, "yes");
- transformerHandler.setResult(new StreamResult(writer));
-
- generateXML(metaData, transformerHandler);
+ generateXML(metaData, IOUtils.getSerializer(file));
} catch (TransformerException e) {
throw new MojoExecutionException("Unable to write xml to " + file, e);
} catch (SAXException e) {