FELIX-1708 Improve Error Reporting. The SCRDescriptorException now requires plain
messages and a source location and line number information. This can be used to
provide enhanced log messages with the Log interface (added signature for error
and warn messages with location and line information) and the IssueLog class. This
helps with non-Maven integrations supporting specialized logging if source and
line number information is present.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@822249 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/JavaClassDescriptorManager.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/JavaClassDescriptorManager.java
index 87dedbe..f96e5cb 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/JavaClassDescriptorManager.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/JavaClassDescriptorManager.java
@@ -238,7 +238,7 @@
                     }
                     catch ( ClassNotFoundException e )
                     {
-                        throw new SCRDescriptorException( "Unable to load class " + className );
+                        throw new SCRDescriptorException( "Unable to load class", className, 0 );
                     }
                 }
                 else
@@ -256,7 +256,7 @@
                 }
                 catch ( ClassNotFoundException e )
                 {
-                    throw new SCRDescriptorException( "Unable to load class " + className );
+                    throw new SCRDescriptorException( "Unable to load class", className, 0);
                 }
             }
             this.javaClassDescriptions.put( className, result );
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/Log.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/Log.java
index 3398928..46d44ff 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/Log.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/Log.java
@@ -116,6 +116,18 @@
      * The error's stacktrace will be output when this error level is enabled.
      *
      * @param content
+     * @param location The location at which the error occurred
+     * @param lineNumber The line number at which the error occurred
+     */
+    void warn( String content, String location, int lineNumber );
+
+
+    /**
+     * Send a message (and accompanying exception) to the user in the <b>warn</b> error level.
+     * <br/>
+     * The error's stacktrace will be output when this error level is enabled.
+     *
+     * @param content
      * @param error
      */
     void warn( String content, Throwable error );
@@ -151,6 +163,18 @@
      * The error's stacktrace will be output when this error level is enabled.
      *
      * @param content
+     * @param location The location at which the error occurred
+     * @param lineNumber The line number at which the error occurred
+     */
+    void error( String content, String location, int lineNumber );
+
+
+    /**
+     * Send a message (and accompanying exception) to the user in the <b>error</b> error level.
+     * <br/>
+     * The error's stacktrace will be output when this error level is enabled.
+     *
+     * @param content
      * @param error
      */
     void error( String content, Throwable error );
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorException.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorException.java
index 13fa575..0721681 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorException.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorException.java
@@ -18,16 +18,57 @@
  */
 package org.apache.felix.scrplugin;
 
+
+import org.apache.felix.scrplugin.tags.JavaTag;
+
+
 public class SCRDescriptorException extends Exception
 {
 
     private static final long serialVersionUID = 1L;
 
-    public SCRDescriptorException(String message) {
-        super(message);
+    private final String m_sourceLocation;
+
+    private final int m_lineNumber;
+
+
+    public SCRDescriptorException( final String message, final JavaTag tag )
+    {
+        this( message, tag.getSourceLocation(), tag.getLineNumber() );
     }
 
-    public SCRDescriptorException(String message, Throwable cause) {
-        super(message, cause);
+
+    public SCRDescriptorException( final String message, final String sourceLocation, final int lineNumber )
+    {
+        super( message );
+        this.m_sourceLocation = sourceLocation;
+        this.m_lineNumber = lineNumber;
+    }
+
+
+    public SCRDescriptorException( final String message, final JavaTag tag, final Throwable cause )
+    {
+        this( message, tag.getSourceLocation(), tag.getLineNumber(), cause );
+    }
+
+
+    public SCRDescriptorException( final String message, final String sourceLocation, final int lineNumber,
+        final Throwable cause )
+    {
+        super( message, cause );
+        this.m_sourceLocation = sourceLocation;
+        this.m_lineNumber = lineNumber;
+    }
+
+
+    public String getSourceLocation()
+    {
+        return m_sourceLocation;
+    }
+
+
+    public int getLineNumber()
+    {
+        return m_lineNumber;
     }
 }
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
index 44aed05..7d56dbf 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
@@ -234,7 +234,7 @@
         this.logger.debug( "..processing annotations: " + this.descriptorManager.isProcessAnnotations() );
 
         // check speck version configuration
-        int specVersion = toSpecVersionCode( this.specVersion );
+        int specVersion = toSpecVersionCode( this.specVersion, null );
         if ( this.specVersion == null )
         {
             this.logger.debug( "..auto detecting spec version" );
@@ -265,28 +265,36 @@
                 if ( javaSources[i].getTagsByName( Constants.COMPONENT, false ).length > 1 )
                 {
                     iLog.addError( "Class " + javaSources[i].getName() + " has more than one " + Constants.COMPONENT
-                        + " tag." + " Merge the tags to a single tag." );
+                        + " tag." + " Merge the tags to a single tag.", tag.getSourceLocation(), tag.getLineNumber() );
                 }
                 else
                 {
-                    final Component comp = this.createComponent( javaSources[i], tag, metaData, iLog );
-                    if ( comp.getSpecVersion() > specVersion )
+                    try
                     {
-                        // if a spec version has been configured and a component requires a higher
-                        // version, this is considered an error!
-                        if ( this.specVersion != null )
+                        final Component comp = this.createComponent( javaSources[i], tag, metaData, iLog );
+                        if ( comp.getSpecVersion() > specVersion )
                         {
-                            String v = Constants.COMPONENT_DS_SPEC_VERSION_10;
-                            if ( comp.getSpecVersion() == Constants.VERSION_1_1 )
+                            // if a spec version has been configured and a component requires a higher
+                            // version, this is considered an error!
+                            if ( this.specVersion != null )
                             {
-                                v = Constants.COMPONENT_DS_SPEC_VERSION_11;
+                                String v = Constants.COMPONENT_DS_SPEC_VERSION_10;
+                                if ( comp.getSpecVersion() == Constants.VERSION_1_1 )
+                                {
+                                    v = Constants.COMPONENT_DS_SPEC_VERSION_11;
+                                }
+                                iLog.addError( "Component " + comp + " requires spec version " + v
+                                    + " but plugin is configured to use version " + this.specVersion, tag
+                                    .getSourceLocation(), tag.getLineNumber() );
                             }
-                            iLog.addError( "Component " + comp + " requires spec version " + v
-                                + " but plugin is configured to use version " + this.specVersion );
+                            specVersion = comp.getSpecVersion();
                         }
-                        specVersion = comp.getSpecVersion();
+                        scannedComponents.add( comp );
                     }
-                    scannedComponents.add( comp );
+                    catch ( SCRDescriptorException sde )
+                    {
+                        iLog.addError( sde.getMessage(), sde.getSourceLocation(), sde.getLineNumber() );
+                    }
                 }
             }
         }
