/* * $Id$ * * Copyright (c) 2000-2003 by Rodney Kinney * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package VASSAL.build.module; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Set; import java.util.zip.ZipException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import VASSAL.build.GameModule; import VASSAL.command.Command; import VASSAL.command.CommandEncoder; import VASSAL.configure.DirectoryConfigurer; import VASSAL.i18n.Resources; import VASSAL.tools.DataArchive; import VASSAL.tools.SequenceEncoder; public class ExtensionsLoader implements CommandEncoder { private static final Logger logger = LoggerFactory.getLogger(ExtensionsLoader.class); public static final String COMMAND_PREFIX = "EXT\t"; //$NON-NLS-1$ // Preferences key for the list of extensions to load public static final String SPECIFY_DIR_IN_PREFS = "specifyExtensionDirInPrefs"; //$NON-NLS-1$ public static final String EXTENSION_DIR = "extensionDIR"; //$NON-NLS-1$ protected Set<String> loadedExtensions = new HashSet<String>(); protected HashMap<String,String> loadedIds = new HashMap<String,String>(); protected ExtensionsManager extMgr; protected ExtensionsManager globalExtMgr; public void addTo(GameModule mod) { extMgr = new ExtensionsManager(mod); globalExtMgr = new ExtensionsManager("ext"); mod.addCommandEncoder(this); if ("true".equals(GlobalOptions.getInstance().getAttributeValueString(SPECIFY_DIR_IN_PREFS))) { //$NON-NLS-1$ final DirectoryConfigurer config = new DirectoryConfigurer(EXTENSION_DIR, Resources.getString("ExtensionsLoader.extensions_directory")); //$NON-NLS-1$ config.setValue((Object) null); GameModule.getGameModule().getPrefs().addOption(Resources.getString("ExtensionsLoader.extensions_tab"), config); //$NON-NLS-1$ extMgr.setExtensionsDirectory(config.getFileValue()); if (config.getFileValue() == null) { config.setValue(extMgr.getExtensionsDirectory(false).getAbsoluteFile()); } config.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { extMgr.setExtensionsDirectory((File) evt.getNewValue()); addExtensions(); } }); } addExtensions(); } protected void addExtensions() { for (File ext : globalExtMgr.getActiveExtensions()) { if (!addExtension(ext)) { globalExtMgr.setActive(ext, false); } } for (File ext : extMgr.getActiveExtensions()) { if (!addExtension(ext)) { GameModule.getGameModule().warn(Resources.getString("ExtensionsLoader.deactivating_extension",ext.getName())); extMgr.setActive(ext, false); } } } protected boolean addExtension(File extension) { logger.info("Loading extension " + extension); String extname = extension.getPath(); boolean success = loadedExtensions.contains(extname); if (!success) { try { final ModuleExtension ext = createExtension(extname); ext.build(); final String id = ext.getExtensionId(); String idMsg = ""; if (id.length() > 0) { for (String loadedId : loadedIds.keySet()) { if (loadedId.equals(id)) { idMsg = Resources.getString("ExtensionsLoader.id_conflict", extension.getName(), id, loadedIds.get(id)); } } loadedIds.put(id, extname); } final String msg = getLoadedMessage(ext.getName(), ext.getVersion()); loadedExtensions.add(extname); GameModule.getGameModule().warn(msg); logger.info(msg); if (idMsg.length() > 0) { GameModule.getGameModule().warn(idMsg); logger.info(idMsg); } success = true; } catch (ZipException e) { // Not a zip file. Ignore. } catch (IOException e) { reportBuildError(e, extension.getName()); } catch (LoadExtensionException e) { reportBuildError(e, extension.getName()); } } return success; } protected ModuleExtension createExtension(String extname) throws ZipException, IOException { return new ModuleExtension(new DataArchive(extname)); } protected String getLoadedMessage(String name, String version) { return Resources.getString("ExtensionsLoader.extension_loaded", name, version); //$NON-NLS-1$ } private void reportBuildError(Exception e, String name) { String msg = e.getMessage(); if (msg == null || msg.length() == 0) { msg = e.getClass().getName(); msg = msg.substring(msg.lastIndexOf('.')); } GameModule.getGameModule().warn(getErrorMessage(name , msg)); //$NON-NLS-1$ } protected String getErrorMessage(String name, String msg) { return Resources.getString("ExtensionsLoader.unable_to_load", name , msg); } public Command decode(String command) { Command c = null; if (command.startsWith(COMMAND_PREFIX)) { SequenceEncoder.Decoder st = new SequenceEncoder.Decoder(command.substring(COMMAND_PREFIX.length()), '\t'); c = new ModuleExtension.RegCmd(st.nextToken(), st.nextToken()); } return c; } public String encode(Command c) { String s = null; if (c instanceof ModuleExtension.RegCmd) { ModuleExtension.RegCmd cmd = (ModuleExtension.RegCmd) c; SequenceEncoder se = new SequenceEncoder('\t'); se.append(cmd.getName()).append(cmd.getVersion()); s = COMMAND_PREFIX + se.getValue(); } return s; } public static class LoadExtensionException extends RuntimeException { private static final long serialVersionUID = 1L; public LoadExtensionException() { super(); } public LoadExtensionException(String message, Throwable cause) { super(message, cause); } public LoadExtensionException(String message) { super(message); } public LoadExtensionException(Throwable cause) { super(cause); } } }