package com.idega.slide.business; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectInputStream.GetField; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TreeMap; import java.util.logging.Level; import java.util.logging.Logger; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import com.idega.business.IBOLookup; import com.idega.business.IBOLookupException; import com.idega.core.file.util.MimeTypeUtil; import com.idega.idegaweb.IWMainApplication; import com.idega.idegaweb.IWResourceBundle; import com.idega.util.CoreConstants; import com.idega.util.IOUtil; import com.idega.util.SortedProperties; import com.idega.util.StringUtil; import com.idega.util.messages.MessageResource; import com.idega.util.messages.MessageResourceImportanceLevel; /** * * * @author <a href="anton@idega.com">Anton Makarov</a> * @version Revision: 1.0 * * Last modified: Oct 15, 2008 by Author: Anton * */ @Service @Scope(BeanDefinition.SCOPE_PROTOTYPE) public class IWSlideResourceBundle extends IWResourceBundle implements MessageResource, Serializable { private static final long serialVersionUID = -4849846267697372361L; private static final Logger LOGGER = Logger.getLogger(IWSlideResourceBundle.class.getName()); private static final String LOCALISATION_PATH = "/files/cms/bundles/", NON_BUNDLE_LOCALISATION_FILE_NAME = "Localizable_no_bundle", BUNDLE_LOCALISATION_FILE_NAME = "Localizable", NON_BUNDLE_LOCALISATION_FILE_EXTENSION = ".strings", RESOURCE_IDENTIFIER = "slide_resource"; public IWSlideResourceBundle() throws IOException { super(); } @Override protected void initProperities() { setIdentifier(RESOURCE_IDENTIFIER); setLevel(MessageResourceImportanceLevel.FIRST_ORDER); setAutoInsert(true); } @Override public void initialize(String bundleIdentifier, Locale locale) throws IOException { setLocale(locale); setBundleIdentifier(bundleIdentifier); InputStream slideSourceStream = getResourceInputStream(getLocalizableFilePath()); Properties localizationProps = new Properties(); if (slideSourceStream != null) { localizationProps.load(slideSourceStream); } @SuppressWarnings({ "unchecked", "rawtypes" }) Map<String, String> props = new TreeMap(localizationProps); setLookup(props); IOUtil.closeInputStream(slideSourceStream); } protected InputStream getResourceInputStream(String resourcePath) { return getResourceInputStream(resourcePath, Boolean.TRUE); } private InputStream getResourceInputStream(String resourcePath, boolean createIfNotFound) { try { IWSlideService service = getIWSlideService(); if (createIfNotFound && !service.getExistence(resourcePath)) { createEmptyFile(resourcePath); } return service.getInputStream(resourcePath); } catch (Exception e) { LOGGER.log(Level.WARNING, "Error getting InputStream for: " + resourcePath, e); } return null; } @Override public synchronized void storeState() { Properties props = new SortedProperties(); ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); OutputStream out = null; Map<String, String> lookup = getLookup(); if (lookup != null) { Map<String, String> copy = new HashMap<String, String>(lookup); for (Iterator<String> iter = copy.keySet().iterator(); iter.hasNext();) { String key = iter.next(); if (key != null) { Object value = copy.get(key); if (value != null) { props.put(key, value); } } } try { props.store(byteStream, CoreConstants.EMPTY); } catch (IOException e) { LOGGER.log(Level.WARNING, "Can't store properties to ByteArrayOutputStream", e); } } InputStream stream = getResourceInputStream(getLocalizableFilePath()); if (stream == null) { LOGGER.warning("Can't save localization file '" + getLocalizableFilePath() + "' to repository - unable to create empty file!"); return; } else { IOUtil.close(stream); } try { IWSlideService service = getIWSlideService(); out = service.getOutputStream(getLocalizableFilePath()); out.write(byteStream.toByteArray()); } catch (Exception e) { LOGGER.log(Level.WARNING, "Can't save localization file '" + getLocalizableFilePath() + "' to repository", e); throw new RuntimeException(e); } finally { IOUtil.close(out); IOUtil.close(byteStream); } } @Override public String getLocalizedString(String key) { Object returnObj = getLookup().get(key); if (returnObj != null && !"null".equals(returnObj)) { return String.valueOf(returnObj); } else { return null; } } @Override public void setString(String key, String value) { getLookup().put(key, value); } /** * @return <code>true</code> - if the value presents in slide bundle. <code>false</code> - in other case * */ @Override protected boolean checkBundleLocalizedString(String key, String value) { return !StringUtil.isEmpty((String) handleGetObject(key)); } private String getLocalizableFilePath() { return getLocalisableFolderPath() + getLocalisableFileName(); } private String getLocalisableFolderPath() { StringBuffer filePath = new StringBuffer(LOCALISATION_PATH); if(!StringUtil.isEmpty(getBundleIdentifier()) && !MessageResource.NO_BUNDLE.equals(getBundleIdentifier())) { filePath.append(getBundleIdentifier()).append(CoreConstants.SLASH); } return filePath.toString(); } private String getLocalisableFileName() { StringBuffer fileName = new StringBuffer(); if(StringUtil.isEmpty(getBundleIdentifier()) || MessageResource.NO_BUNDLE.equals(getBundleIdentifier())) { fileName.append(NON_BUNDLE_LOCALISATION_FILE_NAME) .append(CoreConstants.UNDER).append(getLocale()) .append(NON_BUNDLE_LOCALISATION_FILE_EXTENSION); } else { fileName.append(BUNDLE_LOCALISATION_FILE_NAME) .append(CoreConstants.UNDER).append(getLocale()) .append(NON_BUNDLE_LOCALISATION_FILE_EXTENSION); } return fileName.toString(); } private IWSlideService getIWSlideService() throws IBOLookupException { try { return IBOLookup.getServiceInstance(IWMainApplication.getDefaultIWApplicationContext(), IWSlideService.class); } catch (IBOLookupException e) { LOGGER.log(Level.SEVERE, "Error getting IWSlideService"); throw e; } } private boolean createEmptyFile(String path) { try { IWSlideService slideService = getIWSlideService(); slideService.uploadFileAndCreateFoldersFromStringAsRoot(getLocalisableFolderPath(), getLocalisableFileName(), CoreConstants.EMPTY, MimeTypeUtil.MIME_TYPE_TEXT_PLAIN, false); } catch (Exception e) { return false; } return true; } /** * @param key - message key * @return object that was found in resource or set to it, null - if there are no values with specified key */ @Override public Object getMessage(Object key) { return getLocalizedString(String.valueOf(key)); } /** * @return object that was set or null if there was a failure setting object */ @Override public Object setMessage(Object key, Object value) { getLookup().put(String.valueOf(key), String.valueOf(value)); storeState(); return value; } @Override public void setMessages(Map<Object, Object> values) { for (Object key : values.keySet()) { setString(String.valueOf(key), String.valueOf(values.get(key))); } storeState(); } @SuppressWarnings("unchecked") @Override public Set<String> getAllLocalisedKeys() { return getLookup().keySet(); } @Override public void removeMessage(Object key) { getLookup().remove(key); storeState(); } private void writeObject(ObjectOutputStream out) throws IOException { out.writeBoolean(isAutoInsert()); out.writeObject(getBundleIdentifier()); out.writeObject(getLocale()); out.writeObject(getLookup()); out.writeObject(getLevel()); return; } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { try { GetField fields = in.readFields(); fields.get("autoInsert", Boolean.TRUE); fields.get("bundleIdentifier", MessageResource.NO_BUNDLE); fields.get("locale", Locale.ENGLISH); fields.get("lookup", Collections.emptyMap()); fields.get("usagePriorityLevel", MessageResourceImportanceLevel.FIRST_ORDER); } catch (IllegalArgumentException e) { } catch (Exception e) { LOGGER.log(Level.WARNING, "Error reading objects from the stream: " + in, e); } } }