@@ -366,7 +374,7 @@
         }
 
         // log issues
-        logMessages( iLog );
+        iLog.logMessages( logger );
 
         // after checking all classes, throw if there were any failures
         if ( iLog.hasErrors() )
@@ -591,7 +599,7 @@
         final String dsSpecVersion = tag.getNamedParameter( Constants.COMPONENT_DS_SPEC_VERSION );
         if ( dsSpecVersion != null )
         {
-            component.setSpecVersion( toSpecVersionCode( dsSpecVersion ) );
+            component.setSpecVersion( toSpecVersionCode( dsSpecVersion, tag ) );
         }
 
         // FELIX-593: immediate attribute does not default to true all the
@@ -664,7 +672,7 @@
                 else
                 {
                     iLog.addWarning( "Component factory " + component.getName()
-                        + " should not set metatype factory pid." );
+                        + " should not set metatype factory pid.", tag.getSourceLocation(), tag.getLineNumber() );
                 }
             }
             // designate.object
@@ -716,7 +724,7 @@
                     if ( serviceClass == null )
                     {
                         throw new SCRDescriptorException( "Interface '" + name + "' in class " + description.getName()
-                            + " does not point to a valid class/interface." );
+                            + " does not point to a valid class/interface.", services[i] );
                     }
                     interfaceName = serviceClass.getName();
                 }
@@ -778,7 +786,7 @@
                 if ( isInspectedClass )
                 {
                     throw new SCRDescriptorException( "Duplicate definition for reference " + refName + " in class "
-                        + reference.getJavaClassDescription().getName() );
+                        + reference.getJavaClassDescription().getName(), reference );
                 }
             }
             else
@@ -794,7 +802,7 @@
                     else
                     {
                         throw new SCRDescriptorException( "Interface missing for reference " + refName + " in class "
-                            + reference.getJavaClassDescription().getName() );
+                            + reference.getJavaClassDescription().getName(), reference );
                     }
                 }
                 else if ( isInspectedClass )
@@ -807,7 +815,7 @@
                     {
                         throw new SCRDescriptorException( "Interface '" + type + "' in class "
                             + reference.getJavaClassDescription().getName()
-                            + " does not point to a valid class/interface." );
+                            + " does not point to a valid class/interface.", reference );
                     }
                     type = serviceClass.getName();
                 }
@@ -833,12 +841,12 @@
             if ( values == null || values.length == 0 )
             {
                 throw new SCRDescriptorException( "Referenced field for " + name
-                    + " has no values for a reference name." );
+                    + " has no values for a reference name.", reference );
             }
             if ( values.length > 1 )
             {
                 throw new SCRDescriptorException( "Referenced field " + name
-                    + " has more than one value for a reference name." );
+                    + " has more than one value for a reference name.", reference );
             }
             name = values[0];
         }
@@ -863,7 +871,7 @@
         if ( field == null )
         {
             throw new SCRDescriptorException( "Reference references unknown field " + ref + " in class "
-                + tag.getJavaClassDescription().getName() );
+                + tag.getJavaClassDescription().getName(), tag );
         }
         return field;
     }
@@ -923,31 +931,6 @@
     }
 
 
-    private void logMessages( final IssueLog iLog )
-    {
-        final Log log = logger;
-
-        // now log warnings and errors (warnings first)
-        // in strict mode everything is an error!
-        final Iterator<String> warnings = iLog.getWarnings();
-        while ( warnings.hasNext() )
-        {
-            if ( strictMode )
-            {
-                log.error( warnings.next() );
-            }
-            else
-            {
-                log.warn( warnings.next() );
-            }
-        }
-
-        final Iterator<String> errors = iLog.getErrors();
-        while ( errors.hasNext() )
-        {
-            log.error( errors.next() );
-        }
-    }
 
     /**
      * Converts the specification version string to a specification version
@@ -966,7 +949,7 @@
      * @throws SCRDescriptorException if the <code>specVersion</code> parameter
      *      is not a supported value.
      */
