Win32PrintServiceLookup crystalreport水晶报表 linux下报错

水晶报表rpt转pdf
SAP提供的SDK在 windows下正常, 但在linux下的tomcat里报错

Caused by: com.crystaldecisions.sdk.occa.report.lib.ReportSDKException: javax.print.PrintServiceLookup: Provider sun.print.Win32PrintServiceLookup not found

Caused by: com.crystaldecisions.sdk.occa.report.lib.ReportSDKException: javax.print.PrintServiceLookup: Provider sun.print.Win32PrintServiceLookup could not be instantiated

Caused by: java.lang.UnsatisfiedLinkError: Native Library /usr/java/jdk1.8.0_231/jre/lib/amd64/libawt.so already loaded in another classloader

第二次和之后会报
com.crystaldecisions.reports.common.m 无法初始化, 这个不是根本原因
根本原因是上面调用PrintServiceLookup 出错

原因是Win32PrintServiceLookup查找本地默认打印机时 有这么行代码

static
  {
    AccessController.doPrivileged(new LoadLibraryAction("awt"));
  }

这也是为啥重启之后有问题, 热部署后没问题, 是因为 热部署后classloader啥的没搞明白

同个本地library的loadlibrary是不能被多个classloader调用的
虽然每个classloader都放jar, 还是解决不了,
只能重写
代码如下

