Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/awt/CUPSfuncs.c
32287 views
/*1* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <jni.h>26#include <jni_util.h>27#include <jvm_md.h>28#include <dlfcn.h>29#include <cups/cups.h>30#include <cups/ppd.h>3132//#define CUPS_DEBUG3334#ifdef CUPS_DEBUG35#define DPRINTF(x, y) fprintf(stderr, x, y);36#else37#define DPRINTF(x, y)38#endif3940typedef const char* (*fn_cupsServer)(void);41typedef int (*fn_ippPort)(void);42typedef http_t* (*fn_httpConnect)(const char *, int);43typedef void (*fn_httpClose)(http_t *);44typedef char* (*fn_cupsGetPPD)(const char *);45typedef cups_dest_t* (*fn_cupsGetDest)(const char *name,46const char *instance, int num_dests, cups_dest_t *dests);47typedef int (*fn_cupsGetDests)(cups_dest_t **dests);48typedef void (*fn_cupsFreeDests)(int num_dests, cups_dest_t *dests);49typedef ppd_file_t* (*fn_ppdOpenFile)(const char *);50typedef void (*fn_ppdClose)(ppd_file_t *);51typedef ppd_option_t* (*fn_ppdFindOption)(ppd_file_t *, const char *);52typedef ppd_size_t* (*fn_ppdPageSize)(ppd_file_t *, char *);5354fn_cupsServer j2d_cupsServer;55fn_ippPort j2d_ippPort;56fn_httpConnect j2d_httpConnect;57fn_httpClose j2d_httpClose;58fn_cupsGetPPD j2d_cupsGetPPD;59fn_cupsGetDest j2d_cupsGetDest;60fn_cupsGetDests j2d_cupsGetDests;61fn_cupsFreeDests j2d_cupsFreeDests;62fn_ppdOpenFile j2d_ppdOpenFile;63fn_ppdClose j2d_ppdClose;64fn_ppdFindOption j2d_ppdFindOption;65fn_ppdPageSize j2d_ppdPageSize;666768/*69* Initialize library functions.70* // REMIND : move tab , add dlClose before return71*/72JNIEXPORT jboolean JNICALL73Java_sun_print_CUPSPrinter_initIDs(JNIEnv *env,74jobject printObj) {75void *handle = dlopen(VERSIONED_JNI_LIB_NAME("cups", "2"),76RTLD_LAZY | RTLD_GLOBAL);7778if (handle == NULL) {79handle = dlopen(JNI_LIB_NAME("cups"), RTLD_LAZY | RTLD_GLOBAL);80if (handle == NULL) {81return JNI_FALSE;82}83}8485j2d_cupsServer = (fn_cupsServer)dlsym(handle, "cupsServer");86if (j2d_cupsServer == NULL) {87dlclose(handle);88return JNI_FALSE;89}9091j2d_ippPort = (fn_ippPort)dlsym(handle, "ippPort");92if (j2d_ippPort == NULL) {93dlclose(handle);94return JNI_FALSE;95}9697j2d_httpConnect = (fn_httpConnect)dlsym(handle, "httpConnect");98if (j2d_httpConnect == NULL) {99dlclose(handle);100return JNI_FALSE;101}102103j2d_httpClose = (fn_httpClose)dlsym(handle, "httpClose");104if (j2d_httpClose == NULL) {105dlclose(handle);106return JNI_FALSE;107}108109j2d_cupsGetPPD = (fn_cupsGetPPD)dlsym(handle, "cupsGetPPD");110if (j2d_cupsGetPPD == NULL) {111dlclose(handle);112return JNI_FALSE;113}114115j2d_cupsGetDest = (fn_cupsGetDest)dlsym(handle, "cupsGetDest");116if (j2d_cupsGetDest == NULL) {117dlclose(handle);118return JNI_FALSE;119}120121j2d_cupsGetDests = (fn_cupsGetDests)dlsym(handle, "cupsGetDests");122if (j2d_cupsGetDests == NULL) {123dlclose(handle);124return JNI_FALSE;125}126127j2d_cupsFreeDests = (fn_cupsFreeDests)dlsym(handle, "cupsFreeDests");128if (j2d_cupsFreeDests == NULL) {129dlclose(handle);130return JNI_FALSE;131}132133j2d_ppdOpenFile = (fn_ppdOpenFile)dlsym(handle, "ppdOpenFile");134if (j2d_ppdOpenFile == NULL) {135dlclose(handle);136return JNI_FALSE;137138}139140j2d_ppdClose = (fn_ppdClose)dlsym(handle, "ppdClose");141if (j2d_ppdClose == NULL) {142dlclose(handle);143return JNI_FALSE;144145}146147j2d_ppdFindOption = (fn_ppdFindOption)dlsym(handle, "ppdFindOption");148if (j2d_ppdFindOption == NULL) {149dlclose(handle);150return JNI_FALSE;151}152153j2d_ppdPageSize = (fn_ppdPageSize)dlsym(handle, "ppdPageSize");154if (j2d_ppdPageSize == NULL) {155dlclose(handle);156return JNI_FALSE;157}158159return JNI_TRUE;160}161162/*163* Gets CUPS server name.164*165*/166JNIEXPORT jstring JNICALL167Java_sun_print_CUPSPrinter_getCupsServer(JNIEnv *env,168jobject printObj)169{170jstring cServer = NULL;171const char* server = j2d_cupsServer();172if (server != NULL) {173// Is this a local domain socket?174if (strncmp(server, "/", 1) == 0) {175cServer = JNU_NewStringPlatform(env, "localhost");176} else {177cServer = JNU_NewStringPlatform(env, server);178}179}180return cServer;181}182183/*184* Gets CUPS port name.185*186*/187JNIEXPORT jint JNICALL188Java_sun_print_CUPSPrinter_getCupsPort(JNIEnv *env,189jobject printObj)190{191int port = j2d_ippPort();192return (jint) port;193}194195196/*197* Gets CUPS default printer name.198*199*/200JNIEXPORT jstring JNICALL201Java_sun_print_CUPSPrinter_getCupsDefaultPrinter(JNIEnv *env,202jobject printObj)203{204jstring cDefPrinter = NULL;205cups_dest_t *dests;206char *defaultPrinter = NULL;207int num_dests = j2d_cupsGetDests(&dests);208int i = 0;209cups_dest_t *dest = j2d_cupsGetDest(NULL, NULL, num_dests, dests);210if (dest != NULL) {211defaultPrinter = dest->name;212if (defaultPrinter != NULL) {213cDefPrinter = JNU_NewStringPlatform(env, defaultPrinter);214}215}216j2d_cupsFreeDests(num_dests, dests);217return cDefPrinter;218}219220/*221* Checks if connection can be made to the server.222*223*/224JNIEXPORT jboolean JNICALL225Java_sun_print_CUPSPrinter_canConnect(JNIEnv *env,226jobject printObj,227jstring server,228jint port)229{230const char *serverName;231serverName = (*env)->GetStringUTFChars(env, server, NULL);232if (serverName != NULL) {233http_t *http = j2d_httpConnect(serverName, (int)port);234(*env)->ReleaseStringUTFChars(env, server, serverName);235if (http != NULL) {236j2d_httpClose(http);237return JNI_TRUE;238}239}240return JNI_FALSE;241}242243244/*245* Returns list of media: pages + trays246*/247JNIEXPORT jobjectArray JNICALL248Java_sun_print_CUPSPrinter_getMedia(JNIEnv *env,249jobject printObj,250jstring printer)251{252ppd_file_t *ppd;253ppd_option_t *optionTray, *optionPage;254ppd_choice_t *choice;255const char *name;256const char *filename;257int i, nTrays=0, nPages=0, nTotal=0;258jstring utf_str;259jclass cls;260jobjectArray nameArray = NULL;261262name = (*env)->GetStringUTFChars(env, printer, NULL);263if (name == NULL) {264(*env)->ExceptionClear(env);265JNU_ThrowOutOfMemoryError(env, "Could not create printer name");266return NULL;267}268269// NOTE: cupsGetPPD returns a pointer to a filename of a temporary file.270// unlink() must be caled to remove the file when finished using it.271filename = j2d_cupsGetPPD(name);272(*env)->ReleaseStringUTFChars(env, printer, name);273CHECK_NULL_RETURN(filename, NULL);274275cls = (*env)->FindClass(env, "java/lang/String");276CHECK_NULL_RETURN(cls, NULL);277278if ((ppd = j2d_ppdOpenFile(filename)) == NULL) {279unlink(filename);280DPRINTF("CUPSfuncs::unable to open PPD %s\n", filename);281return NULL;282}283284optionPage = j2d_ppdFindOption(ppd, "PageSize");285if (optionPage != NULL) {286nPages = optionPage->num_choices;287}288289optionTray = j2d_ppdFindOption(ppd, "InputSlot");290if (optionTray != NULL) {291nTrays = optionTray->num_choices;292}293294if ((nTotal = (nPages+nTrays) *2) > 0) {295nameArray = (*env)->NewObjectArray(env, nTotal, cls, NULL);296if (nameArray == NULL) {297unlink(filename);298j2d_ppdClose(ppd);299DPRINTF("CUPSfuncs::bad alloc new array\n", "")300(*env)->ExceptionClear(env);301JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");302return NULL;303}304305for (i = 0; optionPage!=NULL && i<nPages; i++) {306choice = (optionPage->choices)+i;307utf_str = JNU_NewStringPlatform(env, choice->text);308if (utf_str == NULL) {309unlink(filename);310j2d_ppdClose(ppd);311DPRINTF("CUPSfuncs::bad alloc new string ->text\n", "")312JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");313return NULL;314}315(*env)->SetObjectArrayElement(env, nameArray, i*2, utf_str);316(*env)->DeleteLocalRef(env, utf_str);317utf_str = JNU_NewStringPlatform(env, choice->choice);318if (utf_str == NULL) {319unlink(filename);320j2d_ppdClose(ppd);321DPRINTF("CUPSfuncs::bad alloc new string ->choice\n", "")322JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");323return NULL;324}325(*env)->SetObjectArrayElement(env, nameArray, i*2+1, utf_str);326(*env)->DeleteLocalRef(env, utf_str);327}328329for (i = 0; optionTray!=NULL && i<nTrays; i++) {330choice = (optionTray->choices)+i;331utf_str = JNU_NewStringPlatform(env, choice->text);332if (utf_str == NULL) {333unlink(filename);334j2d_ppdClose(ppd);335DPRINTF("CUPSfuncs::bad alloc new string text\n", "")336JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");337return NULL;338}339(*env)->SetObjectArrayElement(env, nameArray,340(nPages+i)*2, utf_str);341(*env)->DeleteLocalRef(env, utf_str);342utf_str = JNU_NewStringPlatform(env, choice->choice);343if (utf_str == NULL) {344unlink(filename);345j2d_ppdClose(ppd);346DPRINTF("CUPSfuncs::bad alloc new string choice\n", "")347JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");348return NULL;349}350(*env)->SetObjectArrayElement(env, nameArray,351(nPages+i)*2+1, utf_str);352(*env)->DeleteLocalRef(env, utf_str);353}354}355j2d_ppdClose(ppd);356unlink(filename);357return nameArray;358}359360361/*362* Returns list of page sizes and imageable area.363*/364JNIEXPORT jfloatArray JNICALL365Java_sun_print_CUPSPrinter_getPageSizes(JNIEnv *env,366jobject printObj,367jstring printer)368{369ppd_file_t *ppd;370ppd_option_t *option;371ppd_choice_t *choice;372ppd_size_t *size;373374const char *name = (*env)->GetStringUTFChars(env, printer, NULL);375if (name == NULL) {376(*env)->ExceptionClear(env);377JNU_ThrowOutOfMemoryError(env, "Could not create printer name");378return NULL;379}380const char *filename;381int i;382jobjectArray sizeArray = NULL;383jfloat *dims;384385// NOTE: cupsGetPPD returns a pointer to a filename of a temporary file.386// unlink() must be called to remove the file after using it.387filename = j2d_cupsGetPPD(name);388(*env)->ReleaseStringUTFChars(env, printer, name);389CHECK_NULL_RETURN(filename, NULL);390if ((ppd = j2d_ppdOpenFile(filename)) == NULL) {391unlink(filename);392DPRINTF("unable to open PPD %s\n", filename)393return NULL;394}395option = j2d_ppdFindOption(ppd, "PageSize");396if (option != NULL && option->num_choices > 0) {397// create array of dimensions - (num_choices * 6)398//to cover length & height399DPRINTF( "CUPSfuncs::option->num_choices %d\n", option->num_choices)400// +1 is for storing the default media index401sizeArray = (*env)->NewFloatArray(env, option->num_choices*6+1);402if (sizeArray == NULL) {403unlink(filename);404j2d_ppdClose(ppd);405DPRINTF("CUPSfuncs::bad alloc new float array\n", "")406(*env)->ExceptionClear(env);407JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");408return NULL;409}410411dims = (*env)->GetFloatArrayElements(env, sizeArray, NULL);412if (dims == NULL) {413unlink(filename);414j2d_ppdClose(ppd);415(*env)->ExceptionClear(env);416JNU_ThrowOutOfMemoryError(env, "Could not create printer name");417return NULL;418}419for (i = 0; i<option->num_choices; i++) {420choice = (option->choices)+i;421// get the index of the default page422if (!strcmp(choice->choice, option->defchoice)) {423dims[option->num_choices*6] = (float)i;424}425size = j2d_ppdPageSize(ppd, choice->choice);426if (size != NULL) {427// paper width and height428dims[i*6] = size->width;429dims[(i*6)+1] = size->length;430// paper printable area431dims[(i*6)+2] = size->left;432dims[(i*6)+3] = size->top;433dims[(i*6)+4] = size->right;434dims[(i*6)+5] = size->bottom;435}436}437438(*env)->ReleaseFloatArrayElements(env, sizeArray, dims, 0);439}440441j2d_ppdClose(ppd);442unlink(filename);443return sizeArray;444}445446447