/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.resources;
import java.awt.image.*;
import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
import javax.imageio.*;
import javax.swing.*;
import net.java.sip.communicator.service.resources.*;
import net.java.sip.communicator.util.*;
import org.osgi.framework.*;
/**
* A default implementation of the ResourceManagementService.
*
* @author Damian Minkov
* @author Yana Stamcheva
* @author Lubomir Marinov
*/
public class ResourceManagementServiceImpl
implements ResourceManagementService,
ServiceListener
{
private static Logger logger =
Logger.getLogger(ResourceManagementServiceImpl.class);
private Map<String, String> colorResources;
private ResourcePack colorPack = null;
private Map<String, String> imageResources;
private ResourcePack imagePack = null;
private Map<String, String> languageResources;
private LanguagePack languagePack = null;
/**
* The {@link Locale} of <code>languageResources</code> so that the caching
* of the latter can be used when a string with the same <code>Locale</code>
* is requested.
*/
private Locale languageLocale;
private Map<String, String> settingsResources;
private ResourcePack settingsPack = null;
private Map<String, String> soundResources;
private ResourcePack soundPack = null;
/**
* Initializes already registered default resource packs.
*/
ResourceManagementServiceImpl()
{
ResourceManagementActivator.bundleContext.addServiceListener(this);
colorPack =
getDefaultResourcePack(ColorPack.class.getName(),
ColorPack.RESOURCE_NAME_DEFAULT_VALUE);
if (colorPack != null)
colorResources = getResources(colorPack);
imagePack =
getDefaultResourcePack(ImagePack.class.getName(),
ImagePack.RESOURCE_NAME_DEFAULT_VALUE);
if (imagePack != null)
imageResources = getResources(imagePack);
languagePack =
(LanguagePack) getDefaultResourcePack(LanguagePack.class.getName(),
LanguagePack.RESOURCE_NAME_DEFAULT_VALUE);
if (languagePack != null)
{
languageLocale = Locale.getDefault();
languageResources = languagePack.getResources(languageLocale);
}
settingsPack =
getDefaultResourcePack(SettingsPack.class.getName(),
SettingsPack.RESOURCE_NAME_DEFAULT_VALUE);
if (settingsPack != null)
settingsResources = getResources(settingsPack);
soundPack =
getDefaultResourcePack(SoundPack.class.getName(),
SoundPack.RESOURCE_NAME_DEFAULT_VALUE);
if (soundPack != null)
soundResources = getResources(soundPack);
}
/**
* Searches for the <tt>ResourcePack</tt> corresponding to the given
* <tt>className</tt> and <tt></tt>.
* @param className The name of the resource class.
* @param typeName The name of the type we're looking for.
* For example: RESOURCE_NAME_DEFAULT_VALUE
* @return the <tt>ResourcePack</tt> corresponding to the given
* <tt>className</tt> and <tt></tt>.
*/
private ResourcePack getDefaultResourcePack(String className,
String typeName)
{
ServiceReference[] serRefs = null;
String osgiFilter =
"(" + ResourcePack.RESOURCE_NAME + "=" + typeName + ")";
try
{
serRefs = ResourceManagementActivator
.bundleContext.getServiceReferences(
className,
osgiFilter);
}
catch (InvalidSyntaxException exc)
{
logger.error("Could not obtain resource packs reference.", exc);
}
if ((serRefs != null) && (serRefs.length > 0))
{
return (ResourcePack)
ResourceManagementActivator.bundleContext.getService(serRefs[0]);
}
return null;
}
/**
* Returns the <tt>Map</tt> of (key, value) pairs contained in the given
* resource pack.
*
* @param resourcePack The <tt>ResourcePack</tt> from which we're obtaining
* the resources.
* @return the <tt>Map</tt> of (key, value) pairs contained in the given
* resource pack.
*/
private Map<String, String> getResources(ResourcePack resourcePack)
{
return resourcePack.getResources();
}
/**
* Handles all <tt>ServiceEvent</tt>s corresponding to <tt>ResourcePack</tt>
* being registered or unregistered.
*/
public void serviceChanged(ServiceEvent event)
{
Object sService = ResourceManagementActivator.bundleContext.getService(
event.getServiceReference());
if (!(sService instanceof ResourcePack))
{
return;
}
ResourcePack resourcePack = (ResourcePack) sService;
if (event.getType() == ServiceEvent.REGISTERED)
{
logger.info("Resource registered " + resourcePack);
Map<String, String> resources = getResources(resourcePack);
if(resourcePack instanceof ColorPack && colorPack == null)
{
colorPack = resourcePack;
colorResources = resources;
}
else if(resourcePack instanceof ImagePack && imagePack == null)
{
imagePack = resourcePack;
imageResources = resources;
}
else if(resourcePack instanceof LanguagePack && languagePack == null)
{
languagePack = (LanguagePack) resourcePack;
languageLocale = Locale.getDefault();
languageResources = resources;
}
else if(resourcePack instanceof SettingsPack && settingsPack == null)
{
settingsPack = resourcePack;
settingsResources = resources;
}
else if(resourcePack instanceof SoundPack && soundPack == null)
{
soundPack = resourcePack;
soundResources = resources;
}
}
else if (event.getType() == ServiceEvent.UNREGISTERING)
{
if(resourcePack instanceof ColorPack
&& colorPack.equals(resourcePack))
{
colorPack =
getDefaultResourcePack(ColorPack.class.getName(),
ColorPack.RESOURCE_NAME_DEFAULT_VALUE);
if (colorPack != null)
colorResources = getResources(colorPack);
}
else if(resourcePack instanceof ImagePack
&& imagePack.equals(resourcePack))
{
imagePack =
getDefaultResourcePack(ImagePack.class.getName(),
ImagePack.RESOURCE_NAME_DEFAULT_VALUE);
if (imagePack != null)
imageResources = getResources(imagePack);
}
else if(resourcePack instanceof LanguagePack
&& languagePack.equals(resourcePack))
{
languagePack =
(LanguagePack) getDefaultResourcePack(
LanguagePack.class.getName(),
LanguagePack.RESOURCE_NAME_DEFAULT_VALUE);
}
else if(resourcePack instanceof SettingsPack
&& settingsPack.equals(resourcePack))
{
settingsPack =
getDefaultResourcePack(SettingsPack.class.getName(),
SettingsPack.RESOURCE_NAME_DEFAULT_VALUE);
if (settingsPack != null)
settingsResources = getResources(settingsPack);
}
else if(resourcePack instanceof SoundPack
&& soundPack.equals(resourcePack))
{
soundPack =
getDefaultResourcePack(SoundPack.class.getName(),
SoundPack.RESOURCE_NAME_DEFAULT_VALUE);
if (soundPack != null)
soundResources = getResources(soundPack);
}
}
}
/**
* Returns the int representation of the color corresponding to the
* given key.
*
* @param key The key of the color in the colors properties file.
* @return the int representation of the color corresponding to the
* given key.
*/
public int getColor(String key)
{
String res = colorResources.get(key);
if(res == null)
{
logger.error("Missing color resource for key: " + key);
return 0xFFFFFF;
}
else
return Integer.parseInt(res, 16);
}
/**
* Returns the string representation of the color corresponding to the
* given key.
*
* @param key The key of the color in the colors properties file.
* @return the string representation of the color corresponding to the
* given key.
*/
public String getColorString(String key)
{
String res = colorResources.get(key);
if(res == null)
{
logger.error("Missing color resource for key: " + key);
return "0xFFFFFF";
}
else
return res;
}
/**
* Returns the <tt>InputStream</tt> of the image corresponding to the given
* path.
*
* @param path The path to the image file.
* @return the <tt>InputStream</tt> of the image corresponding to the given
* path.
*/
public InputStream getImageInputStreamForPath(String path)
{
return imagePack.getClass().getClassLoader().getResourceAsStream(path);
}
/**
* Returns the <tt>InputStream</tt> of the image corresponding to the given
* key.
*
* @param streamKey The identifier of the image in the resource properties
* file.
* @return the <tt>InputStream</tt> of the image corresponding to the given
* key.
*/
public InputStream getImageInputStream(String streamKey)
{
String path = imageResources.get(streamKey);
if (path == null || path.length() == 0)
{
logger.warn("Missing resource for key: " + streamKey);
return null;
}
return getImageInputStreamForPath(path);
}
/**
* Returns the <tt>URL</tt> of the image corresponding to the given key.
*
* @param urlKey The identifier of the image in the resource properties file.
* @return the <tt>URL</tt> of the image corresponding to the given key
*/
public URL getImageURL(String urlKey)
{
String path = imageResources.get(urlKey);
if (path == null || path.length() == 0)
{
logger.info("Missing resource for key: " + urlKey);
return null;
}
return getImageURLForPath(path);
}
/**
* Returns the image path corresponding to the given key.
*
* @param key The identifier of the image in the resource properties file.
* @return the image path corresponding to the given key.
*/
public String getImagePath(String key)
{
return imageResources.get(key);
}
/**
* Returns the <tt>URL</tt> of the image corresponding to the given path.
*
* @param path The path to the given image file.
* @return the <tt>URL</tt> of the image corresponding to the given path.
*/
public URL getImageURLForPath(String path)
{
return imagePack.getClass().getClassLoader().getResource(path);
}
// Language pack methods
/**
* Returns an internationalized string corresponding to the given key.
*
* @param key The identifier of the string in the resources properties file.
* @return An internationalized string corresponding to the given key.
*/
public String getI18NString(String key)
{
return getI18NString(key, Locale.getDefault());
}
/**
* Returns an internationalized string corresponding to the given key.
*
* @param key The identifier of the string in the resources properties file.
* @param locale The locale.
* @return An internationalized string corresponding to the given key and
* given locale.
*/
public String getI18NString(String key, Locale locale)
{
return getI18NString(key, null, locale);
}
/**
* Returns an internationalized string corresponding to the given key.
*
* @param key The identifier of the string.
* @return An internationalized string corresponding to the given key.
*/
public String getI18NString(String key, String[] params)
{
return getI18NString(key, params, Locale.getDefault());
}
/**
* Returns an internationalized string corresponding to the given key.
*
* @param key The identifier of the string in the resources properties
* file.
* @param locale The locale.
* @return An internationalized string corresponding to the given key.
*/
public String getI18NString(String key, String[] params, Locale locale)
{
Map<String, String> stringResources;
if ((locale != null) && locale.equals(languageLocale))
{
stringResources = languageResources;
}
else
{
stringResources = languagePack.getResources(locale);
}
String resourceString = stringResources.get(key);
if (resourceString == null)
{
logger.warn("Missing resource for key: " + key);
return '!' + key + '!';
}
int mnemonicIndex = resourceString.indexOf('&');
if (mnemonicIndex == 0
|| (mnemonicIndex > 0
&& resourceString.charAt(mnemonicIndex - 1) != '\\'))
{
String firstPart = resourceString.substring(0, mnemonicIndex);
String secondPart = resourceString.substring(mnemonicIndex + 1);
resourceString = firstPart.concat(secondPart);
}
if (resourceString.indexOf('\\') > -1)
{
resourceString = resourceString.replaceAll("\\\\", "");
}
if(params != null)
resourceString
= MessageFormat.format(resourceString, (Object[])params);
return resourceString;
}
/**
* Returns an internationalized string corresponding to the given key.
*
* @param key The identifier of the string in the resources properties file.
* @return An internationalized string corresponding to the given key.
*/
public char getI18nMnemonic(String key)
{
return getI18nMnemonic(key, Locale.getDefault());
}
/**
* Returns an internationalized string corresponding to the given key.
*
* @param key The identifier of the string in the resources properties file.
* @param locale The locale that we'd like to receive the result in.
* @return An internationalized string corresponding to the given key.
*/
public char getI18nMnemonic(String key, Locale locale)
{
Map<String, String> stringResources;
if ((locale != null) && locale.equals(languageLocale))
{
stringResources = languageResources;
}
else
{
stringResources = languagePack.getResources(locale);
}
String resourceString = stringResources.get(key);
if (resourceString == null)
{
logger.warn("Missing resource for key: " + key);
return 0;
}
int mnemonicIndex = resourceString.indexOf('&');
if (mnemonicIndex > -1)
{
return resourceString.charAt(mnemonicIndex + 1);
}
return 0;
}
/**
* Returns the int value of the corresponding configuration key.
*
* @param key The identifier of the string in the resources properties file.
* @return the int value of the corresponding configuration key.
*/
public String getSettingsString(String key)
{
return settingsResources.get(key);
}
/**
* Returns the int value of the corresponding configuration key.
*
* @param key The identifier of the string in the resources properties file.
* @return the int value of the corresponding configuration key.
*/
public int getSettingsInt(String key)
{
String resourceString = settingsResources.get(key);
if (resourceString == null)
{
logger.warn("Missing resource for key: " + key);
return 0;
}
return Integer.parseInt(resourceString);
}
/**
* Returns an <tt>URL</tt> from a given identifier.
*
* @param urlKey The identifier of the url.
* @return The url for the given identifier.
*/
public URL getSettingsURL(String urlKey)
{
String path = settingsResources.get(urlKey);
if (path == null || path.length() == 0)
{
logger.warn("Missing resource for key: " + urlKey);
return null;
}
return settingsPack.getClass().getClassLoader().getResource(path);
}
/**
* Returns a stream from a given identifier.
*
* @param streamKey The identifier of the stream.
* @return The stream for the given identifier.
*/
public InputStream getSettingsInputStream(String streamKey)
{
String path = settingsResources.get(streamKey);
if (path == null || path.length() == 0)
{
logger.warn("Missing resource for key: " + streamKey);
return null;
}
return settingsPack.getClass()
.getClassLoader().getResourceAsStream(path);
}
/**
* Returns the <tt>URL</tt> of the sound corresponding to the given
* property key.
*
* @return the <tt>URL</tt> of the sound corresponding to the given
* property key.
*/
public URL getSoundURL(String urlKey)
{
String path = soundResources.get(urlKey);
if (path == null || path.length() == 0)
{
logger.warn("Missing resource for key: " + urlKey);
return null;
}
return getSoundURLForPath(path);
}
/**
* Returns the <tt>URL</tt> of the sound corresponding to the given path.
*
* @return the <tt>URL</tt> of the sound corresponding to the given path.
*/
public URL getSoundURLForPath(String path)
{
return soundPack.getClass().getClassLoader().getResource(path);
}
/**
* Returns the path of the sound corresponding to the given
* property key.
*
* @return the path of the sound corresponding to the given
* property key.
*/
public String getSoundPath(String soundKey)
{
return soundResources.get(soundKey);
}
/**
* Loads an image from a given image identifier.
*
* @param imageID The identifier of the image.
* @return The image for the given identifier.
*/
public byte[] getImageInBytes(String imageID)
{
InputStream in = getImageInputStream(imageID);
if(in == null)
return null;
byte[] image = null;
try
{
image = new byte[in.available()];
in.read(image);
}
catch (IOException e)
{
logger.error("Failed to load image:" + imageID, e);
}
return image;
}
/**
* Loads an image from a given image identifier.
*
* @param imageID The identifier of the image.
* @return The image for the given identifier.
*/
public ImageIcon getImage(String imageID)
{
BufferedImage image = null;
InputStream in = getImageInputStream(imageID);
if(in == null)
return null;
try
{
image = ImageIO.read(in);
}
catch (IOException e)
{
logger.error("Failed to load image:" + imageID, e);
}
return new ImageIcon(image);
}
}