001/* 002 * BridJ - Dynamic and blazing-fast native interop for Java. 003 * http://bridj.googlecode.com/ 004 * 005 * Copyright (c) 2010-2013, Olivier Chafik (http://ochafik.com/) 006 * All rights reserved. 007 * 008 * Redistribution and use in source and binary forms, with or without 009 * modification, are permitted provided that the following conditions are met: 010 * 011 * * Redistributions of source code must retain the above copyright 012 * notice, this list of conditions and the following disclaimer. 013 * * Redistributions in binary form must reproduce the above copyright 014 * notice, this list of conditions and the following disclaimer in the 015 * documentation and/or other materials provided with the distribution. 016 * * Neither the name of Olivier Chafik nor the 017 * names of its contributors may be used to endorse or promote products 018 * derived from this software without specific prior written permission. 019 * 020 * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY 021 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 023 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY 024 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 027 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 030 */ 031package org.bridj; 032 033import java.io.FileNotFoundException; 034import org.bridj.ann.*; 035 036//import static org.bridj.LastError.Windows.*; 037//import static org.bridj.LastError.Unix.*; 038import static org.bridj.Pointer.*; 039 040/** 041 * Native error that correspond to the <a 042 * href="http://en.wikipedia.org/wiki/Errno.h">errno</a> or <a 043 * href="http://msdn.microsoft.com/en-us/library/ms679360(v=vs.85).aspx">GetLastError()</a> 044 * mechanism.<br> 045 * Some C functions declare errors by marking an error code in <a 046 * href="http://en.wikipedia.org/wiki/Errno.h">errno</a> or through <a 047 * href="http://msdn.microsoft.com/en-us/library/ms680627(v=vs.85).aspx">SetLastError(int)</a>.<br> 048 * If you want their corresponding bindings to throw an exception whenever such 049 * an error was marked, simply make them throw this exception explicitly.<br> 050 * On Windows, BridJ will first check <a 051 * href="http://msdn.microsoft.com/en-us/library/ms679360(v=vs.85).aspx">GetLastError()</a>, 052 * then if no error was found it will check <a 053 * href="http://en.wikipedia.org/wiki/Errno.h">errno</a> (on the other platforms 054 * only <a href="http://en.wikipedia.org/wiki/Errno.h">errno</a> is 055 * available).<br> 056 * For instance, look at the following binding of the C-library <a 057 * href="http://www.cplusplus.com/reference/clibrary/cstdlib/strtoul/">strtoul</a> 058 * function : 059 * <pre> 060 * @Library("c") 061 * {@code 062 * public static native long strtoul(Pointer<Byte> str, Pointer<Pointer<Byte>> endptr, int base) throws LastError; 063 * }</pre> 064 * 065 * @author Olivier Chafik 066 */ 067public class LastError extends NativeError { 068 069 final int code, kind; 070 String description; 071 072 static final int eLastErrorKindWindows = 1, eLastErrorKindCLibrary = 2; 073 074 LastError(int code, int kind) { 075 super(null); 076 this.code = code; 077 this.kind = kind; 078 /* 079 if (BridJ.verbose) { 080 BridJ.info("Last error detected : " + getMessage()); 081 }*/ 082 } 083 084 public int hashCode() { 085 return Integer.valueOf(code).hashCode() ^ Integer.valueOf(kind).hashCode(); 086 } 087 088 public boolean equals(Object o) { 089 if (!(o instanceof LastError)) { 090 return false; 091 } 092 LastError e = (LastError) o; 093 return code == e.code && kind == e.kind; 094 } 095 096 /** 097 * Native error code (as returned by <a 098 * href="http://en.wikipedia.org/wiki/Errno.h">errno</a> or <a 099 * href="http://msdn.microsoft.com/en-us/library/ms679360(v=vs.85).aspx">GetLastError()</a>). 100 */ 101 public int getCode() { 102 return code; 103 } 104 105 /** 106 * Native error description (as returned by <a 107 * href="http://www.cplusplus.com/reference/clibrary/cstring/strerror/">strerror</a> 108 * or <a 109 * href="http://msdn.microsoft.com/en-us/library/ms680582(v=vs.85).aspx">FormatMessage</a>). 110 */ 111 public String getDescription() { 112 if (description == null) { 113 description = getDescription(code, kind); 114 } 115 return description; 116 } 117 118 @Override 119 public String getMessage() { 120 String description = getDescription(); 121 return (description == null ? "?" : description.trim()) + " (error code = " + code + ")"; 122 } 123 124 private static native String getDescription(int value, int kind); 125 126 private static final ThreadLocal<LastError> lastError = new ThreadLocal<LastError>(); 127 128 public static LastError getLastError() { 129 return lastError.get(); 130 } 131 132 static LastError setLastError(int code, int kind) { 133 if (code == 0) { 134 lastError.set(null); 135 return null; 136 } 137 LastError err = new LastError(code, kind); 138 err.fillInStackTrace(); 139 lastError.set(err); 140 return err; 141 } 142}