/* * Copyright (c) 2004, PostgreSQL Global Development Group * See the LICENSE file in the project root for more information. */ package org.postgresql.util; import org.postgresql.core.EncodingPredictor; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; public class ServerErrorMessage implements Serializable { private static final Logger LOGGER = Logger.getLogger(ServerErrorMessage.class.getName()); private static final Character SEVERITY = 'S'; private static final Character MESSAGE = 'M'; private static final Character DETAIL = 'D'; private static final Character HINT = 'H'; private static final Character POSITION = 'P'; private static final Character WHERE = 'W'; private static final Character FILE = 'F'; private static final Character LINE = 'L'; private static final Character ROUTINE = 'R'; private static final Character SQLSTATE = 'C'; private static final Character INTERNAL_POSITION = 'p'; private static final Character INTERNAL_QUERY = 'q'; private static final Character SCHEMA = 's'; private static final Character TABLE = 't'; private static final Character COLUMN = 'c'; private static final Character DATATYPE = 'd'; private static final Character CONSTRAINT = 'n'; private final Map<Character, String> m_mesgParts = new HashMap<Character, String>(); public ServerErrorMessage(EncodingPredictor.DecodeResult serverError) { this(serverError.result); if (serverError.encoding != null) { m_mesgParts.put(MESSAGE, m_mesgParts.get(MESSAGE) + GT.tr(" (pgjdbc: autodetected server-encoding to be {0}, if the message is not readable, please check database logs and/or host, port, dbname, user, password, pg_hba.conf)", serverError.encoding) ); } } public ServerErrorMessage(String p_serverError) { char[] l_chars = p_serverError.toCharArray(); int l_pos = 0; int l_length = l_chars.length; while (l_pos < l_length) { char l_mesgType = l_chars[l_pos]; if (l_mesgType != '\0') { l_pos++; int l_startString = l_pos; // order here is important position must be checked before accessing the array while (l_pos < l_length && l_chars[l_pos] != '\0') { l_pos++; } String l_mesgPart = new String(l_chars, l_startString, l_pos - l_startString); m_mesgParts.put(l_mesgType, l_mesgPart); } l_pos++; } } public String getSQLState() { return m_mesgParts.get(SQLSTATE); } public String getMessage() { return m_mesgParts.get(MESSAGE); } public String getSeverity() { return m_mesgParts.get(SEVERITY); } public String getDetail() { return m_mesgParts.get(DETAIL); } public String getHint() { return m_mesgParts.get(HINT); } public int getPosition() { return getIntegerPart(POSITION); } public String getWhere() { return m_mesgParts.get(WHERE); } public String getSchema() { return m_mesgParts.get(SCHEMA); } public String getTable() { return m_mesgParts.get(TABLE); } public String getColumn() { return m_mesgParts.get(COLUMN); } public String getDatatype() { return m_mesgParts.get(DATATYPE); } public String getConstraint() { return m_mesgParts.get(CONSTRAINT); } public String getFile() { return m_mesgParts.get(FILE); } public int getLine() { return getIntegerPart(LINE); } public String getRoutine() { return m_mesgParts.get(ROUTINE); } public String getInternalQuery() { return m_mesgParts.get(INTERNAL_QUERY); } public int getInternalPosition() { return getIntegerPart(INTERNAL_POSITION); } private int getIntegerPart(Character c) { String s = m_mesgParts.get(c); if (s == null) { return 0; } return Integer.parseInt(s); } public String toString() { // Now construct the message from what the server sent // The general format is: // SEVERITY: Message \n // Detail: \n // Hint: \n // Position: \n // Where: \n // Internal Query: \n // Internal Position: \n // Location: File:Line:Routine \n // SQLState: \n // // Normally only the message and detail is included. // If INFO level logging is enabled then detail, hint, position and where are // included. If DEBUG level logging is enabled then all information // is included. StringBuilder l_totalMessage = new StringBuilder(); String l_message = m_mesgParts.get(SEVERITY); if (l_message != null) { l_totalMessage.append(l_message).append(": "); } l_message = m_mesgParts.get(MESSAGE); if (l_message != null) { l_totalMessage.append(l_message); } l_message = m_mesgParts.get(DETAIL); if (l_message != null) { l_totalMessage.append("\n ").append(GT.tr("Detail: {0}", l_message)); } l_message = m_mesgParts.get(HINT); if (l_message != null) { l_totalMessage.append("\n ").append(GT.tr("Hint: {0}", l_message)); } l_message = m_mesgParts.get(POSITION); if (l_message != null) { l_totalMessage.append("\n ").append(GT.tr("Position: {0}", l_message)); } l_message = m_mesgParts.get(WHERE); if (l_message != null) { l_totalMessage.append("\n ").append(GT.tr("Where: {0}", l_message)); } if (LOGGER.isLoggable(Level.FINEST)) { String l_internalQuery = m_mesgParts.get(INTERNAL_QUERY); if (l_internalQuery != null) { l_totalMessage.append("\n ").append(GT.tr("Internal Query: {0}", l_internalQuery)); } String l_internalPosition = m_mesgParts.get(INTERNAL_POSITION); if (l_internalPosition != null) { l_totalMessage.append("\n ").append(GT.tr("Internal Position: {0}", l_internalPosition)); } String l_file = m_mesgParts.get(FILE); String l_line = m_mesgParts.get(LINE); String l_routine = m_mesgParts.get(ROUTINE); if (l_file != null || l_line != null || l_routine != null) { l_totalMessage.append("\n ").append(GT.tr("Location: File: {0}, Routine: {1}, Line: {2}", l_file, l_routine, l_line)); } l_message = m_mesgParts.get(SQLSTATE); if (l_message != null) { l_totalMessage.append("\n ").append(GT.tr("Server SQLState: {0}", l_message)); } } return l_totalMessage.toString(); } }