2015-05-18 3 views
1

Я использую один из ee-jars в моем проекте Android. Он использует ResourceBundle.getBundle(String path) для i18n. Поскольку ресурсы раздели в баночку и .apk не содержит ресурсы и я получаю исключение:Где разместить ресурсы в Android для ResourceBundle.getBundle (String path)?

java.util.MissingResourceException: Can't find resource for bundle 'org/apache/xml/security/resource/xmlsecurity_en_US', key '' 
     at java.util.ResourceBundle.missingResourceException(ResourceBundle.java:239) 
     at java.util.ResourceBundle.getBundle(ResourceBundle.java:231) 
     at org.apache.wss4j.common.crypto.WSS4JResourceBundle.<init>(WSS4JResourceBundle.java:54) 
     at org.apache.wss4j.common.crypto.WSProviderConfig.initializeResourceBundles(WSProviderConfig.java:199) 
     at org.apache.wss4j.common.crypto.WSProviderConfig.init(WSProviderConfig.java:65) 
     at org.apache.wss4j.dom.WSSConfig.init(WSSConfig.java:428) 
     at org.apache.wss4j.dom.WSSConfig.getNewInstance(WSSConfig.java:435) 
     at org.apache.wss4j.dom.WSSecurityEngine.getWssConfig(WSSecurityEngine.java:148) 
     at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessageInternal(WSS4JInInterceptor.java:215) 
     at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:190) 
     at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:96) 
     at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307) 
     at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:122) 
     at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:243) 
     at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:261) 
     at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:70) 
     at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1088) 
     at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1024) 
     at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135) 
     at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255) 
     at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116) 
     at org.eclipse.jetty.server.Server.handle(Server.java:370) 
     at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494) 
     at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:982) 
     at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1043) 
     at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:865) 
     at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240) 
     at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82) 
     at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:696) 
     at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:53) 
     at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608) 
     at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543) 
     at java.lang.Thread.run(Thread.java:841) 

Что я могу сделать для того, чтобы исправить это? Моя идея - получить ресурсы из jar и поместить их в папку ресурсов в проекте Android. Где это место? Android поддерживает ResourceBundle.getBundle(String path) (reference), но не написано, где разместить ресурсы.

ответ

0

мне пришлось:

  1. ввести загрузчик ресурсов интерфейс (WSS4JResourceBundle.ResourceBundleLoader)
  2. ввести статическую переменную загрузчика ресурса для загрузки ресурсов (public static ResourceBundleLoader sharedLoader)
  3. заменить загрузки ресурса с помощью ResourceBundle.getBundle методы статического вара вызова (wss4jSecResourceBundle = sharedLoader.getBundle("messages.wss4j_errors"); fe)
  4. создать по умолчанию (DefaultResourceBundleLoader) и андроид (AndroidResourceBundleLoader)
  5. Упаковать ресурсы для андроида проекта assets FOLDER
  6. инъекционные андроид осущ вместо неплатежа один на приложение запуска (WSS4JResourceBundle.sharedLoader = new AndroidResourceBundleLoader(ctx, "wss4j/");)

модифицированном WSS4JResourceBundle:

package org.apache.wss4j.common.crypto; 

import java.util.Enumeration; 
import java.util.Locale; 
import java.util.MissingResourceException; 
import java.util.ResourceBundle; 

import org.apache.xml.security.utils.Constants; 
import org.apache.xml.security.utils.I18n; 

/** 
* ResourceBundle for WSS4J 
*/ 
public class WSS4JResourceBundle extends ResourceBundle { 

    /** 
    * Loader API 
    */ 
    public interface ResourceBundleLoader { 
     ResourceBundle getBundle(String path); 
     ResourceBundle getBundle(String baseName, Locale locale, ClassLoader loader); 
    } 

    // default 
    public static ResourceBundleLoader sharedLoader = new DefaultResourceBundleLoader(); 

    /** 
    * Default IMPL 
    */ 
    public static class DefaultResourceBundleLoader implements ResourceBundleLoader { 
     @Override 
     public ResourceBundle getBundle(String path) { 
      return ResourceBundle.getBundle(path); 
     } 

     @Override 
     public ResourceBundle getBundle(String baseName, Locale locale, ClassLoader loader) { 
      return ResourceBundle.getBundle(baseName, locale, loader); 
     } 
    } 

    private static final org.slf4j.Logger LOG = 
     org.slf4j.LoggerFactory.getLogger(WSS4JResourceBundle.class); 

    private final ResourceBundle wss4jSecResourceBundle; 
    private final ResourceBundle xmlSecResourceBundle; 

    public WSS4JResourceBundle() { 
     wss4jSecResourceBundle = sharedLoader.getBundle("messages.wss4j_errors"); 

     ResourceBundle tmpResourceBundle; 
     try { 
      tmpResourceBundle = sharedLoader.getBundle(
         Constants.exceptionMessagesResourceBundleBase, 
         Locale.getDefault(), 
         I18n.class.getClassLoader()); 
     } catch (MissingResourceException ex) { 
      // Using a Locale of which there is no properties file. 
      LOG.debug(ex.getMessage()); 
      // Default to en/US 
      tmpResourceBundle = 
        sharedLoader.getBundle(Constants.exceptionMessagesResourceBundleBase, 
             new Locale("en", "US"), I18n.class.getClassLoader()); 
     } 
     xmlSecResourceBundle = tmpResourceBundle; 
    } 

    @Override 
    protected Object handleGetObject(String key) { 
     Object value = null; 
     try { 
      value = wss4jSecResourceBundle.getObject(key); 
     } catch (MissingResourceException e) { 
      try { 
       value = xmlSecResourceBundle.getObject(key); 
      } catch (MissingResourceException ex) { //NOPMD 
       //ignore 
      } 
     } 
     return value; 
    } 

    @Override 
    public Enumeration<String> getKeys() { 
     throw new UnsupportedOperationException("getKeys not supported"); 
    } 

} 

новый AndroidResourceBundleLoader:

package org.apache.wss4j.common.crypto; 

import android.content.Context; 
import android.content.res.AssetManager; 
import com.splinex.streaming.Log; 

import java.io.IOException; 
import java.io.InputStream; 
import java.util.Locale; 
import java.util.PropertyResourceBundle; 
import java.util.ResourceBundle; 

public class AndroidResourceBundleLoader implements WSS4JResourceBundle.ResourceBundleLoader { 

    private static final String TAG = AndroidResourceBundleLoader.class.getSimpleName(); 

    private String prefix; 
    private AssetManager manager; 

    public AndroidResourceBundleLoader(Context context, String prefix) { 
     manager = context.getAssets(); 
     this.prefix = prefix; 
    } 

    @Override 
    public ResourceBundle getBundle(String path) { 
     try { 
      String fullPath = prefix + path.replace(".", "/") + ".properties"; 
      return new PropertyResourceBundle(manager.open(fullPath)); 
     } catch (IOException e) { 
      android.util.Log.e(TAG, "Failed to load " + path, e); 
      throw new RuntimeException(e); 
     } 
    } 

    @Override 
    public ResourceBundle getBundle(String path, Locale locale, ClassLoader classLoader) { 
     return getBundle(path + "_" + locale.getLanguage()); 
    } 
} 

INJECT андроид осущ, как это:

WSS4JResourceBundle.sharedLoader = new AndroidResourceBundleLoader(ctx, "wss4j/"); 
Смежные вопросы