123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811 |
- /* ========================================================================
- * JCommon : a free general purpose class library for the Java(tm) platform
- * ========================================================================
- *
- * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
- *
- * Project Info: http://www.jfree.org/jcommon/index.html
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * 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 Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- *
- * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
- * in the United States and other countries.]
- *
- * -------------------
- * AbstractModule.java
- * -------------------
- * (C)opyright 2003, 2004, by Thomas Morgner and Contributors.
- *
- * Original Author: Thomas Morgner;
- * Contributor(s): David Gilbert (for Object Refinery Limited);
- *
- * $Id: AbstractModule.java,v 1.7 2008/09/10 09:16:54 mungady Exp $
- *
- * Changes
- * -------
- * 05-Jul-2003 : Initial version
- * 07-Jun-2004 : Added JCommon header (DG);
- *
- */
- package org.jfree.base.modules;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.util.ArrayList;
- import org.jfree.util.ObjectUtilities;
- /**
- * The abstract module provides a default implementation of the module interface.
- * <p>
- * The module can be specified in an external property file. The file name of this
- * specification defaults to "module.properties". This file is no real property file,
- * it follows a more complex rule set.</p>
- * <p>
- * Lines starting with '#' are considered comments.
- * Section headers start at the beginning of the line, section properties
- * are indented with at least one whitespace.</p>
- * <p>
- * The first section is always the module info and contains the basic module
- * properties like name, version and a short description.</p>
- *
- * <pre>
- * module-info:
- * name: xls-export-gui
- * producer: The JFreeReport project - www.jfree.org/jfreereport
- * description: A dialog component for the Excel table export.
- * version.major: 0
- * version.minor: 84
- * version.patchlevel: 0
- * </pre>
- * The properties name, producer and description are simple strings. They may
- * span multiple lines, but may not contain a colon (':').
- * The version properties are integer values.
- * <p>
- * This section may be followed by one or more "depends" sections. These
- * sections describe the base modules that are required to be active to make this
- * module work. The package manager will enforce this policy and will deactivate this
- * module if one of the base modules is missing.</p>
- *
- * <pre>
- * depends:
- * module: org.jfree.report.modules.output.table.xls.XLSTableModule
- * version.major: 0
- * version.minor: 84
- * </pre>
- * <p>
- * The property module references to the module implementation of the module package.
- *
- * @author Thomas Morgner
- */
- public abstract class AbstractModule extends DefaultModuleInfo implements Module
- {
- /**
- * The reader helper provides a pushback interface for the reader to read and
- * buffer complete lines.
- * @author Thomas Morgner
- */
- private static class ReaderHelper
- {
- /** The line buffer containing the last line read. */
- private String buffer;
- /** The reader from which to read the text. */
- private final BufferedReader reader;
- /**
- * Creates a new reader helper for the given buffered reader.
- *
- * @param reader the buffered reader that is the source of the text.
- */
- protected ReaderHelper(final BufferedReader reader)
- {
- this.reader = reader;
- }
- /**
- * Checks, whether the reader contains a next line. Returns false if the end
- * of the stream has been reached.
- *
- * @return true, if there is a next line to read, false otherwise.
- * @throws IOException if an error occures.
- */
- public boolean hasNext() throws IOException
- {
- if (this.buffer == null)
- {
- this.buffer = readLine();
- }
- return this.buffer != null;
- }
- /**
- * Returns the next line.
- *
- * @return the next line.
- */
- public String next()
- {
- final String line = this.buffer;
- this.buffer = null;
- return line;
- }
- /**
- * Pushes the given line back into the buffer. Only one line can be contained in
- * the buffer at one time.
- *
- * @param line the line that should be pushed back into the buffer.
- */
- public void pushBack(final String line)
- {
- this.buffer = line;
- }
- /**
- * Reads the next line skipping all comment lines.
- *
- * @return the next line, or null if no line can be read.
- * @throws IOException if an IO error occures.
- */
- protected String readLine() throws IOException
- {
- String line = this.reader.readLine();
- while (line != null && (line.length() == 0 || line.startsWith("#")))
- {
- // empty line or comment is ignored
- line = this.reader.readLine();
- }
- return line;
- }
- /**
- * Closes the reader.
- *
- * @throws IOException if an IOError occurs.
- */
- public void close() throws IOException
- {
- this.reader.close();
- }
- }
- /** The list of required modules. */
- private ModuleInfo[] requiredModules;
- /** The list of optional modules. */
- private ModuleInfo[] optionalModules;
- /** The name of the module. */
- private String name;
- /** A short description of the module. */
- private String description;
- /** The name of the module producer. */
- private String producer;
- /** The modules subsystem. */
- private String subsystem;
- /**
- * Default Constructor.
- */
- public AbstractModule()
- {
- setModuleClass(this.getClass().getName());
- }
- /**
- * Loads the default module description from the file "module.properties". This file
- * must be in the same package as the implementing class.
- *
- * @throws ModuleInitializeException if an error occurs.
- */
- protected void loadModuleInfo() throws ModuleInitializeException
- {
- final InputStream in = ObjectUtilities.getResourceRelativeAsStream
- ("module.properties", getClass());
- if (in == null)
- {
- throw new ModuleInitializeException
- ("File 'module.properties' not found in module package.");
- }
- loadModuleInfo(in);
- }
- /**
- * Loads the module descriptiong from the given input stream. The module description
- * must conform to the rules define in the class description. The file must be encoded
- * with "ISO-8859-1" (like property files).
- *
- * @param in the input stream from where to read the file
- * @throws ModuleInitializeException if an error occurs.
- */
- protected void loadModuleInfo(final InputStream in) throws ModuleInitializeException
- {
- if (in == null)
- {
- throw new NullPointerException
- ("Given InputStream is null.");
- }
- try
- {
- final ArrayList optionalModules = new ArrayList();
- final ArrayList dependendModules = new ArrayList();
- final ReaderHelper rh = new ReaderHelper(new BufferedReader
- (new InputStreamReader(in, "ISO-8859-1")));
- try
- {
- while (rh.hasNext())
- {
- final String lastLineRead = rh.next();
- if (lastLineRead.startsWith("module-info:"))
- {
- readModuleInfo(rh);
- }
- else if (lastLineRead.startsWith("depends:"))
- {
- dependendModules.add(readExternalModule(rh));
- }
- else if (lastLineRead.startsWith("optional:"))
- {
- optionalModules.add(readExternalModule(rh));
- }
- else
- {
- // we dont understand the current line, so we skip it ...
- // should we throw a parse exception instead?
- }
- }
- }
- finally
- {
- rh.close();
- }
- this.optionalModules = (ModuleInfo[])
- optionalModules.toArray(new ModuleInfo[optionalModules.size()]);
- this.requiredModules = (ModuleInfo[])
- dependendModules.toArray(new ModuleInfo[dependendModules.size()]);
- }
- catch (IOException ioe)
- {
- throw new ModuleInitializeException("Failed to load properties", ioe);
- }
- }
- /**
- * Reads a multiline value the stream. This will read the stream until
- * a new key is found or the end of the file is reached.
- *
- * @param reader the reader from where to read.
- * @param firstLine the first line (which was read elsewhere).
- * @return the complete value, never null
- * @throws IOException if an IO error occurs.
- */
- private String readValue(final ReaderHelper reader, String firstLine) throws IOException
- {
- final StringBuffer b = new StringBuffer(firstLine.trim());
- boolean newLine = true;
- while (isNextLineValueLine(reader))
- {
- firstLine = reader.next();
- final String trimedLine = firstLine.trim();
- if (trimedLine.length() == 0 && (newLine == false))
- {
- b.append ("\n");
- newLine = true;
- }
- else
- {
- if (newLine == false)
- {
- b.append(" ");
- }
- b.append(parseValue(trimedLine));
- newLine = false;
- }
- }
- return b.toString();
- }
- /**
- * Checks, whether the next line in the reader is a value line.
- *
- * @param reader from where to read the lines.
- * @return true, if the next line is a value line, false otherwise.
- * @throws IOException if an IO error occurs.
- */
- private boolean isNextLineValueLine (final ReaderHelper reader) throws IOException
- {
- if (reader.hasNext() == false)
- {
- return false;
- }
- final String firstLine = reader.next();
- if (firstLine == null)
- {
- return false;
- }
- if (parseKey(firstLine) != null)
- {
- reader.pushBack(firstLine);
- return false;
- }
- reader.pushBack(firstLine);
- return true;
- }
- /**
- * Reads the module definition header. This header contains information about
- * the module itself.
- *
- * @param reader the reader from where to read the content.
- * @throws IOException if an error occures
- */
- private void readModuleInfo(final ReaderHelper reader) throws IOException
- {
- while (reader.hasNext())
- {
- final String lastLineRead = reader.next();
- if (Character.isWhitespace(lastLineRead.charAt(0)) == false)
- {
- // break if the current character is no whitespace ...
- reader.pushBack(lastLineRead);
- return;
- }
- final String line = lastLineRead.trim();
- final String key = parseKey(line);
- if (key != null)
- {
- // parse error: Non data line does not contain a colon
- final String b = readValue(reader, parseValue(line.trim()));
- if ("name".equals(key))
- {
- setName(b);
- }
- else if ("producer".equals(key))
- {
- setProducer(b);
- }
- else if ("description".equals(key))
- {
- setDescription(b);
- }
- else if ("subsystem".equals(key))
- {
- setSubSystem(b);
- }
- else if ("version.major".equals(key))
- {
- setMajorVersion(b);
- }
- else if ("version.minor".equals(key))
- {
- setMinorVersion(b);
- }
- else if ("version.patchlevel".equals(key))
- {
- setPatchLevel(b);
- }
- }
- }
- }
- /**
- * Parses an string to find the key section of the line. This section ends with
- * an colon.
- *
- * @param line the line which to parse
- * @return the key or null if no key is found.
- */
- private String parseKey(final String line)
- {
- final int idx = line.indexOf(':');
- if (idx == -1)
- {
- return null;
- }
- return line.substring(0, idx);
- }
- /**
- * Parses the value section of the given line.
- *
- * @param line the line that should be parsed
- * @return the value, never null
- */
- private String parseValue(final String line)
- {
- final int idx = line.indexOf(':');
- if (idx == -1)
- {
- return line;
- }
- if ((idx + 1) == line.length())
- {
- return "";
- }
- return line.substring(idx + 1);
- }
- /**
- * Reads an external module description. This describes either an optional or
- * a required module.
- *
- * @param reader the reader from where to read the module
- * @return the read module, never null
- * @throws IOException if an error occures.
- */
- private DefaultModuleInfo readExternalModule(final ReaderHelper reader)
- throws IOException
- {
- final DefaultModuleInfo mi = new DefaultModuleInfo();
- while (reader.hasNext())
- {
- final String lastLineRead = reader.next();
- if (Character.isWhitespace(lastLineRead.charAt(0)) == false)
- {
- // break if the current character is no whitespace ...
- reader.pushBack(lastLineRead);
- return mi;
- }
- final String line = lastLineRead.trim();
- final String key = parseKey(line);
- if (key != null)
- {
- final String b = readValue(reader, parseValue(line));
- if ("module".equals(key))
- {
- mi.setModuleClass(b);
- }
- else if ("version.major".equals(key))
- {
- mi.setMajorVersion(b);
- }
- else if ("version.minor".equals(key))
- {
- mi.setMinorVersion(b);
- }
- else if ("version.patchlevel".equals(key))
- {
- mi.setPatchLevel(b);
- }
- }
- }
- return mi;
- }
- /**
- * Returns the name of this module.
- *
- * @see Module#getName()
- *
- * @return the module name
- */
- public String getName()
- {
- return this.name;
- }
- /**
- * Defines the name of the module.
- *
- * @param name the module name.
- */
- protected void setName(final String name)
- {
- this.name = name;
- }
- /**
- * Returns the module description.
- * @see Module#getDescription()
- *
- * @return the description of the module.
- */
- public String getDescription()
- {
- return this.description;
- }
- /**
- * Defines the description of the module.
- *
- * @param description the module's desciption.
- */
- protected void setDescription(final String description)
- {
- this.description = description;
- }
- /**
- * Returns the producer of the module.
- *
- * @see Module#getProducer()
- *
- * @return the producer.
- */
- public String getProducer()
- {
- return this.producer;
- }
- /**
- * Defines the producer of the module.
- *
- * @param producer the producer.
- */
- protected void setProducer(final String producer)
- {
- this.producer = producer;
- }
- /**
- * Returns a copy of the required modules array. This array contains all
- * description of the modules that need to be present to make this module work.
- * @see Module#getRequiredModules()
- *
- * @return an array of all required modules.
- */
- public ModuleInfo[] getRequiredModules()
- {
- final ModuleInfo[] retval = new ModuleInfo[this.requiredModules.length];
- System.arraycopy(this.requiredModules, 0, retval, 0, this.requiredModules.length);
- return retval;
- }
- /**
- * Returns a copy of the required modules array. This array contains all
- * description of the optional modules that may improve the modules functonality.
- * @see Module#getRequiredModules()
- *
- * @return an array of all required modules.
- */
- public ModuleInfo[] getOptionalModules()
- {
- final ModuleInfo[] retval = new ModuleInfo[this.optionalModules.length];
- System.arraycopy(this.optionalModules, 0, retval, 0, this.optionalModules.length);
- return retval;
- }
- /**
- * Defines the required module descriptions for this module.
- *
- * @param requiredModules the required modules.
- */
- protected void setRequiredModules(final ModuleInfo[] requiredModules)
- {
- this.requiredModules = new ModuleInfo[requiredModules.length];
- System.arraycopy(requiredModules, 0, this.requiredModules, 0, requiredModules.length);
- }
- /**
- * Defines the optional module descriptions for this module.
- *
- * @param optionalModules the optional modules.
- */
- public void setOptionalModules(final ModuleInfo[] optionalModules)
- {
- this.optionalModules = new ModuleInfo[optionalModules.length];
- System.arraycopy(optionalModules, 0, this.optionalModules, 0, optionalModules.length);
- }
- /**
- * Returns a string representation of this module.
- * @see java.lang.Object#toString()
- *
- * @return the string representation of this module for debugging purposes.
- */
- public String toString()
- {
- final StringBuffer buffer = new StringBuffer();
- buffer.append("Module : ");
- buffer.append(getName());
- buffer.append("\n");
- buffer.append("ModuleClass : ");
- buffer.append(getModuleClass());
- buffer.append("\n");
- buffer.append("Version: ");
- buffer.append(getMajorVersion());
- buffer.append(".");
- buffer.append(getMinorVersion());
- buffer.append(".");
- buffer.append(getPatchLevel());
- buffer.append("\n");
- buffer.append("Producer: ");
- buffer.append(getProducer());
- buffer.append("\n");
- buffer.append("Description: ");
- buffer.append(getDescription());
- buffer.append("\n");
- return buffer.toString();
- }
- /**
- * Tries to load a class to indirectly check for the existence
- * of a certain library.
- *
- * @param name the name of the library class.
- * @return true, if the class could be loaded, false otherwise.
- * @deprecated use the method that passes in a context-class.
- */
- protected static boolean isClassLoadable(final String name)
- {
- try
- {
- final ClassLoader loader = ObjectUtilities.getClassLoader(AbstractModule.class);
- if (loader == null)
- {
- // this should not happen .. If it happens, it measn we dont even have a system-classloader.
- return false;
- }
- loader.loadClass(name);
- return true;
- }
- catch (Exception e)
- {
- return false;
- }
- }
- /**
- * Tries to load a class to indirectly check for the existence
- * of a certain library.
- *
- * @param name the name of the library class.
- * @param context the context class to get a classloader from.
- * @return true, if the class could be loaded, false otherwise.
- */
- protected static boolean isClassLoadable(final String name, final Class context)
- {
- try
- {
- ObjectUtilities.getClassLoader(context).loadClass(name);
- return true;
- }
- catch (Exception e)
- {
- return false;
- }
- }
- /**
- * Configures the module by loading the configuration properties and
- * adding them to the package configuration.
- *
- * @param subSystem the subsystem.
- */
- public void configure(final SubSystem subSystem)
- {
- final InputStream in = ObjectUtilities.getResourceRelativeAsStream
- ("configuration.properties", getClass());
- if (in == null)
- {
- return;
- }
- try
- {
- subSystem.getPackageManager().getPackageConfiguration().load(in);
- }
- finally
- {
- try
- {
- in.close();
- }
- catch (IOException e)
- {
- // can be ignored ...
- }
- }
- }
- /**
- * Tries to load an module initializer and uses this initializer to initialize
- * the module.
- *
- * @param classname the class name of the initializer.
- * @throws ModuleInitializeException if an error occures
- * @deprecated Use the method that provides a class-context instead.
- */
- protected void performExternalInitialize(final String classname)
- throws ModuleInitializeException
- {
- try
- {
- final ModuleInitializer mi =
- (ModuleInitializer) ObjectUtilities.loadAndInstantiate(classname, AbstractModule.class, ModuleInitializer.class);
- if (mi == null)
- {
- throw new ModuleInitializeException("Failed to load specified initializer class.");
- }
- mi.performInit();
- }
- catch (ModuleInitializeException mie)
- {
- throw mie;
- }
- catch (Exception e)
- {
- throw new ModuleInitializeException("Failed to load specified initializer class.", e);
- }
- }
- /**
- * ???.
- *
- * @param classname ?
- * @param context ?
- * @throws ModuleInitializeException if there is an initialisation error.
- */
- protected void performExternalInitialize(final String classname, final Class context)
- throws ModuleInitializeException
- {
- try
- {
- final ModuleInitializer mi =
- (ModuleInitializer) ObjectUtilities.loadAndInstantiate(classname, context, ModuleInitializer.class);
- if (mi == null)
- {
- throw new ModuleInitializeException("Failed to load specified initializer class.");
- }
- mi.performInit();
- }
- catch (ModuleInitializeException mie)
- {
- throw mie;
- }
- catch (Exception e)
- {
- throw new ModuleInitializeException("Failed to load specified initializer class.", e);
- }
- }
- /**
- * Returns the modules subsystem. If this module is not part of an subsystem
- * then return the modules name, but never null.
- *
- * @return the name of the subsystem.
- */
- public String getSubSystem()
- {
- if (this.subsystem == null)
- {
- return getName();
- }
- return this.subsystem;
- }
- /**
- * Defines the subsystem name for this module.
- *
- * @param name the new name of the subsystem.
- */
- protected void setSubSystem (final String name)
- {
- this.subsystem = name;
- }
- }
|