-    private int toSpecVersionCode( String specVersion ) throws SCRDescriptorException
+    private int toSpecVersionCode( String specVersion, JavaTag tag ) throws SCRDescriptorException
     {
         if ( specVersion == null || specVersion.equals( Constants.COMPONENT_DS_SPEC_VERSION_10 ) )
         {
@@ -978,6 +961,6 @@
         }
 
         // unknown specVersion string
-        throw new SCRDescriptorException( "Unknown configuration for spec version: " + specVersion );
+        throw new SCRDescriptorException( "Unsupported or unknown DS spec version: " + specVersion, tag );
     }
 }
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/helper/IssueLog.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/helper/IssueLog.java
index bc5e40a..f861beb 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/helper/IssueLog.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/helper/IssueLog.java
@@ -22,6 +22,8 @@
 import java.util.Iterator;
 import java.util.List;
 
+import org.apache.felix.scrplugin.Log;
+
 /**
  * Utility class for handling errors and warnings
  */
@@ -29,9 +31,9 @@
 
     private final boolean strictMode;
 
-    private final List<String> errors = new ArrayList<String>();
+    private final List<Entry> errors = new ArrayList<Entry>();
 
-    private final List<String> warnings = new ArrayList<String>();
+    private final List<Entry> warnings = new ArrayList<Entry>();
 
     public IssueLog(final boolean strictMode) {
         this.strictMode = strictMode;
@@ -45,19 +47,60 @@
         return errors.size() > 0 || (this.strictMode && warnings.size() > 0 );
     }
 
-    public void addError(final String e) {
-        errors.add(e);
+    public void addError(final String message, final String location, final int lineNumber) {
+        errors.add( new Entry( message, location, lineNumber ) );
     }
 
-    public void addWarning(final String e) {
-        warnings.add(e);
+    public void addWarning(final String message, final String location, final int lineNumber) {
+        warnings.add( new Entry( message, location, lineNumber ) );
+    }
+
+    public void logMessages( final Log log )
+    {
+        // now log warnings and errors (warnings first)
+        // in strict mode everything is an error!
+        final Iterator<Entry> warnings = this.warnings.iterator();
+        while ( warnings.hasNext() )
+        {
+            final Entry entry = warnings.next();
+            if ( strictMode )
+            {
+                log.error( entry.message, entry.location, entry.lineNumber);
+            }
+            else
+            {
+                log.warn( entry.message, entry.location, entry.lineNumber);
+            }
+        }
+
+        final Iterator<Entry> errors = this.errors.iterator();
+        while ( errors.hasNext() )
+        {
+            final Entry entry = errors.next();
+            log.error( entry.message, entry.location, entry.lineNumber);
+        }
     }
 
     public Iterator<String> getWarnings() {
-        return warnings.iterator();
+        return null; // warnings.iterator();
     }
 
     public Iterator<String> getErrors() {
-        return errors.iterator();
+        return null; // errors.iterator();
+    }
+
+    private static class Entry
+    {
+        final String message;
+        final String location;
+        final int lineNumber;
+
+
+        Entry( final String message, final String location, final int lineNumber )
+        {
+            this.message = message;
+            this.location = location;
+            this.lineNumber = lineNumber;
+        }
     }
 }
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/helper/PropertyHandler.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/helper/PropertyHandler.java
index 6728389..9eb2eec 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/helper/PropertyHandler.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/helper/PropertyHandler.java
@@ -216,10 +216,10 @@
                 final JavaField refField = this.getReferencedField(tag, name);
                 final String[] values = refField.getInitializationExpression();
                 if ( values == null || values.length == 0 ) {
-                    throw new SCRDescriptorException("Referenced field for " + name + " has no values for a property name.");
+                    throw new SCRDescriptorException("Referenced field for " + name + " has no values for a property name.", tag);
                 }
                 if ( values.length > 1 ) {
-                    throw new SCRDescriptorException("Referenced field " + name + " has more than one value for a property name.");
+                    throw new SCRDescriptorException("Referenced field " + name + " has more than one value for a property name.", tag);
                 }
                 name = values[0];
             }
@@ -264,7 +264,7 @@
             field = tag.getJavaClassDescription().getExternalFieldByName(ref);
         }
         if ( field == null ) {
-            throw new SCRDescriptorException("Property references unknown field " + ref + " in class " + tag.getJavaClassDescription().getName());
+            throw new SCRDescriptorException("Property references unknown field " + ref + " in class " + tag.getJavaClassDescription().getName(), tag);
         }
         return field;
     }
@@ -318,13 +318,13 @@
                 // if the current class is the class we are currently inspecting, we
                 // have found a duplicate definition
                 if ( isInspectedClass ) {
-                    throw new SCRDescriptorException("Duplicate definition for property " + propName + " in class " + property.getJavaClassDescription().getName());
+                    throw new SCRDescriptorException("Duplicate definition for property " + propName + " in class " + property.getJavaClassDescription().getName(), property);
                 }
             } else {
                 properties.put(propName, new PropertyDescription(property, field));
             }
         } else {
-            throw new SCRDescriptorException("Property has no name " + property.getSourceLocation());
+            throw new SCRDescriptorException("Property has no name", property);
         }
     }
 
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenJavaClassDescriptorManager.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenJavaClassDescriptorManager.java
index 0978e80..906fa97 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenJavaClassDescriptorManager.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenJavaClassDescriptorManager.java
@@ -129,11 +129,11 @@
                             }
                             catch ( FileNotFoundException e )
                             {
-                                throw new SCRDescriptorException( "Unable to scan directory.", e );
+                                throw new SCRDescriptorException( "Unable to scan directory.", files[m], 0, e );
                             }
                             catch ( IOException e )
                             {
-                                throw new SCRDescriptorException( "Unable to scan directory.", e );
+                                throw new SCRDescriptorException( "Unable to scan directory.", files[m], 0, e );
                             }
                         }
                     }