/***
 * overwrite by duqiang.wang
 * for crystal report .rpt to .pdf
 */


    /* Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    *
    * This code is free software; you can redistribute it and/or modify it
    * under the terms of the GNU General Public License version 2 only, as
    * published by the Free Software Foundation.  Oracle designates this
    * particular file as subject to the "Classpath" exception as provided
    * by Oracle in the LICENSE file that accompanied this code.
    *
    * This code is distributed in the hope that it will be useful, but WITHOUT
    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    * version 2 for more details (a copy is included in the LICENSE file that
    * accompanied this code).
    *
    * You should have received a copy of the GNU General Public License version
    * 2 along with this work; if not, write to the Free Software Foundation,
    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    *
    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    * or visit www.oracle.com if you need additional information or have any
    * questions.
    */
   
   package sun.print;
   
   import java.io.BufferedReader;
   import java.io.InputStream;
   import java.io.InputStreamReader;
   import java.io.IOException;
   import java.util.ArrayList;
   import java.security.AccessController;
   import java.security.PrivilegedActionException;
   import java.security.PrivilegedExceptionAction;
   import javax.print.DocFlavor;
   import javax.print.MultiDocPrintService;
   import javax.print.PrintService;
   import javax.print.PrintServiceLookup;
   import javax.print.attribute.Attribute;
   import javax.print.attribute.AttributeSet;
   import javax.print.attribute.HashPrintRequestAttributeSet;
   import javax.print.attribute.HashPrintServiceAttributeSet;
   import javax.print.attribute.PrintRequestAttribute;
   import javax.print.attribute.PrintRequestAttributeSet;
   import javax.print.attribute.PrintServiceAttribute;
   import javax.print.attribute.PrintServiceAttributeSet;
   import javax.print.attribute.standard.PrinterName;
   
   public class Win32PrintServiceLookup extends PrintServiceLookup {
    
    
   
       private String defaultPrinter;
       private PrintService defaultPrintService;
       private String[] printers; /* excludes the default printer */
       private PrintService[] printServices; /* includes the default printer */
   
       /*
       static {
           java.security.AccessController.doPrivileged(
                       new sun.security.action.LoadLibraryAction("awt"));
       }*/
   
       /* The singleton win32 print lookup service.
        * Code that is aware of this field and wants to use it must first
        * see if its null, and if so instantiate it by calling a method such as
        * javax.print.PrintServiceLookup.defaultPrintService() so that the
        * same instance is stored there.
        */
       private static Win32PrintServiceLookup win32PrintLUS;
   
       /* Think carefully before calling this. Preferably don't call it. */
       public static Win32PrintServiceLookup getWin32PrintLUS() {
    
    
           if (win32PrintLUS == null) {
    
    
               /* This call is internally synchronized.
                * When it returns an instance of this class will have
                * been instantiated - else there's a JDK internal error.
                */
               PrintServiceLookup.lookupDefaultPrintService();
           }
           return win32PrintLUS;
       }
   
       public Win32PrintServiceLookup() {
    
    
    
       }
   
       /* Want the PrintService which is default print service to have
        * equality of reference with the equivalent in list of print services
        * This isn't required by the API and there's a risk doing this will
        * lead people to assume its guaranteed.
        */
       public synchronized PrintService[] getPrintServices() {
    
    
           SecurityManager security = System.getSecurityManager();
           if (security != null) {
    
    
               security.checkPrintJobAccess();
           }
           if (printServices == null) {
    
    
               refreshServices();
           }
           return printServices;
       }
   
       private synchronized void refreshServices() {
    
    
    	   return;
       }
   
   
       public synchronized PrintService getPrintServiceByName(String name) {
    
    
   
           if (name == null || name.equals("")) {
    
    
               return null;
           } else {
    
    
               /* getPrintServices() is now very fast. */
               PrintService[] printServices = getPrintServices();
               for (int i=0; i<printServices.length; i++) {
    
    
                   if (printServices[i].getName().equals(name)) {
    
    
                       return printServices[i];
                   }
               }
               return null;
           }
       }
   
       boolean matchingService(PrintService service,
                               PrintServiceAttributeSet serviceSet) {
    
    
           if (serviceSet != null) {
    
    
               Attribute [] attrs =  serviceSet.toArray();
               Attribute serviceAttr;
               for (int i=0; i<attrs.length; i++) {
    
    
                   serviceAttr
                       = service.getAttribute((Class<PrintServiceAttribute>)attrs[i].getCategory());
                   if (serviceAttr == null || !serviceAttr.equals(attrs[i])) {
    
    
                       return false;
                   }
               }
           }
           return true;
       }
   
       public PrintService[] getPrintServices(DocFlavor flavor,
                                              AttributeSet attributes) {
    
    
   
           SecurityManager security = System.getSecurityManager();
           if (security != null) {
    
    
             security.checkPrintJobAccess();
           }
           PrintRequestAttributeSet requestSet = null;
           PrintServiceAttributeSet serviceSet = null;
   
           if (attributes != null && !attributes.isEmpty()) {
    
    
   
               requestSet = new HashPrintRequestAttributeSet();
               serviceSet = new HashPrintServiceAttributeSet();
   
               Attribute[] attrs = attributes.toArray();
               for (int i=0; i<attrs.length; i++) {
    
    
                   if (attrs[i] instanceof PrintRequestAttribute) {
    
    
                       requestSet.add(attrs[i]);
                   } else if (attrs[i] instanceof PrintServiceAttribute) {
    
    
                       serviceSet.add(attrs[i]);
                   }
               }
           }
   
           /*
            * Special case: If client is asking for a particular printer
            * (by name) then we can save time by getting just that service
            * to check against the rest of the specified attributes.
            */
           PrintService[] services = null;
           if (serviceSet != null && serviceSet.get(PrinterName.class) != null) {
    
    
               PrinterName name = (PrinterName)serviceSet.get(PrinterName.class);
               PrintService service = getPrintServiceByName(name.getValue());
               if (service == null || !matchingService(service, serviceSet)) {
    
    
                   services = new PrintService[0];
               } else {
    
    
                   services = new PrintService[1];
                   services[0] = service;
               }
           } else {
    
    
               services = getPrintServices();
           }
   
           if (services.length == 0) {
    
    
               return services;
           } else {
    
    
               ArrayList matchingServices = new ArrayList();
               for (int i=0; i<services.length; i++) {
    
    
                   try {
    
    
                       if (services[i].
                           getUnsupportedAttributes(flavor, requestSet) == null) {
    
    
                           matchingServices.add(services[i]);
                       }
                   } catch (IllegalArgumentException e) {
    
    
                   }
               }
               services = new PrintService[matchingServices.size()];
               return (PrintService[])matchingServices.toArray(services);
           }
       }
   
       /*
        * return empty array as don't support multi docs
        */
       public MultiDocPrintService[]
           getMultiDocPrintServices(DocFlavor[] flavors,
                                    AttributeSet attributes) {
    
    
           SecurityManager security = System.getSecurityManager();
           if (security != null) {
    
    
             security.checkPrintJobAccess();
           }
           return new MultiDocPrintService[0];
       }
   
   
       public synchronized PrintService getDefaultPrintService() {
    
    
           return null; 
       }
    
    
   }

生成jar后, 想要被重写的jar的名字要大于生成的jar,
同包同名的class加载后是不会再加载的, 达到重写的目的
在这里插入图片描述

参考

https://blog.csdn.net/jayjjb/article/details/7963937
https://my.oschina.net/u/2326085/blog/391294
https://blog.csdn.net/Yaqing_568/article/details/79700281
https://blog.csdn.net/JBossWeek/article/details/1777088
https://www.cnblogs.com/matrixlei/p/4677327.html
https://blog.csdn.net/briblue/article/details/54973413
https://blog.csdn.net/ld422586546/article/details/14522721

猜你喜欢

转载自blog.csdn.net/wangduqiang747/article/details/109093781
今日推荐