001 /*
002 * Copyright 2006 Stephen J. McConnell.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.lang;
020
021 import dpml.util.ElementHelper;
022
023 import java.io.File;
024 import java.io.IOException;
025 import java.net.URI;
026 import java.net.URL;
027
028 import net.dpml.transit.Artifact;
029
030 import org.w3c.dom.Document;
031 import org.w3c.dom.Element;
032 import org.w3c.dom.NamedNodeMap;
033 import org.w3c.dom.Node;
034
035 /**
036 * Exception related to data decoding from a DOM element.
037 */
038 public class DecodingException extends IOException
039 {
040 private final Element m_element;
041
042 /**
043 * Create a new decoding exception.
044 * @param element the element representing the source of the error
045 * @param message the exception message
046 */
047 public DecodingException( String message, Element element )
048 {
049 this( message, null, element );
050 }
051
052 /**
053 * Create a new decoding exception.
054 * @param element the element representing the source of the error
055 * @param message the exception message
056 * @param cause the causal exception
057 */
058 public DecodingException( String message, Throwable cause, Element element )
059 {
060 super( message );
061 if( null != cause )
062 {
063 super.initCause( cause );
064 }
065 m_element = element;
066 }
067
068 /**
069 * Get the element that is the subject of this exception.
070 * @return the subject element
071 */
072 public Element getElement()
073 {
074 return m_element;
075 }
076
077 /**
078 * Return a string representation of the exception.
079 * @return the string value
080 */
081 public String getMessage()
082 {
083 try
084 {
085 String message = super.getMessage();
086 StringBuffer buffer = new StringBuffer( message );
087 Element element = getElement();
088 if( null != element )
089 {
090 Document document = element.getOwnerDocument();
091 String uri = document.getDocumentURI();
092 if( null != uri )
093 {
094 buffer.append( "\nSource: " + uri );
095 String filename = getSourceFilePath( uri );
096 if( null != filename )
097 {
098 buffer.append( "\nFile: " + filename );
099 }
100 buffer.append( "\n" );
101 }
102 String listing = list( element );
103 buffer.append( listing );
104 }
105 return buffer.toString();
106 }
107 catch( Throwable e )
108 {
109 return super.getMessage();
110 }
111 }
112
113 /**
114 * Static utility operation that returns a string representation of a DOM element.
115 * @param element the element to stringify
116 * @return the string value
117 */
118 public static String list( Element element )
119 {
120 return list( element, "" );
121 }
122
123 /**
124 * Static utility operation that returns a syring representation of a DOM element.
125 * @param element the element to stringify
126 * @param pad padding offset
127 * @return the string value
128 */
129 public static String list( Element element, String pad )
130 {
131 if( null == element )
132 {
133 return "";
134 }
135 StringBuffer buffer = new StringBuffer();
136 String tag = element.getTagName();
137 buffer.append( pad + "<" );
138 buffer.append( tag );
139 NamedNodeMap map = element.getAttributes();
140 for( int i=0; i<map.getLength(); i++ )
141 {
142 Node item = map.item( i );
143 buffer.append( " " + item.getNodeName() + "=\"" );
144 buffer.append( item.getNodeValue() );
145 buffer.append( "\"" );
146 }
147
148 Element[] children = ElementHelper.getChildren( element );
149 if( children.length > 0 )
150 {
151 buffer.append( ">" );
152 for( int i=0; i<children.length; i++ )
153 {
154 Element child = children[i];
155 String listing = list( child, pad + " " );
156 String tagName = child.getTagName();
157 buffer.append( "\n" + listing );
158 }
159 buffer.append( "\n" + pad + "</" + tag + ">" );
160 }
161 else
162 {
163 buffer.append( "/>" );
164 }
165 return buffer.toString();
166 }
167
168 private static String getSourceFilePath( String value )
169 {
170 try
171 {
172 URI uri = URI.create( value );
173 if( Artifact.isRecognized( uri ) )
174 {
175 URL url = Artifact.toURL( uri );
176 File file = (File) url.getContent( new Class[]{File.class} );
177 return file.getCanonicalPath();
178 }
179 return null;
180 }
181 catch( Throwable e )
182 {
183 return null;
184 }
185 }
186
187 }