@@ -224,8 +224,8 @@
                             }
                             catch ( IOException ioe )
                             {
-                                throw new SCRDescriptorException( "Unable to get manifest from artifact " + artifact,
-                                    ioe );
+                                throw new SCRDescriptorException( "Unable to get manifest from artifact", artifact
+                                    .toString(), 0, ioe );
                             }
                             this.log.debug( "Trying to get scrinfo from artifact " + artifact );
                             // now read the scr private file - components stored there overwrite components already
@@ -246,8 +246,8 @@
                             }
                             catch ( IOException ioe )
                             {
-                                throw new SCRDescriptorException( "Unable to get scrinfo from artifact " + artifact,
-                                    ioe );
+                                throw new SCRDescriptorException( "Unable to get scrinfo from artifact", artifact
+                                    .toString(), 0, ioe );
                             }
                             finally
                             {
@@ -319,7 +319,8 @@
         try {
             xml = this.getFile(artifact, entry);
             if ( xml == null ) {
-                throw new SCRDescriptorException("Artifact " + artifact + " does not contain declared service component descriptor " + entry);
+                throw new SCRDescriptorException( "Entry " + entry + " not contained in artifact", artifact.toString(),
+                    0 );
             }
             return this.parseServiceComponentDescriptor(xml);
         } catch (IOException mee) {
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenLog.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenLog.java
index e5312c1..d5d9697 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenLog.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/mojo/MavenLog.java
@@ -62,6 +62,16 @@
     }
 
 
+    public void error( String content, String location, int lineNumber )
+    {
+        if ( isErrorEnabled() )
+        {
+            final String message = formatMessage( content, location, lineNumber );
+            mavenLog.error( message );
+        }
+    }
+
+
     public void error( String content )
     {
         mavenLog.error( content );
@@ -122,6 +132,16 @@
     }
 
 
+    public void warn( String content, String location, int lineNumber )
+    {
+        if ( isWarnEnabled() )
+        {
+            final String message = formatMessage( content, location, lineNumber );
+            mavenLog.warn( message );
+        }
+    }
+
+
     public void warn( String content )
     {
         mavenLog.warn( content );
@@ -132,4 +152,10 @@
     {
         mavenLog.warn( error );
     }
+
+
+    private String formatMessage( String content, String location, int lineNumber )
+    {
+        return content + " at " + location + ":" + lineNumber;
+    }
 }
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/AbstractObject.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/AbstractObject.java
index f5d0f58..45511d6 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/AbstractObject.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/AbstractObject.java
@@ -18,6 +18,7 @@
  */
 package org.apache.felix.scrplugin.om;
 
+import org.apache.felix.scrplugin.helper.IssueLog;
 import org.apache.felix.scrplugin.tags.JavaTag;
 
 /**
@@ -32,11 +33,12 @@
         this.tag = tag;
     }
 
-    protected String getMessage(String message) {
-        if ( this.tag == null ) {
-            return message;
-        }
-        return "@" + this.tag.getName() + ": " + message + " (" + this.tag.getSourceLocation() + ")";
+    protected void logWarn(IssueLog iLog, String message) {
+        iLog.addWarning( "@" + this.tag.getName() + ": " + message, tag.getSourceLocation(), tag.getLineNumber() );
+    }
+
+    protected void logError(IssueLog iLog, String message) {
+        iLog.addError( "@" + this.tag.getName() + ": " + message, tag.getSourceLocation(), tag.getLineNumber() );
     }
 
     public JavaTag getJavaTag() {
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java
index e69ff07..d392eaf 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java
@@ -267,17 +267,17 @@
 
         final JavaClassDescription javaClass = this.tag.getJavaClassDescription();
         if (javaClass == null) {
-            iLog.addError(this.getMessage("Tag not declared in a Java Class"));
+            this.logError( iLog, "Tag not declared in a Java Class" );
         } else {
 
             // if the service is abstract, we do not validate everything
             if ( !this.isAbstract ) {
                 // ensure non-abstract, public class
                 if (!javaClass.isPublic()) {
-                    iLog.addError(this.getMessage("Class must be public: " + javaClass.getName()));
+                    this.logError( iLog, "Class must be public: " + javaClass.getName() );
                 }
                 if (javaClass.isAbstract() || javaClass.isInterface()) {
-                    iLog.addError(this.getMessage("Class must be concrete class (not abstract or interface) : " + javaClass.getName()));
+                    this.logError( iLog, "Class must be concrete class (not abstract or interface) : " + javaClass.getName() );
                 }
 
                 // no errors so far, let's continue
@@ -309,7 +309,7 @@
                         }
                     }
                     if (!constructorFound) {
-                        iLog.addError(this.getMessage("Class must have public default constructor: " + javaClass.getName()));
+                        this.logError( iLog, "Class must have public default constructor: " + javaClass.getName() );
                     }
 
                     // verify properties
@@ -321,7 +321,7 @@
                     boolean isServiceFactory = false;
                     if (this.getService() != null) {
                         if ( this.getService().getInterfaces().size() == 0 ) {
-                            iLog.addError(this.getMessage("Service interface information is missing for @scr.service tag"));
+                            this.logError( iLog, "Service interface information is missing for @scr.service tag" );
                         }
                         this.getService().validate(specVersion, iLog);
                         isServiceFactory = this.getService().isServicefactory();
@@ -329,12 +329,12 @@
 
                     // serviceFactory must not be true for immediate of component factory
                     if (isServiceFactory && this.isImmediate() != null && this.isImmediate().booleanValue() && this.getFactory() != null) {
-                        iLog.addError(this.getMessage("Component must not be a ServiceFactory, if immediate and/or component factory: " + javaClass.getName()));
+                        this.logError( iLog, "Component must not be a ServiceFactory, if immediate and/or component factory: " + javaClass.getName() );
                     }
 
                     // immediate must not be true for component factory
                     if (this.isImmediate() != null && this.isImmediate().booleanValue() && this.getFactory() != null) {
-                        iLog.addError(this.getMessage("Component must not be immediate if component factory: " + javaClass.getName()));
+                        this.logError( iLog, "Component must not be immediate if component factory: " + javaClass.getName() );
                     }
                 }
             }
@@ -352,7 +352,7 @@
                  && !Constants.COMPONENT_CONFIG_POLICY_IGNORE.equals(cp)
                  && !Constants.COMPONENT_CONFIG_POLICY_REQUIRE.equals(cp)
                  && !Constants.COMPONENT_CONFIG_POLICY_OPTIONAL.equals(cp) ) {
-                iLog.addError(this.getMessage("Component has an unknown value for configuration policy: " + cp));
+                this.logError( iLog, "Component has an unknown value for configuration policy: " + cp );
             }
 
         }
@@ -427,7 +427,8 @@
                                             found = methods[i];
                                         } else {
                                             // print warning
-                                            iLog.addWarning(this.getMessage("Lifecycle method " + methods[i].getName() + " occurs several times with different matching signature."));
+                                            this.logWarn( iLog, "Lifecycle method " + methods[i].getName()
+                                                + " occurs several times with different matching signature." );
                                         }
                                     }
                                 }
@@ -448,9 +449,11 @@
                 for(int i=0; i<methods.length; i++) {
                     if ( methodName.equals(methods[i].getName()) ) {
                         if ( methods[i].getParameters().length != 1 ) {
-                            iLog.addWarning(this.getMessage("Lifecycle method " + methods[i].getName() + " has wrong number of arguments"));
+                            this.logWarn( iLog, "Lifecycle method " + methods[i].getName()
+                                + " has wrong number of arguments" );
                         } else {
-                            iLog.addWarning(this.getMessage("Lifecycle method " + methods[i].getName() + " has wrong argument " + methods[i].getParameters()[0].getType()));
+                            this.logWarn( iLog, "Lifecycle method " + methods[i].getName() + " has wrong argument "
+                                + methods[i].getParameters()[0].getType() );
                         }
                     }
                 }
@@ -460,9 +463,10 @@
         if ( method != null && specVersion == Constants.VERSION_1_0) {
             // check protected
             if (method.isPublic()) {
-                iLog.addWarning(this.getMessage("Lifecycle method " + method.getName() + " should be declared protected"));
+                this.logWarn( iLog, "Lifecycle method " + method.getName() + " should be declared protected" );
             } else if (!method.isProtected()) {
-                iLog.addWarning(this.getMessage("Lifecycle method " + method.getName() + " has wrong qualifier, public or protected required"));
+                this.logWarn( iLog, "Lifecycle method " + method.getName()
+                    + " has wrong qualifier, public or protected required" );
             }
         }
     }
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Interface.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Interface.java
index 281a483..9f55f6d 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Interface.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Interface.java
@@ -62,12 +62,12 @@
     throws SCRDescriptorException {
         final JavaClassDescription javaClass = this.tag.getJavaClassDescription();
         if (javaClass == null) {
-            iLog.addError(this.getMessage("Must be declared in a Java class"));
+            this.logError( iLog, "Must be declared in a Java class" );
         } else {
 
             if ( !javaClass.isA(this.getInterfacename()) ) {
                // interface not implemented
-                iLog.addError(this.getMessage("Class must implement provided interface " + this.getInterfacename()));
+                this.logError( iLog, "Class must implement provided interface " + this.getInterfacename() );
             }
         }
     }
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java
index a70ecf5..f3bbb22 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java
@@ -93,7 +93,7 @@
      */
     public void validate(final int specVersion, final IssueLog iLog) {
         if ( name == null || name.trim().length() == 0 ) {
-            iLog.addError(this.getMessage("Property name can not be empty."));
+            this.logError( iLog, "Property name can not be empty." );
         }
         if ( type != null ) {
             if ( !type.equals(Constants.PROPERTY_TYPE_BOOLEAN)
@@ -106,7 +106,7 @@
                  && !type.equals(Constants.PROPERTY_TYPE_LONG )
                  && !type.equals(Constants.PROPERTY_TYPE_STRING )
                  && !type.equals(Constants.PROPERTY_TYPE_SHORT ) ) {
-                iLog.addError(this.getMessage("Property " + name + " has unknown type: " + type));
+                this.logError( iLog, "Property " + name + " has unknown type: " + type );
             }
             // now check for old and new char
             if ( specVersion == Constants.VERSION_1_0 && type.equals(Constants.PROPERTY_TYPE_CHAR_1_1) ) {
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java
index 901d883..47db55c 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java
@@ -160,12 +160,12 @@
 
         // validate name
         if (StringUtils.isEmpty(this.name)) {
-            iLog.addError(this.getMessage("Reference has no name"));
+            this.logError( iLog, "Reference has no name" );
         }
 
         // validate interface
         if (StringUtils.isEmpty(this.interfacename)) {
-            iLog.addError(this.getMessage("Missing interface name"));
+            this.logError( iLog, "Missing interface name" );
         }
 
         // validate cardinality
@@ -173,14 +173,14 @@
             this.cardinality = "1..1";
         } else if (!"0..1".equals(this.cardinality) && !"1..1".equals(this.cardinality)
             && !"0..n".equals(this.cardinality) && !"1..n".equals(this.cardinality)) {
-            iLog.addError(this.getMessage("Invalid Cardinality specification " + this.cardinality));
+            this.logError( iLog, "Invalid Cardinality specification " + this.cardinality );
         }
 
         // validate policy
         if (this.policy == null) {
             this.policy = "static";
         } else if (!"static".equals(this.policy) && !"dynamic".equals(this.policy)) {
-            iLog.addError(this.getMessage("Invalid Policy specification " + this.policy));
+            this.logError( iLog, "Invalid Policy specification " + this.policy );
         }
 
         // validate strategy
@@ -188,7 +188,7 @@
             this.strategy = Constants.REFERENCE_STRATEGY_EVENT;
         } else if (!Constants.REFERENCE_STRATEGY_EVENT.equals(this.strategy)
                    && !Constants.REFERENCE_STRATEGY_LOOKUP.equals(this.strategy)) {
-            iLog.addError(this.getMessage("Invalid strategy type " + this.strategy));
+            this.logError( iLog, "Invalid strategy type " + this.strategy );
         }
 
         // validate bind and unbind methods
@@ -231,7 +231,7 @@
         final JavaMethod method = this.findMethod(specVersion, methodName);
         if (method == null) {
             if ( !componentIsAbstract ) {
-                iLog.addError(this.getMessage("Missing method " + methodName + " for reference " + this.getName()));
+                this.logError( iLog, "Missing method " + methodName + " for reference " + this.getName() );
             }
             return null;
         }
@@ -239,9 +239,9 @@
         // method needs to be protected for 1.0
         if ( specVersion == Constants.VERSION_1_0 ) {
             if (method.isPublic()) {
-                iLog.addWarning(this.getMessage("Method " + method.getName() + " should be declared protected"));
+                this.logWarn( iLog, "Method " + method.getName() + " should be declared protected" );
             } else if (!method.isProtected()) {
-                iLog.addError(this.getMessage("Method " + method.getName() + " has wrong qualifier, public or protected required"));
+                this.logError( iLog, "Method " + method.getName() + " has wrong qualifier, public or protected required" );
                 return null;
             }
         }
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaTag.java
index ba82aa1..336f103 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaTag.java
@@ -34,6 +34,8 @@
 
     String getSourceLocation();
 
+    int getLineNumber();
+
     JavaClassDescription getJavaClassDescription();
 
     JavaField getField();
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/AbstractTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/AbstractTag.java
index bdefa23..c92a1a6 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/AbstractTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/AbstractTag.java
@@ -22,6 +22,8 @@
 
 import org.apache.felix.scrplugin.tags.*;
 
+import com.thoughtworks.qdox.model.Annotation;
+
 /**
  * Description of a java tag for components.
  */
@@ -31,13 +33,16 @@
 
     protected final JavaField field;
 
+    protected final Annotation sourceAnnotation;
+
     protected Map<String, String> parameters;
 
     /**
      * @param desc Description
      * @param field Field
      */
-    public AbstractTag(JavaClassDescription desc, JavaField field) {
+    public AbstractTag(Annotation sourceAnnotation, JavaClassDescription desc, JavaField field) {
+        this.sourceAnnotation = sourceAnnotation;
         this.description = desc;
         this.field = field;
     }
@@ -72,6 +77,13 @@
     }
 
     /**
+     * @see JavaTag#getLineNumber()
+     */
+    public int getLineNumber() {
+        return sourceAnnotation.getLineNumber();
+    }
+
+    /**
      * @see JavaTag#getJavaClassDescription()
      */
     public JavaClassDescription getJavaClassDescription() {
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ComponentTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ComponentTag.java
index 3747bc1..a36c63a 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ComponentTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ComponentTag.java
@@ -35,15 +35,12 @@
 
     protected final Component annotation;
 
-    protected final Annotation sourceAnnotation;
-
     /**
      * @param annotation Annotation
      * @param desc Description
      */
     public ComponentTag(final Annotation annotation, final JavaClassDescription desc) {
-        super(desc, null);
-        this.sourceAnnotation = annotation;
+        super(annotation, desc, null);
         this.annotation = new Component() {
 
             public boolean componentAbstract() {
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/PropertyTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/PropertyTag.java
index 083c013..33ca627 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/PropertyTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/PropertyTag.java
@@ -40,7 +40,7 @@
      * @param desc Description
      */
     public PropertyTag(final Annotation annotation, final JavaClassDescription desc, JavaField field) {
-        super(desc, field);
+        super(annotation, desc, field);
         this.annotation = new Property() {
 
             public int cardinality() {
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ReferenceTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ReferenceTag.java
index 1ab68a7..05e41cc 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ReferenceTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ReferenceTag.java
@@ -40,7 +40,7 @@
      * @param desc Description
      */
     public ReferenceTag(final Annotation annotation, final JavaClassDescription desc, JavaField field) {
-        super(desc, field);
+        super(annotation, desc, field);
 
         this.annotation = new Reference() {
 
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ServiceTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ServiceTag.java
index 6654377..f7fcc47 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ServiceTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/defaulttag/ServiceTag.java
@@ -40,7 +40,7 @@
      * @param desc Description
      */
     public ServiceTag(final Annotation annotation, JavaClassDescription desc) {
-        super(desc, null);
+        super(annotation, desc, null);
         this.annotation = new Service() {
 
             public boolean serviceFactory() {
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingAnnotationTagProvider.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingAnnotationTagProvider.java
index 6ecc1fa..b83a691 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingAnnotationTagProvider.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingAnnotationTagProvider.java
@@ -42,44 +42,44 @@
             // generate @Component tag if required
             boolean generateComponent = Util.getBooleanValue(annotation, "generateComponent", SlingServlet.class);
             if (generateComponent) {
-                tags.add(new SlingServletComponentTag(description));
+                tags.add(new SlingServletComponentTag(annotation, description));
             }
 
             // generate @Service tag if required
             boolean generateService = Util.getBooleanValue(annotation, "generateService", SlingServlet.class);
             if (generateService) {
-                tags.add(new SlingServletServiceTag(description));
+                tags.add(new SlingServletServiceTag(annotation, description));
             }
 
             // generate @Property tags
             // {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_PATHS}
             String[] paths = Util.getStringValues(annotation, description, "paths");
             if (paths != null && paths.length != 0) {
-                tags.add(new SlingServletPropertyTag("sling.servlet.paths", paths, description));
+                tags.add(new SlingServletPropertyTag(annotation, "sling.servlet.paths", paths, description));
             }
 
             // {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES}
             String[] resourceTypes = Util.getStringValues(annotation, description, "resourceTypes");
             if (resourceTypes != null && resourceTypes.length != 0) {
-                tags.add(new SlingServletPropertyTag("sling.servlet.resourceTypes", resourceTypes, description));
+                tags.add(new SlingServletPropertyTag(annotation, "sling.servlet.resourceTypes", resourceTypes, description));
             }
 
             // {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_SELECTORS}
             String[] selectors = Util.getStringValues(annotation, description, "selectors");
             if (selectors != null && selectors.length != 0) {
-                tags.add(new SlingServletPropertyTag("sling.servlet.selectors", selectors, description));
+                tags.add(new SlingServletPropertyTag(annotation, "sling.servlet.selectors", selectors, description));
             }
 
             // {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_EXTENSIONS}
             String[] extensions = Util.getStringValues(annotation, description, "extensions");
             if (extensions != null && extensions.length != 0) {
-                tags.add(new SlingServletPropertyTag("sling.servlet.extensions", extensions, description));
+                tags.add(new SlingServletPropertyTag(annotation, "sling.servlet.extensions", extensions, description));
             }
 
             // {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_METHODS}
             String[] methods = Util.getStringValues(annotation, description, "methods");
             if (methods != null && methods.length != 0) {
-                tags.add(new SlingServletPropertyTag("sling.servlet.methods", methods, description));
+                tags.add(new SlingServletPropertyTag(annotation, "sling.servlet.methods", methods, description));
             }
 
         }
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletComponentTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletComponentTag.java
index c10771d..105186a 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletComponentTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletComponentTag.java
@@ -25,6 +25,8 @@
 import org.apache.felix.scrplugin.tags.JavaClassDescription;
 import org.apache.felix.scrplugin.tags.annotation.defaulttag.AbstractTag;
 
+import com.thoughtworks.qdox.model.Annotation;
+
 /**
  * Description of a java tag for components.
  */
@@ -33,8 +35,8 @@
     /**
      * @param desc Description
      */
-    public SlingServletComponentTag(JavaClassDescription desc) {
-        super(desc, null);
+    public SlingServletComponentTag(Annotation annotation, JavaClassDescription desc) {
+        super(annotation, desc, null);
     }
 
     @Override
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletPropertyTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletPropertyTag.java
index 62a2557..e88b5b6 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletPropertyTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletPropertyTag.java
@@ -27,6 +27,8 @@
 import org.apache.felix.scrplugin.tags.JavaClassDescription;
 import org.apache.felix.scrplugin.tags.annotation.defaulttag.AbstractTag;
 
+import com.thoughtworks.qdox.model.Annotation;
+
 /**
  * Description of a java tag for components.
  */
@@ -40,8 +42,8 @@
      * @param values Property values
      * @param desc Description
      */
-    public SlingServletPropertyTag(String name, String[] values, JavaClassDescription desc) {
-        super(desc, null);
+    public SlingServletPropertyTag(Annotation annotation, String name, String[] values, JavaClassDescription desc) {
+        super(annotation, desc, null);
         this.name = name;
         this.values = values;
     }
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletServiceTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletServiceTag.java
index 63e8277..8ca4d99 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletServiceTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/annotation/sling/SlingServletServiceTag.java
@@ -27,6 +27,8 @@
 import org.apache.felix.scrplugin.tags.JavaClassDescription;
 import org.apache.felix.scrplugin.tags.annotation.defaulttag.AbstractTag;
 
+import com.thoughtworks.qdox.model.Annotation;
+
 /**
  * Description of a java tag for components.
  */
@@ -35,8 +37,8 @@
     /**
      * @param desc Description
      */
-    public SlingServletServiceTag(JavaClassDescription desc) {
-        super(desc, null);
+    public SlingServletServiceTag(Annotation annotation, JavaClassDescription desc) {
+        super(annotation, desc, null);
     }
 
     @Override
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
index cb98c98..6d1fb49 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
@@ -92,7 +92,7 @@
      */
     public JavaField getExternalFieldByName(String name)
     throws SCRDescriptorException {
-        throw new SCRDescriptorException("getExternalFieldByName not supported for this class.");
+        throw new SCRDescriptorException("getExternalFieldByName not supported for this class.", getName(), 0);
     }
 
     /**
@@ -100,7 +100,7 @@
      */
     public JavaClassDescription getReferencedClass(String referencedName)
     throws SCRDescriptorException {
-        throw new SCRDescriptorException("getReferencedClass not supported for this class.");
+        throw new SCRDescriptorException("getReferencedClass not supported for this class.", getName(), 0);
     }
 
     /**
@@ -143,7 +143,7 @@
             // scopes exists.
             throw new SCRDescriptorException("Class loading error. This error usually occurs if you have a " +
                     "service inheriting from a class coming from another bundle and that class using a " +
-                    "third library and all dependencies are specified with scope 'provided'.", ncdfe);
+                    "third library and all dependencies are specified with scope 'provided'.", getName(), 0, ncdfe);
         } catch (NoSuchMethodException e) {
             // ignore this
         }
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaTag.java
index cfe721e..f7f68b3 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaTag.java
@@ -166,4 +166,13 @@
     public String getSourceLocation() {
         return "Compiled class: " + this.description.getName();
     }
+
+    /**
+     * @see org.apache.felix.scrplugin.tags.JavaTag#getLineNumber()
+     */
+    public int getLineNumber()
+    {
+        // we don't know the exact line number of a tag in a compiled class
+        return 0;
+    }
 }
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java
index 27023d5..2c68c75 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java
@@ -43,7 +43,6 @@
 import com.thoughtworks.qdox.model.DocletTag;
 import com.thoughtworks.qdox.model.JavaClass;
 import com.thoughtworks.qdox.model.JavaParameter;
-import com.thoughtworks.qdox.model.JavaSource;
 import com.thoughtworks.qdox.model.Type;
 
 /**
@@ -389,7 +388,7 @@
             fos.write(writer.toByteArray());
             fos.close();
         } catch (Exception e) {
-            throw new SCRDescriptorException("Unable to add methods to " + this.getName(), e);
+            throw new SCRDescriptorException("Unable to add methods to " + this.getName(), className, 0, e);
         }
     }
 
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaTag.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaTag.java
index 53e9353..f416cd8 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaTag.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaTag.java
@@ -71,7 +71,14 @@
      * @see org.apache.felix.scrplugin.tags.JavaTag#getSourceLocation()
      */
     public String getSourceLocation() {
-        return this.docletTag.getContext().getParent().getParentSource().getURL() + ", line " + this.docletTag.getLineNumber();
+        return String.valueOf(this.docletTag.getContext().getParent().getParentSource().getURL());
+    }
+
+    /**
+     * @see org.apache.felix.scrplugin.tags.JavaTag#getLineNumber()
+     */
+    public int getLineNumber() {
+        return this.docletTag.getLineNumber();
     }
 
     /**
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
index 482201e..9207fcf 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
@@ -120,7 +120,7 @@
             IOUtils.parse(file, xmlHandler);
             return xmlHandler.components;
         } catch (TransformerException e) {
-            throw new SCRDescriptorException("Unable to read xml from " + file, e);
+            throw new SCRDescriptorException( "Unable to read xml", "[stream]", 0, e );
         }
     }
 
@@ -135,11 +135,11 @@
         try {
             generateXML(components, IOUtils.getSerializer(file), isScrPrivateFile);
         } catch (TransformerException e) {
-            throw new SCRDescriptorException("Unable to write xml to " + file, e);
+            throw new SCRDescriptorException("Unable to write xml", file.toString(), 0, e);
         } catch (SAXException e) {
-            throw new SCRDescriptorException("Unable to generate xml for " + file, e);
+            throw new SCRDescriptorException("Unable to generate xml", file.toString(), 0, e);
         } catch (IOException e) {
-            throw new SCRDescriptorException("Unable to write xml to " + file, e);
+            throw new SCRDescriptorException("Unable to write xml", file.toString(), 0, e);
         }
     }
 
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java
index 15eeaff..dcbae69 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/MetaTypeIO.java
@@ -73,11 +73,11 @@
         try {
             generateXML(metaData, IOUtils.getSerializer(file));
         } catch (TransformerException e) {
-            throw new SCRDescriptorException("Unable to write xml to " + file, e);
+            throw new SCRDescriptorException("Unable to write xml", file.toString(), 0, e);
         } catch (SAXException e) {
-            throw new SCRDescriptorException("Unable to generate xml for " + file, e);
+            throw new SCRDescriptorException("Unable to generate xml", file.toString(), 0, e);
         } catch (IOException e) {
-            throw new SCRDescriptorException("Unable to write xml to " + file, e);
+            throw new SCRDescriptorException("Unable to write xml", file.toString(), 0, e);
         }
     }