Index: 3rdParty_sources/jbossweb/org/jboss/logging/DynamicLogger.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/logging/DynamicLogger.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/logging/DynamicLogger.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,265 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.logging;
+
+/**
+ * An extension of the JBoss Logger that adds a log()
+ * primitive that maps to a dynamically defined log level.
+ *
+ * TODO - Make sure serialization works correctly
+ *
+ * @author Dimitris Andreadis
+ * @version $Revision: 1.1 $
+ *
+ * @since 4.0.3
+ */
+public class DynamicLogger extends Logger
+{
+ /** The serialVersionUID */
+ private static final long serialVersionUID = -5963699806863917370L;
+
+ /** No logging */
+ public static final int LOG_LEVEL_NONE = 0;
+
+ /** Fatal level logging */
+ public static final int LOG_LEVEL_FATAL = 1;
+
+ /** Error level logging */
+ public static final int LOG_LEVEL_ERROR = 2;
+
+ /** Warn level logging */
+ public static final int LOG_LEVEL_WARN = 3;
+
+ /** Info level logging */
+ public static final int LOG_LEVEL_INFO = 4;
+
+ /** Debug level logging */
+ public static final int LOG_LEVEL_DEBUG = 5;
+
+ /** Trace level logging */
+ public static final int LOG_LEVEL_TRACE = 6;
+
+ /** The available log level strings */
+ public final static String[] LOG_LEVEL_STRINGS =
+ { "NONE", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" };
+
+ /** The log level to use for the "log" primitive */
+ private int logLevel = LOG_LEVEL_DEBUG;
+
+ /**
+ * Create a DynamicLogger instance given the logger name.
+ *
+ * @param name the logger name
+ * @return the dynamic logger
+ */
+ public static DynamicLogger getDynamicLogger(String name)
+ {
+ return new DynamicLogger(name);
+ }
+
+ /**
+ * Create a DynamicLogger instance given the logger name with the given suffix.
+ *
+ *
This will include a logger seperator between classname and suffix
+ *
+ * @param name The logger name
+ * @param suffix A suffix to append to the classname.
+ * @return the dynamic logger
+ */
+ public static DynamicLogger getDynamicLogger(String name, String suffix)
+ {
+ return new DynamicLogger(name + "." + suffix);
+ }
+
+ /**
+ * Create a DynamicLogger instance given the logger class. This simply
+ * calls create(clazz.getName()).
+ *
+ * @param clazz the Class whose name will be used as the logger name
+ * @return the dynamic logger
+ */
+ public static DynamicLogger getDynamicLogger(Class clazz)
+ {
+ return new DynamicLogger(clazz.getName());
+ }
+
+ /**
+ * Create a DynamicLogger instance given the logger class with the given suffix.
+ *
+ *
This will include a logger seperator between classname and suffix
+ *
+ * @param clazz The Class whose name will be used as the logger name.
+ * @param suffix A suffix to append to the classname.
+ * @return the dynamic logger
+ */
+ public static DynamicLogger getDynamicLogger(Class clazz, String suffix)
+ {
+ return new DynamicLogger(clazz.getName() + "." + suffix);
+ }
+
+ /**
+ * Create a new DynamicLogger.
+ *
+ * @param name the log name
+ */
+ protected DynamicLogger(final String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Sets the logLevel for the log() primitive
+ *
+ * @param logLevel between LOG_LEVEL_NONE and LOG_LEVEL_TRACE
+ */
+ public void setLogLevel(int logLevel)
+ {
+ if (logLevel >= LOG_LEVEL_NONE && logLevel <= LOG_LEVEL_TRACE)
+ {
+ this.logLevel = logLevel;
+ }
+ }
+
+ /**
+ * Gets the logLevel of the log() primitive
+ *
+ * @return the logLevel of the log() primitive
+ */
+ public int getLogLevel()
+ {
+ return logLevel;
+ }
+
+ /**
+ * Sets the logLevel of the log() primitive
+ *
+ * @param logLevelString the log level in String form
+ */
+ public void setLogLevelAsString(String logLevelString)
+ {
+ if (logLevelString != null)
+ {
+ logLevelString = logLevelString.toUpperCase().trim();
+
+ for (int i = 0; i <= LOG_LEVEL_TRACE; i++)
+ {
+ if (logLevelString.equals(LOG_LEVEL_STRINGS[i]))
+ {
+ // match
+ this.logLevel = i;
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the logLevel of the log() primitive in String form
+ *
+ * @return the logLevel of the log() primitive in String form
+ */
+ public String getLogLevelAsString()
+ {
+ return LOG_LEVEL_STRINGS[logLevel];
+ }
+
+ /**
+ * Logs a message using dynamic log level
+ *
+ * @param message the message to log
+ */
+ public void log(Object message)
+ {
+ switch (logLevel)
+ {
+ case LOG_LEVEL_TRACE:
+ super.trace(message);
+ break;
+
+ case LOG_LEVEL_DEBUG:
+ super.debug(message);
+ break;
+
+ case LOG_LEVEL_INFO:
+ super.info(message);
+ break;
+
+ case LOG_LEVEL_WARN:
+ super.warn(message);
+ break;
+
+ case LOG_LEVEL_ERROR:
+ super.error(message);
+ break;
+
+ case LOG_LEVEL_FATAL:
+ super.fatal(message);
+ break;
+
+ case LOG_LEVEL_NONE:
+ default:
+ // do nothing
+ break;
+ }
+ }
+
+ /**
+ * Logs a message and a throwable using dynamic log level
+ *
+ * @param message the message to log
+ * @param t the throwable to log
+ */
+ public void log(Object message, Throwable t)
+ {
+ switch (logLevel)
+ {
+ case LOG_LEVEL_TRACE:
+ super.trace(message, t);
+ break;
+
+ case LOG_LEVEL_DEBUG:
+ super.debug(message, t);
+ break;
+
+ case LOG_LEVEL_INFO:
+ super.info(message, t);
+ break;
+
+ case LOG_LEVEL_WARN:
+ super.warn(message, t);
+ break;
+
+ case LOG_LEVEL_ERROR:
+ super.error(message, t);
+ break;
+
+ case LOG_LEVEL_FATAL:
+ super.fatal(message, t);
+ break;
+
+ case LOG_LEVEL_NONE:
+ default:
+ // do nothing
+ break;
+ }
+ }
+}
Index: 3rdParty_sources/jbossweb/org/jboss/logging/Logger.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/logging/Logger.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/logging/Logger.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,434 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.logging;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+
+/**
+ * Logger wrapper that tries to dynamically load a log4j class to
+ * determine if log4j is available in the VM. If it is the case,
+ * a log4j delegate is built and used. In the contrary, a null
+ * logger is used. This class cannot directly reference log4j
+ * classes otherwise the JVM will try to load it and make it fail.
+ * To set
+ *
+ *
Only exposes the relevent factory and logging methods.
+ *
+ *
For JBoss the logging should be done as follows:
+ *
+ * FATAL - JBoss is likely to/will crash
+ * ERROR - A definite problem
+ * WARN - Likely to be a problem, or it could be JBoss
+ * detected a problem it can recover from
+ * INFO - Lifecycle low volume, e.g. "Bound x into jndi",
+ * things that are of interest to a user
+ * DEBUG - Lifecycle low volume but necessarily of interest
+ * to the user, e.g. "Starting listener thread"
+ * TRACE - High volume detailed logging
+ *
+ *
+ * @see #isTraceEnabled
+ * @see #trace(Object)
+ * @see #trace(Object,Throwable)
+ *
+ * @version $Revision: 1.1 $
+ * @author Scott.Stark@jboss.org
+ * @author Jason Dillon
+ * @author Sacha Labourey
+ */
+public class Logger implements Serializable
+{
+ /** Serialization */
+ private static final long serialVersionUID = 4232175575988879434L;
+
+ /** The system property to look for an externalized LoggerPlugin implementation class */
+ protected static String PLUGIN_CLASS_PROP = "org.jboss.logging.Logger.pluginClass";
+
+ /** The default LoggerPlugin implementation is log4j */
+ protected static final String DEFAULT_PLUGIN_CLASS_NAME = "org.jboss.logging.jdk.JDK14LoggerPlugin";
+
+ /** The LoggerPlugin implementation class to use */
+ protected static Class pluginClass = null;
+
+ /** The class name of the LoggerPlugin implementation class to use */
+ protected static String pluginClassName = null;
+
+ static
+ {
+ init();
+ }
+
+ /** The logger name. */
+ private final String name;
+
+ /** The logger plugin delegate */
+ protected transient LoggerPlugin loggerDelegate = null;
+
+ /** The LoggerPlugin implementation class name in use
+ *
+ * @return LoggerPlugin implementation class name
+ */
+ public static String getPluginClassName()
+ {
+ return Logger.pluginClassName;
+ }
+
+ /**
+ * Set the LoggerPlugin implementation class name in use
+ *
+ * @param pluginClassName the LoggerPlugin implementation class name
+ */
+ public static void setPluginClassName(String pluginClassName)
+ {
+ if (pluginClassName.equals(Logger.pluginClassName) == false)
+ {
+ Logger.pluginClassName = pluginClassName;
+ init();
+ }
+ }
+
+ /**
+ * Creates new Logger the given logger name.
+ *
+ * @param name the logger name.
+ */
+ protected Logger(final String name)
+ {
+ this.name = name;
+ this.loggerDelegate = getDelegatePlugin(name);
+ }
+
+ /**
+ * Return the name of this logger.
+ *
+ * @return The name of this logger.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Get the logger plugin delegate
+ *
+ * @return the delegate
+ */
+ public LoggerPlugin getLoggerPlugin()
+ {
+ return this.loggerDelegate;
+ }
+
+ /**
+ * Check to see if the TRACE level is enabled for this logger.
+ *
+ * @return true if a {@link #trace(Object)} method invocation would pass
+ * the msg to the configured appenders, false otherwise.
+ */
+ public boolean isTraceEnabled()
+ {
+ return loggerDelegate.isTraceEnabled();
+ }
+
+ /**
+ * Issue a log msg with a level of TRACE.
+ *
+ * @param message the message
+ */
+ public void trace(Object message)
+ {
+ loggerDelegate.trace(message);
+ }
+
+ /**
+ * Issue a log msg and throwable with a level of TRACE.
+ *
+ * @param message the message
+ * @param t the throwable
+ */
+ public void trace(Object message, Throwable t)
+ {
+ loggerDelegate.trace(message, t);
+ }
+
+ /**
+ * Check to see if the DEBUG level is enabled for this logger.
+ *
+ * @deprecated DEBUG is for low volume logging, you don't need this
+ * @return true if a {@link #trace(Object)} method invocation would pass
+ * the msg to the configured appenders, false otherwise.
+ */
+ public boolean isDebugEnabled()
+ {
+ return loggerDelegate.isDebugEnabled();
+ }
+
+ /**
+ * Issue a log msg with a level of DEBUG.
+ *
+ * @param message the message
+ */
+ public void debug(Object message)
+ {
+ loggerDelegate.debug(message);
+ }
+
+ /**
+ * Issue a log msg and throwable with a level of DEBUG.
+ *
+ * @param message the message
+ * @param t the throwable
+ */
+ public void debug(Object message, Throwable t)
+ {
+ loggerDelegate.debug(message, t);
+ }
+
+ /**
+ * Check to see if the INFO level is enabled for this logger.
+ *
+ * @deprecated INFO is for low volume information, you don't need this
+ * @return true if a {@link #info(Object)} method invocation would pass
+ * the msg to the configured appenders, false otherwise.
+ */
+ public boolean isInfoEnabled()
+ {
+ return loggerDelegate.isInfoEnabled();
+ }
+
+ /**
+ * Issue a log msg with a level of INFO.
+ *
+ * @param message the message
+ */
+ public void info(Object message)
+ {
+ loggerDelegate.info(message);
+ }
+
+ /**
+ * Issue a log msg and throwable with a level of INFO.
+ *
+ * @param message the message
+ * @param t the throwable
+ */
+ public void info(Object message, Throwable t)
+ {
+ loggerDelegate.info(message, t);
+ }
+
+ /**
+ * Issue a log msg with a level of WARN.
+ *
+ * @param message the message
+ */
+ public void warn(Object message)
+ {
+ loggerDelegate.warn(message);
+ }
+
+ /**
+ * Issue a log msg and throwable with a level of WARN.
+ *
+ * @param message the message
+ * @param t the throwable
+ */
+ public void warn(Object message, Throwable t)
+ {
+ loggerDelegate.warn(message, t);
+ }
+
+ /**
+ * Issue a log msg with a level of ERROR.
+ *
+ * @param message the message
+ */
+ public void error(Object message)
+ {
+ loggerDelegate.error(message);
+ }
+
+ /**
+ * Issue a log msg and throwable with a level of ERROR.
+ *
+ * @param message the message
+ * @param t the throwable
+ */
+ public void error(Object message, Throwable t)
+ {
+ loggerDelegate.error(message, t);
+ }
+
+ /**
+ * Issue a log msg with a level of FATAL.
+ *
+ * @param message the message
+ */
+ public void fatal(Object message)
+ {
+ loggerDelegate.fatal(message);
+ }
+
+ /**
+ * Issue a log msg and throwable with a level of FATAL.
+ *
+ * @param message the message
+ * @param t the throwable
+ */
+ public void fatal(Object message, Throwable t)
+ {
+ loggerDelegate.fatal(message, t);
+ }
+
+ /**
+ * Custom serialization to reinitalize the delegate
+ *
+ * @param stream the object stream
+ * @throws IOException for any error
+ * @throws ClassNotFoundException if a class is not found during deserialization
+ */
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException
+ {
+ // restore non-transient fields (aka name)
+ stream.defaultReadObject();
+
+ // Restore logging
+ if (pluginClass == null)
+ {
+ init();
+ }
+ this.loggerDelegate = getDelegatePlugin(name);
+ }
+
+ /**
+ * Create a Logger instance given the logger name.
+ *
+ * @param name the logger name
+ * @return the logger
+ */
+ public static Logger getLogger(String name)
+ {
+ return new Logger(name);
+ }
+
+ /**
+ * Create a Logger instance given the logger name with the given suffix.
+ *
+ * This will include a logger seperator between classname and suffix
+ *
+ * @param name the logger name
+ * @param suffix a suffix to append to the classname.
+ * @return the logger
+ */
+ public static Logger getLogger(String name, String suffix)
+ {
+ return new Logger(name + "." + suffix);
+ }
+
+ /**
+ * Create a Logger instance given the logger class. This simply
+ * calls create(clazz.getName()).
+ *
+ * @param clazz the Class whose name will be used as the logger name
+ * @return the logger
+ */
+ public static Logger getLogger(Class clazz)
+ {
+ return new Logger(clazz.getName());
+ }
+
+ /**
+ * Create a Logger instance given the logger class with the given suffix.
+ *
+ *
This will include a logger seperator between classname and suffix
+ *
+ * @param clazz the Class whose name will be used as the logger name.
+ * @param suffix a suffix to append to the classname.
+ * @return the logger
+ */
+ public static Logger getLogger(Class clazz, String suffix)
+ {
+ return new Logger(clazz.getName() + "." + suffix);
+ }
+
+ /**
+ * Get the delegate plugin
+ *
+ * @param name the name of the logger
+ * @return the plugin
+ */
+ protected static LoggerPlugin getDelegatePlugin(String name)
+ {
+ LoggerPlugin plugin = null;
+ try
+ {
+ plugin = (LoggerPlugin) pluginClass.newInstance();
+ }
+ catch (Throwable e)
+ {
+ plugin = new NullLoggerPlugin();
+ }
+ try
+ {
+ plugin.init(name);
+ }
+ catch (Throwable e)
+ {
+ String extraInfo = e.getMessage();
+ System.err.println("Failed to initalize plugin: " + plugin
+ + (extraInfo != null ? ", cause: " + extraInfo : ""));
+ plugin = new NullLoggerPlugin();
+ }
+
+ return plugin;
+ }
+
+ /**
+ * Initialize the LoggerPlugin class to use as the delegate to the
+ * logging system. This first checks to see if a pluginClassName has
+ * been specified via the {@link #setPluginClassName(String)} method,
+ * then the PLUGIN_CLASS_PROP system property and finally the
+ * LOG4J_PLUGIN_CLASS_NAME default. If the LoggerPlugin implementation
+ * class cannot be loaded the default NullLoggerPlugin will be used.
+ */
+ protected static void init()
+ {
+ try
+ {
+ // See if there is a PLUGIN_CLASS_PROP specified
+ if (pluginClassName == null)
+ {
+ pluginClassName = System.getProperty(PLUGIN_CLASS_PROP, DEFAULT_PLUGIN_CLASS_NAME);
+ }
+
+ // Try to load the plugin via the TCL
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ pluginClass = cl.loadClass(pluginClassName);
+ }
+ catch (Throwable e)
+ {
+ // The plugin could not be setup, default to a null logger
+ pluginClass = org.jboss.logging.NullLoggerPlugin.class;
+ }
+ }
+}
Index: 3rdParty_sources/jbossweb/org/jboss/logging/LoggerPlugin.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/logging/LoggerPlugin.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/logging/LoggerPlugin.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,158 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.logging;
+
+/**
+ * Defines a "pluggable" login module. In fact, this is only used to split between
+ * log4j and /dev/null. Choice is made in org.jboss.logging.Logger
+ *
+ * @see org.jboss.logging.Logger
+ * @see org.jboss.logging.NullLoggerPlugin
+ *
+ * @author Sacha Labourey .
+ * @version $Revision: 1.1 $
+ */
+public interface LoggerPlugin
+{
+ /**
+ * Initialise the logger with the given name
+ *
+ * @param name the name
+ */
+ void init(String name);
+
+ /**
+ * Check to see if the TRACE level is enabled for this logger.
+ *
+ * @return true if a {@link #trace(Object)} method invocation would pass
+ * the msg to the configured appenders, false otherwise.
+ */
+ boolean isTraceEnabled();
+
+ /**
+ * Issue a log msg with a level of TRACE.
+ *
+ * @param message the message
+ */
+ void trace(Object message);
+
+ /**
+ * Issue a log msg and throwable with a level of TRACE.
+ *
+ * @param message the message
+ * @param t the throwable
+ */
+ void trace(Object message, Throwable t);
+
+ /**
+ * Check to see if the DEBUG level is enabled for this logger.
+ *
+ * @deprecated DEBUG is for low volume logging, you don't need this
+ * @return true if a {@link #trace(Object)} method invocation would pass
+ * the msg to the configured appenders, false otherwise.
+ */
+ boolean isDebugEnabled();
+
+ /**
+ * Issue a log msg with a level of DEBUG.
+ *
+ * @param message the message
+ */
+ void debug(Object message);
+
+ /**
+ * Issue a log msg and throwable with a level of DEBUG.
+ *
+ * @param message the message
+ * @param t the throwable
+ */
+ void debug(Object message, Throwable t);
+
+ /**
+ * Check to see if the INFO level is enabled for this logger.
+ *
+ * @deprecated INFO is for low volume information, you don't need this
+ * @return true if a {@link #info(Object)} method invocation would pass
+ * the msg to the configured appenders, false otherwise.
+ */
+ boolean isInfoEnabled();
+
+ /**
+ * Issue a log msg with a level of INFO.
+ *
+ * @param message the message
+ */
+ void info(Object message);
+
+ /**
+ * Issue a log msg and throwable with a level of INFO.
+ *
+ * @param message the message
+ * @param t the throwable
+ */
+ void info(Object message, Throwable t);
+
+ /**
+ * Issue a log msg with a level of WARN.
+ *
+ * @param message the message
+ */
+ void warn(Object message);
+
+ /**
+ * Issue a log msg and throwable with a level of WARN.
+ *
+ * @param message the message
+ * @param t the throwable
+ */
+ void warn(Object message, Throwable t);
+
+ /**
+ * Issue a log msg with a level of ERROR.
+ *
+ * @param message the message
+ */
+ void error(Object message);
+
+ /**
+ * Issue a log msg and throwable with a level of ERROR.
+ *
+ * @param message the message
+ * @param t the throwable
+ */
+ void error(Object message, Throwable t);
+
+ /**
+ * Issue a log msg with a level of FATAL.
+ *
+ * @param message the message
+ */
+ void fatal(Object message);
+
+ /**
+ * Issue a log msg and throwable with a level of FATAL.
+ *
+ * @param message the message
+ * @param t the throwable
+ */
+ void fatal(Object message, Throwable t);
+}
Index: 3rdParty_sources/jbossweb/org/jboss/logging/MDC.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/logging/MDC.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/logging/MDC.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,76 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.logging;
+
+import java.util.Map;
+
+/**
+ * A "Map Diagnostic Context" abstraction.
+ *
+ * @author Jason T. Greene
+ */
+public class MDC
+{
+ private final static MDCProvider mdc;
+
+ static
+ {
+ MDCProvider m = null;
+ if (NDCSupport.class.isAssignableFrom(Logger.pluginClass))
+ {
+
+ try
+ {
+ m = ((MDCSupport) Logger.pluginClass.newInstance()).getMDCProvider();
+ }
+ catch (Throwable t)
+ {
+ // Eat
+ }
+ }
+
+ if (m == null)
+ m = new NullMDCProvider();
+
+ mdc = m;
+ }
+
+ public static void put(String key, Object val)
+ {
+ mdc.put(key, val);
+ }
+
+ public static Object get(String key)
+ {
+ return mdc.get(key);
+ }
+
+ public static void remove(String key)
+ {
+ mdc.remove(key);
+ }
+
+ public static Map getMap()
+ {
+ return mdc.getMap();
+ }
+}
Index: 3rdParty_sources/jbossweb/org/jboss/logging/MDCProvider.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/logging/MDCProvider.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/logging/MDCProvider.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.logging;
+
+import java.util.Map;
+
+/**
+ * MDC SPI for the backend logging implementation.
+ *
+ * @author Jason T. Greene
+ */
+public interface MDCProvider
+{
+ public void put(String key, Object value);
+
+ public Object get(String key);
+
+ public void remove(String key);
+
+ public Map getMap();
+}
Index: 3rdParty_sources/jbossweb/org/jboss/logging/MDCSupport.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/logging/MDCSupport.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/logging/MDCSupport.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,32 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.logging;
+
+/**
+ * Indicates that a Logger plugin supports MDC.
+ *
+ * @author Jason T. Greene
+ */
+public interface MDCSupport
+{
+ public MDCProvider getMDCProvider();
+}
Index: 3rdParty_sources/jbossweb/org/jboss/logging/NDC.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/logging/NDC.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/logging/NDC.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,90 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.logging;
+
+
+/**
+ * A "Nested Diagnostic Context" abstraction.
+ *
+ * @author Jason T. Greene
+ */
+public class NDC
+{
+ private final static NDCProvider ndc;
+
+ static
+ {
+ NDCProvider n = null;
+ if (NDCSupport.class.isAssignableFrom(Logger.pluginClass))
+ {
+
+ try
+ {
+ n = ((NDCSupport) Logger.pluginClass.newInstance()).getNDCProvider();
+ }
+ catch (Throwable t)
+ {
+ // Eat
+ }
+ }
+
+ if (n == null)
+ n = new NullNDCProvider();
+
+ ndc = n;
+ }
+
+ public static void clear()
+ {
+ ndc.clear();
+ }
+
+ public static String get()
+ {
+ return ndc.get();
+ }
+
+ public static int getDepth()
+ {
+ return ndc.getDepth();
+ }
+
+ public static String pop()
+ {
+ return ndc.pop();
+ }
+
+ public static String peek()
+ {
+ return ndc.peek();
+ }
+
+ public static void push(String message)
+ {
+ ndc.push(message);
+ }
+
+ public static void setMaxDepth(int maxDepth)
+ {
+ ndc.setMaxDepth(maxDepth);
+ }
+}
Index: 3rdParty_sources/jbossweb/org/jboss/logging/NDCProvider.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/logging/NDCProvider.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/logging/NDCProvider.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,45 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.logging;
+
+
+/**
+ * An NDC SPI for the backend logging implementation.
+ *
+ * @author Jason T. Greene
+ */
+public interface NDCProvider
+{
+ public void clear();
+
+ public String get();
+
+ public int getDepth();
+
+ public String pop();
+
+ public String peek();
+
+ public void push(String message);
+
+ public void setMaxDepth(int maxDepth);
+}
\ No newline at end of file
Index: 3rdParty_sources/jbossweb/org/jboss/logging/NDCSupport.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/logging/NDCSupport.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/logging/NDCSupport.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,32 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.logging;
+
+/**
+ * Indicates that a logger plugin supports NDC.
+ *
+ * @author Jason T. Greene
+ */
+public interface NDCSupport
+{
+ public NDCProvider getNDCProvider();
+}
Index: 3rdParty_sources/jbossweb/org/jboss/logging/NullLoggerPlugin.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/logging/NullLoggerPlugin.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/logging/NullLoggerPlugin.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,115 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.logging;
+
+/**
+ * LoggerPlugin implementation producing no output at all. Used for client
+ * side logging when no log4j.jar is available on the classpath.
+ *
+ * @see org.jboss.logging.Logger
+ * @see org.jboss.logging.LoggerPlugin
+ *
+ * @author Sacha Labourey .
+ * @version $Revision: 1.1 $
+ */
+public class NullLoggerPlugin implements LoggerPlugin
+{
+ public void init(String name)
+ {
+ /* don't care */
+ }
+
+ public boolean isTraceEnabled()
+ {
+ return false;
+ }
+
+ public void trace(Object message)
+ {
+ // nothing
+ }
+
+ public void trace(Object message, Throwable t)
+ {
+ // nothing
+ }
+
+ public boolean isDebugEnabled()
+ {
+ return false;
+ }
+
+ public void debug(Object message)
+ {
+ // nothing
+ }
+
+ public void debug(Object message, Throwable t)
+ {
+ // nothing
+ }
+
+ public boolean isInfoEnabled()
+ {
+ return false;
+ }
+
+ public void info(Object message)
+ {
+ // nothing
+ }
+
+ public void info(Object message, Throwable t)
+ {
+ // nothing
+ }
+
+ public void error(Object message)
+ {
+ // nothing
+ }
+
+ public void error(Object message, Throwable t)
+ {
+ // nothing
+ }
+
+ public void fatal(Object message)
+ {
+ // nothing
+ }
+
+ public void fatal(Object message, Throwable t)
+ {
+ // nothing
+ }
+
+ public void warn(Object message)
+ {
+ // nothing
+ }
+
+ public void warn(Object message, Throwable t)
+ {
+ // nothing
+ }
+}
Index: 3rdParty_sources/jbossweb/org/jboss/logging/NullMDCProvider.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/logging/NullMDCProvider.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/logging/NullMDCProvider.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,50 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.logging;
+
+import java.util.Map;
+
+/**
+ * An MDC provider which does nothing.
+ *
+ * @author Jason T. Greene
+ */
+public class NullMDCProvider implements MDCProvider
+{
+ public Object get(String key)
+ {
+ return null;
+ }
+
+ public Map getMap()
+ {
+ return null;
+ }
+
+ public void put(String key, Object val)
+ {
+ }
+
+ public void remove(String key)
+ {
+ }
+}
\ No newline at end of file
Index: 3rdParty_sources/jbossweb/org/jboss/logging/NullNDCProvider.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/logging/NullNDCProvider.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/logging/NullNDCProvider.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,77 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.logging;
+
+import java.util.Stack;
+
+/**
+ * An NDC provider which does nothing.
+ *
+ * @author Jason T. Greene
+ */
+public class NullNDCProvider implements NDCProvider
+{
+ public void clear()
+ {
+ }
+
+ public Stack cloneStack()
+ {
+ return null;
+ }
+
+ public String get()
+ {
+ return null;
+ }
+
+ public int getDepth()
+ {
+ return 0;
+ }
+
+ public void inherit(Stack stack)
+ {
+ }
+
+ public String peek()
+ {
+ return null;
+ }
+
+ public String pop()
+ {
+ return null;
+ }
+
+ public void push(String message)
+ {
+ }
+
+ public void remove()
+ {
+ }
+
+ public void setMaxDepth(int maxDepth)
+ {
+ }
+}
Index: 3rdParty_sources/jbossweb/org/jboss/logging/jdk/JDK14LoggerPlugin.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/logging/jdk/JDK14LoggerPlugin.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/logging/jdk/JDK14LoggerPlugin.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,154 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.logging.jdk;
+
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+import org.jboss.logging.LoggerPlugin;
+import org.jboss.logging.MDCProvider;
+import org.jboss.logging.MDCSupport;
+import org.jboss.logging.NDCProvider;
+import org.jboss.logging.NDCSupport;
+
+/** An example LoggerPlugin which uses the JDK java.util.logging framework.
+ *
+ * @author Scott.Stark@jboss.org
+ * @version $Revison:$
+ */
+public class JDK14LoggerPlugin implements LoggerPlugin, MDCSupport, NDCSupport
+{
+ private Logger log;
+
+ public void init(String name)
+ {
+ log = Logger.getLogger(name);
+ }
+
+ public boolean isTraceEnabled()
+ {
+ return log.isLoggable(Level.FINER);
+ }
+
+ public void trace(Object message)
+ {
+ log(Level.FINER, String.valueOf(message), null);
+ }
+
+ public void trace(Object message, Throwable t)
+ {
+ log(Level.FINER, String.valueOf(message), t);
+ }
+
+ public boolean isDebugEnabled()
+ {
+ return log.isLoggable(Level.FINE);
+ }
+
+ public void debug(Object message)
+ {
+ log(Level.FINE, String.valueOf(message), null);
+ }
+
+ public void debug(Object message, Throwable t)
+ {
+ log(Level.FINE, String.valueOf(message), t);
+ }
+
+ public boolean isInfoEnabled()
+ {
+ return log.isLoggable(Level.INFO);
+ }
+
+ public void info(Object message)
+ {
+ log(Level.INFO, String.valueOf(message), null);
+ }
+
+ public void info(Object message, Throwable t)
+ {
+ log(Level.INFO, String.valueOf(message), t);
+ }
+
+ public void warn(Object message)
+ {
+ log(Level.WARNING, String.valueOf(message), null);
+ }
+
+ public void warn(Object message, Throwable t)
+ {
+ log(Level.WARNING, String.valueOf(message), t);
+ }
+
+ public void error(Object message)
+ {
+ log(Level.SEVERE, String.valueOf(message), null);
+ }
+
+ public void error(Object message, Throwable t)
+ {
+ log(Level.SEVERE, String.valueOf(message), t);
+ }
+
+ public void fatal(Object message)
+ {
+ log(Level.SEVERE, String.valueOf(message), null);
+ }
+
+ public void fatal(Object message, Throwable t)
+ {
+ log(Level.SEVERE, String.valueOf(message), t);
+ }
+
+ // From commons-logging
+ private void log(Level level, String msg, Throwable ex) {
+ if (log.isLoggable(level)) {
+ // Get the stack trace.
+ Throwable dummyException = new Throwable();
+ StackTraceElement locations[] = dummyException.getStackTrace();
+ // Caller will be the third element
+ String cname = "unknown";
+ String method = "unknown";
+ if (locations != null && locations.length > 3) {
+ StackTraceElement caller = locations[3];
+ cname = caller.getClassName();
+ method = caller.getMethodName();
+ }
+ if (ex == null) {
+ log.logp(level, cname, method, msg);
+ } else {
+ log.logp(level, cname, method, msg, ex);
+ }
+ }
+ }
+
+ public NDCProvider getNDCProvider()
+ {
+ return new JDKNDCProvider();
+ }
+
+ public MDCProvider getMDCProvider()
+ {
+ return new JDKMDCProvider();
+ }
+}
Index: 3rdParty_sources/jbossweb/org/jboss/logging/jdk/JDKMDCProvider.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/logging/jdk/JDKMDCProvider.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/logging/jdk/JDKMDCProvider.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,68 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.logging.jdk;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.logging.MDCProvider;
+
+/**
+ * MDC implementation for JDK logging.
+ *
+ * @author Jason T. Greene
+ */
+public class JDKMDCProvider implements MDCProvider
+{
+ private ThreadLocal> map = new ThreadLocal>();
+
+ public Object get(String key)
+ {
+ return map.get() == null ? null : map.get().get(key);
+ }
+
+ public Map getMap()
+ {
+ return map.get();
+ }
+
+ public void put(String key, Object value)
+ {
+ Map map = this.map.get();
+ if (map == null)
+ {
+ map = new HashMap();
+ this.map.set(map);
+ }
+
+ map.put(key, value);
+ }
+
+ public void remove(String key)
+ {
+ Map map = this.map.get();
+ if (map == null)
+ return;
+
+ map.remove(key);
+ }
+}
\ No newline at end of file
Index: 3rdParty_sources/jbossweb/org/jboss/logging/jdk/JDKNDCProvider.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/logging/jdk/JDKNDCProvider.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/logging/jdk/JDKNDCProvider.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,149 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.logging.jdk;
+
+import java.util.ArrayList;
+import java.util.EmptyStackException;
+import java.util.Stack;
+
+import org.jboss.logging.NDCProvider;
+
+/**
+ * NDC implementation for JDK logging
+ *
+ * @author Jason T. Greene
+ */
+public class JDKNDCProvider implements NDCProvider
+{
+ private class ArrayStack extends ArrayList
+ {
+ private static final long serialVersionUID = -8520038422243642840L;
+
+ public E pop()
+ {
+ int size = size();
+ if (size == 0)
+ throw new EmptyStackException();
+
+ return remove(size - 1);
+ }
+
+ public E peek()
+ {
+ int size = size();
+ if (size == 0)
+ throw new EmptyStackException();
+
+ return get(size - 1);
+ }
+
+ public void push(E val)
+ {
+ add(val);
+ }
+
+ public void setSize(int newSize)
+ {
+ int size = size();
+ if (newSize >= size || newSize < 0)
+ return;
+
+ removeRange(newSize, size);
+ }
+ }
+
+ private class Entry
+ {
+ private String merged;
+ private String current;
+
+ public Entry(String current)
+ {
+ this.merged = current;
+ this.current = current;
+ }
+
+ public Entry(Entry parent, String current)
+ {
+ this.merged = parent.merged + ' ' + current;
+ this.current = current;
+ }
+ }
+
+ private ThreadLocal> stack = new ThreadLocal>();
+
+ public void clear()
+ {
+ ArrayStack stack = this.stack.get();
+ if (stack != null)
+ stack.clear();
+ }
+
+ public String get()
+ {
+ ArrayStack stack = this.stack.get();
+
+ return stack == null || stack.isEmpty() ? null : stack.peek().merged;
+ }
+
+ public int getDepth()
+ {
+ ArrayStack stack = this.stack.get();
+
+ return stack == null ? 0 : stack.size();
+ }
+
+ public String peek()
+ {
+ ArrayStack stack = this.stack.get();
+
+ return stack == null || stack.isEmpty() ? "" : stack.peek().current;
+ }
+
+ public String pop()
+ {
+ ArrayStack stack = this.stack.get();
+
+ return stack == null || stack.isEmpty() ? "" : stack.pop().current;
+ }
+
+ public void push(String message)
+ {
+ ArrayStack stack = this.stack.get();
+
+ if (stack == null)
+ {
+ stack = new ArrayStack();
+ this.stack.set(stack);
+ }
+
+ stack.push(stack.isEmpty() ? new Entry(message) : new Entry(stack.peek(), message));
+ }
+
+ public void setMaxDepth(int maxDepth)
+ {
+ ArrayStack stack = this.stack.get();
+
+ if (stack != null)
+ stack.setSize(maxDepth);
+ }
+}
Index: 3rdParty_sources/jbossweb/org/jboss/servlet/http/HttpEvent.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/servlet/http/HttpEvent.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/servlet/http/HttpEvent.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,178 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.servlet.http;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * The HttpEvent interface, which indicates the type of the event that is
+ * being processed, as well as provides useful callbacks and utility objects.
+ */
+public interface HttpEvent {
+
+ /**
+ * Enumeration describing the major events that the container can invoke
+ * the EventHttpServlet event() method with:
+ *
+ * BEGIN - will be called at the beginning
+ * of the processing of the connection. It can be used to initialize any relevant
+ * fields using the request and response objects. Between the end of the processing
+ * of this event, and the beginning of the processing of the end or error events,
+ * it is possible to use the response object to write data on the open connection.
+ * Note that the response object and dependent OutputStream and Writer are
+ * not synchronized, so when they are accessed by multiple threads adequate
+ * synchronization is needed. After processing the initial event, the request
+ * is considered to be committed.
+ * EOF - The end of file of the input has been reached, and no further data is
+ * available. This event is sent because it can be difficult to detect otherwise.
+ * Following the processing of this event and the processing of any subsequent
+ * event, the event will be suspended.
+ * END - End may be called to end the processing of the request. Fields that have
+ * been initialized in the begin method should be reset. After this event has
+ * been processed, the request and response objects, as well as all their dependent
+ * objects will be recycled and used to process other requests. In particular,
+ * this event will be called if the HTTP session associated with the connection
+ * times out, if the web application is reloaded, if the server is shutdown, or
+ * if the connection was closed asynchronously.
+ * ERROR - Error will be called by the container in the case where an IO exception
+ * or a similar unrecoverable error occurs on the connection. Fields that have
+ * been initialized in the begin method should be reset. After this event has
+ * been processed, the request and response objects, as well as all their dependent
+ * objects will be recycled and used to process other requests.
+ * EVENT - Event will be called by the container after the resume() method is called,
+ * during which any operations can be performed, including closing the connection
+ * using the close() method.
+ * READ - This indicates that input data is available, and that at least one
+ * read can be made without blocking. The available and ready methods of the InputStream or
+ * Reader may be used to determine if there is a risk of blocking: the Servlet
+ * must continue reading while data is reported available. When encountering a read error,
+ * the Servlet should report it by propagating the exception properly. Throwing
+ * an exception will cause the error event to be invoked, and the connection
+ * will be closed.
+ * Alternately, it is also possible to catch any exception, perform clean up
+ * on any data structure the Servlet may be using, and using the close method
+ * of the event. It is not allowed to attempt reading data from the request
+ * object outside of the processing of this event, unless the suspend() method
+ * has been used.
+ * TIMEOUT - the connection timed out, but the connection will not be closed unless
+ * the servlet uses the close method of the event
+ * WRITE - Write is sent if the Servlet is using the ready method. This means that
+ * the connection is ready to receive data to be written out. This event will never
+ * be received if the Servlet is not using the ready() method, or if the ready()
+ * method always returns true.
+ *
+ */
+ public enum EventType { BEGIN, END, ERROR, EVENT, READ, EOF, TIMEOUT, WRITE }
+
+
+ /**
+ * Returns the HttpServletRequest.
+ *
+ * @return HttpServletRequest
+ */
+ public HttpServletRequest getHttpServletRequest();
+
+ /**
+ * Returns the HttpServletResponse.
+ *
+ * @return HttpServletResponse
+ */
+ public HttpServletResponse getHttpServletResponse();
+
+ /**
+ * Returns the event type.
+ *
+ * @return EventType
+ * @see #EventType
+ */
+ public EventType getType();
+
+ /**
+ * Ends the request, which marks the end of the event stream. This will send
+ * back to the client a notice that the server has no more data to send
+ * as part of this request. An END event will be sent to the Servlet.
+ *
+ * @throws IOException if an IO exception occurs
+ */
+ public void close() throws IOException;
+
+ /**
+ * This method sets the timeout in milliseconds of idle time on the connection.
+ * The timeout is reset every time data is received from the connection. If a timeout occurs, the
+ * Servlet will receive an TIMEOUT event which will not result in automatically closing
+ * the event (the event may be closed using the close() method).
+ *
+ * @param timeout The timeout in milliseconds for this connection, must be a positive value, larger than 0
+ */
+ public void setTimeout(int timeout);
+
+ /**
+ * Returns true when data may be read from the connection (the flag becomes false if no data
+ * is available to read). When the flag becomes false, the Servlet can attempt to read additional
+ * data, but it will block until data is available. This method is equivalent to
+ * Reader.ready() and (InputStream.available() > 0).
+ *
+ * @return boolean true if data can be read without blocking
+ */
+ public boolean isReadReady();
+
+ /**
+ * Returns true when data may be written to the connection (the flag becomes false
+ * when the client is unable to accept data fast enough). When the flag becomes false,
+ * the Servlet must stop writing data. If there's an attempt to flush additional data
+ * to the client and data still cannot be written immediately, an IOException will be
+ * thrown. If calling this method returns false, it will also
+ * request notification when the connection becomes available for writing again, and the
+ * Servlet will receive a write event.
+ *
+ * Note: If the Servlet is not using isWriteReady, and is writing its output inside the
+ * container threads (inside the event() method processing, for example), using this method
+ * is not mandatory, and writes will block until all bytes are written.
+ *
+ * @return boolean true if data can be written without blocking
+ */
+ public boolean isWriteReady();
+
+ /**
+ * Suspend processing of the connection until the configured timeout occurs,
+ * or resume() is called. In practice, this means the servlet will no longer
+ * receive read events. Reading should always be performed synchronously in
+ * the Tomcat threads unless the connection has been suspended.
+ */
+ public void suspend();
+
+ /**
+ * Resume will cause the Servlet container to send a generic event
+ * to the Servlet, where the request can be processed synchronously
+ * (for example, it is possible to use this to complete the request after
+ * some asynchronous processing is done). This also resumes read events
+ * if they have been disabled using suspend. It is then possible to call suspend
+ * again later. It is also possible to call resume without calling suspend before.
+ * This method must be called asynchronously.
+ */
+ public void resume();
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/servlet/http/HttpEventFilter.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/servlet/http/HttpEventFilter.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/servlet/http/HttpEventFilter.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.servlet.http;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.ServletException;
+
+/**
+ * An event filter, similar to regular filters, performs filtering tasks on either
+ * the request to a resource (an event driven Servlet), or on the response from a resource, or both.
+ */
+public interface HttpEventFilter extends Filter {
+
+
+ /**
+ * The doFilterEvent
method of the HttpEventFilter is called by the container
+ * each time a request/response pair is passed through the chain due
+ * to a client event for a resource at the end of the chain. The HttpEventFilterChain passed in to this
+ * method allows the Filter to pass on the event to the next entity in the
+ * chain.
+ * A typical implementation of this method would follow the following pattern:-
+ * 1. Examine the request
+ * 2. Optionally wrap the request object contained in the event with a custom implementation to
+ * filter content or headers for input filtering and pass a HttpEvent instance containing
+ * the wrapped request to the next filter
+ * 3. Optionally wrap the response object contained in the event with a custom implementation to
+ * filter content or headers for output filtering and pass a HttpEvent instance containing
+ * the wrapped request to the next filter
+ * 4. a) Either invoke the next entity in the chain using the HttpEventFilterChain
+ * object (chain.doFilterEvent()
),
+ * 4. b) or not pass on the request/response pair to the next entity in the
+ * filter chain to block the event processing
+ * 5. Directly set fields on the response after invocation of the next entity in the filter chain.
+ *
+ * @param event the event that is being processed. Another event may be passed along the chain.
+ * @param chain
+ * @throws IOException
+ * @throws ServletException
+ */
+ public void doFilterEvent(HttpEvent event, HttpEventFilterChain chain)
+ throws IOException, ServletException;
+
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/servlet/http/HttpEventFilterChain.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/servlet/http/HttpEventFilterChain.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/servlet/http/HttpEventFilterChain.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,47 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.servlet.http;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+/**
+ * A HttpEventFilterChain is an object provided by the Servlet container to the developer
+ * giving a view into the invocation chain of a filtered event for a resource. Filters
+ * use the HttpEventFilterChain to invoke the next filter in the chain, or if the calling filter
+ * is the last filter in the chain, to invoke the resource at the end of the chain.
+ */
+public interface HttpEventFilterChain {
+
+
+ /**
+ * Causes the next filter in the chain to be invoked, or if the calling filter is the last filter
+ * in the chain, causes the resource at the end of the chain to be invoked.
+ *
+ * @param event the event to pass along the chain.
+ */
+ public void doFilterEvent(HttpEvent event) throws IOException, ServletException;
+
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/servlet/http/HttpEventServlet.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/servlet/http/HttpEventServlet.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/servlet/http/HttpEventServlet.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,50 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.servlet.http;
+
+import java.io.IOException;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+
+/**
+ * This interface should be implemented by Servlets which would like to handle
+ * asynchronous IO, receiving events when data is available for reading, and
+ * being able to output data without the need for being invoked by the container.
+ * Note: When this interface is implemented, the service method of the Servlet will
+ * never be called, and will be replaced with a begin event.
+ */
+public interface HttpEventServlet extends Servlet
+{
+
+ /**
+ * Process the given IO event.
+ *
+ * @param event The event that will be processed
+ * @throws IOException
+ * @throws ServletException
+ */
+ public void event(HttpEvent event)
+ throws IOException, ServletException;
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/cluster/ClusterListener.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/cluster/ClusterListener.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/cluster/ClusterListener.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,1557 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+
+package org.jboss.web.cluster;
+
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import javax.management.ObjectName;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.TrustManagerFactory;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.ContainerEvent;
+import org.apache.catalina.ContainerListener;
+import org.apache.catalina.Context;
+import org.apache.catalina.Engine;
+import org.apache.catalina.Host;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleEvent;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.Server;
+import org.apache.catalina.ServerFactory;
+import org.apache.catalina.Service;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.core.StandardServer;
+import org.apache.catalina.util.StringManager;
+import org.apache.tomcat.util.IntrospectionUtils;
+import org.apache.tomcat.util.buf.CharChunk;
+import org.apache.tomcat.util.buf.UEncoder;
+import org.apache.tomcat.util.modeler.Registry;
+import org.jboss.logging.Logger;
+import org.jboss.web.cluster.advertise.AdvertiseListener;
+
+
+
+/**
+ * This listener communicates with a front end mod_cluster enabled proxy to
+ * automatically maintain the node configuration according to what is
+ * deployed.
+ */
+public class ClusterListener
+ implements LifecycleListener, ContainerListener {
+
+ protected static Logger log = Logger.getLogger(ClusterListener.class);
+
+ /**
+ * The string manager for this package.
+ */
+ protected StringManager sm =
+ StringManager.getManager(Constants.Package);
+
+
+ // -------------------------------------------------------------- Constants
+
+
+ protected enum State { OK, ERROR, DOWN };
+
+
+ // ----------------------------------------------------------------- Fields
+
+
+ /**
+ * URL encoder used to generate requests bodies.
+ */
+ protected UEncoder encoder = new UEncoder();
+
+
+ /**
+ * JMX registration information.
+ */
+ protected ObjectName oname;
+
+
+ /**
+ * Proxies.
+ */
+ protected Proxy[] proxies = new Proxy[0];
+
+
+ /**
+ * Socket factory.
+ */
+ protected JSSESocketFactory sslSocketFactory = null;
+
+
+ /**
+ * Active connections.
+ */
+ protected Socket[] connections = null;
+
+
+ /**
+ * Connection readers.
+ */
+ protected BufferedReader[] connectionReaders = null;
+
+
+ /**
+ * Connection writers.
+ */
+ protected BufferedWriter[] connectionWriters = null;
+
+
+ /**
+ * Initialization flag.
+ */
+ protected boolean init = false;
+
+
+ /**
+ * Add proxy list.
+ */
+ protected ArrayList addProxies = new ArrayList();
+
+
+ /**
+ * Remove proxy list.
+ */
+ protected ArrayList removeProxies = new ArrayList();
+
+
+ /**
+ * Advertise listener.
+ */
+ protected AdvertiseListener listener = null;
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * Receive advertisements from httpd proxies (default is to use advertisements
+ * if the proxyList is not set).
+ */
+ protected int advertise = -1;
+ public boolean getAdvertise() { return (advertise == 0) ? false : true; }
+ public void setAdvertise(boolean advertise) { this.advertise = advertise ? 1 : 0; }
+
+
+ /**
+ * Advertise group.
+ */
+ protected String advertiseGroupAddress = null;
+ public String getAdvertiseGroupAddress() { return advertiseGroupAddress; }
+ public void setAdvertiseGroupAddress(String advertiseGroupAddress) { this.advertiseGroupAddress = advertiseGroupAddress; }
+
+
+ /**
+ * Advertise port.
+ */
+ protected int advertisePort = -1;
+ public int getAdvertisePort() { return advertisePort; }
+ public void setAdvertisePort(int advertisePort) { this.advertisePort = advertisePort; }
+
+
+ /**
+ * Advertise security key.
+ */
+ protected String advertiseSecurityKey = null;
+ public String getAdvertiseSecurityKey() { return advertiseSecurityKey; }
+ public void setAdvertiseSecurityKey(String advertiseSecurityKey) { this.advertiseSecurityKey = advertiseSecurityKey; }
+
+
+ /**
+ * Proxy list, format "address:port,address:port".
+ */
+ protected String proxyList = null;
+ public String getProxyList() { return proxyList; }
+ public void setProxyList(String proxyList) { this.proxyList = proxyList; }
+
+
+ /**
+ * URL prefix.
+ */
+ protected String proxyURL = null;
+ public String getProxyURL() { return proxyURL; }
+ public void setProxyURL(String proxyURL) { this.proxyURL = proxyURL; }
+
+
+ /**
+ * Connection timeout for communication with the proxy.
+ */
+ protected int socketTimeout = 20000;
+ public int getSocketTimeout() { return socketTimeout; }
+ public void setSocketTimeout(int socketTimeout) { this.socketTimeout = socketTimeout; }
+
+
+ /**
+ * Domain parameter, which allows tying a jvmRoute to a particular domain.
+ */
+ protected String domain = null;
+ public String getDomain() { return domain; }
+ public void setDomain(String domain) { this.domain = domain; }
+
+
+ /**
+ * Allows controlling flushing of packets.
+ */
+ protected boolean flushPackets = false;
+ public boolean getFlushPackets() { return flushPackets; }
+ public void setFlushPackets(boolean flushPackets) { this.flushPackets = flushPackets; }
+
+
+ /**
+ * Time to wait before flushing packets.
+ */
+ protected int flushWait = -1;
+ public int getFlushWait() { return flushWait; }
+ public void setFlushWait(int flushWait) { this.flushWait = flushWait; }
+
+
+ /**
+ * Time to wait for a pong answer to a ping.
+ */
+ protected int ping = -1;
+ public int getPing() { return ping; }
+ public void setPing(int ping) { this.ping = ping; }
+
+
+ /**
+ * Soft maximum inactive connection count.
+ */
+ protected int smax = -1;
+ public int getSmax() { return smax; }
+ public void setSmax(int smax) { this.smax = smax; }
+
+
+ /**
+ * Maximum time on seconds for idle connections above smax.
+ */
+ protected int ttl = -1;
+ public int getTtl() { return ttl; }
+ public void setTtl(int ttl) { this.ttl = ttl; }
+
+
+ /**
+ * Maximum time on seconds for idle connections the proxy will wait to connect to the node.
+ */
+ protected int nodeTimeout = -1;
+ public int getNodeTimeout() { return nodeTimeout; }
+ public void setNodeTimeout(int nodeTimeout) { this.nodeTimeout = nodeTimeout; }
+
+
+ /**
+ * Name of the balancer.
+ */
+ protected String balancer = null;
+ public String getBalancer() { return balancer; }
+ public void setBalancer(String balancer) { this.balancer = balancer; }
+
+
+ /**
+ * Enables sticky sessions.
+ */
+ protected boolean stickySession = true;
+ public boolean getStickySession() { return stickySession; }
+ public void setStickySession(boolean stickySession) { this.stickySession = stickySession; }
+
+
+ /**
+ * Remove session when the request cannot be routed to the right node.
+ */
+ protected boolean stickySessionRemove = false;
+ public boolean getStickySessionRemove() { return stickySessionRemove; }
+ public void setStickySessionRemove(boolean stickySessionRemove) { this.stickySessionRemove = stickySessionRemove; }
+
+
+ /**
+ * Return an error when the request cannot be routed to the right node.
+ */
+ protected boolean stickySessionForce = true;
+ public boolean getStickySessionForce() { return stickySessionForce; }
+ public void setStickySessionForce(boolean stickySessionForce) { this.stickySessionForce = stickySessionForce; }
+
+
+ /**
+ * Timeout to wait for an available worker (default is no wait).
+ */
+ protected int workerTimeout = -1;
+ public int getWorkerTimeout() { return workerTimeout; }
+ public void setWorkerTimeout(int workerTimeout) { this.workerTimeout = workerTimeout; }
+
+
+ /**
+ * Maximum number of attempts to send the request to the backend server.
+ */
+ protected int maxAttempts = -1;
+ public int getMaxAttempts() { return maxAttempts; }
+ public void setMaxAttempts(int maxAttempts) { this.maxAttempts = maxAttempts; }
+
+
+ /**
+ * SSL client cert usage to connect to the proxy.
+ */
+ protected boolean ssl = false;
+ public boolean isSsl() { return ssl; }
+ public void setSsl(boolean ssl) { this.ssl = ssl; }
+
+
+ /**
+ * SSL ciphers.
+ */
+ protected String sslCiphers = null;
+ public String getSslCiphers() { return sslCiphers; }
+ public void setSslCiphers(String sslCiphers) { this.sslCiphers = sslCiphers; }
+
+
+ /**
+ * SSL protocol.
+ */
+ protected String sslProtocol = "TLS";
+ public String getSslProtocol() { return sslProtocol; }
+ public void setSslProtocol(String sslProtocol) { this.sslProtocol = sslProtocol; }
+
+
+ /**
+ * Certificate encoding algorithm.
+ */
+ protected String sslCertificateEncodingAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
+ public String getSslCertificateEncodingAlgorithm() { return sslCertificateEncodingAlgorithm; }
+ public void setSslCertificateEncodingAlgorithm(String sslCertificateEncodingAlgorithm) { this.sslCertificateEncodingAlgorithm = sslCertificateEncodingAlgorithm; }
+
+
+ /**
+ * SSL keystore.
+ */
+ protected String sslKeyStore = System.getProperty("user.home") + "/.keystore";
+ public String getSslKeyStore() { return sslKeyStore; }
+ public void setSslKeyStore(String sslKeyStore) { this.sslKeyStore = sslKeyStore; }
+
+
+ /**
+ * SSL keystore password.
+ */
+ protected String sslKeyStorePass = "changeit";
+ public String getSslKeyStorePass() { return sslKeyStorePass; }
+ public void setSslKeyStorePass(String sslKeyStorePass) { this.sslKeyStorePass = sslKeyStorePass; }
+
+
+ /**
+ * Keystore type.
+ */
+ protected String sslKeyStoreType = "JKS";
+ public String getSslKeyStoreType() { return sslKeyStoreType; }
+ public void setSslKeyStoreType(String sslKeyStoreType) { this.sslKeyStoreType = sslKeyStoreType; }
+
+
+ /**
+ * Keystore provider.
+ */
+ protected String sslKeyStoreProvider = null;
+ public String getSslKeyStoreProvider() { return sslKeyStoreProvider; }
+ public void setSslKeyStoreProvider(String sslKeyStoreProvider) { this.sslKeyStoreProvider = sslKeyStoreProvider; }
+
+
+ /**
+ * Truststore algorithm.
+ */
+ protected String sslTrustAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
+ public String getSslTrustAlgorithm() { return sslTrustAlgorithm; }
+ public void setSslTrustAlgorithm(String sslTrustAlgorithm) { this.sslTrustAlgorithm = sslTrustAlgorithm; }
+
+
+ /**
+ * Key alias.
+ */
+ protected String sslKeyAlias = null;
+ public String getSslKeyAlias() { return sslKeyAlias; }
+ public void setSslKeyAlias(String sslKeyAlias) { this.sslKeyAlias = sslKeyAlias; }
+
+
+ /**
+ * Certificate revocation list.
+ */
+ protected String sslCrlFile = null;
+ public String getSslCrlFile() { return sslCrlFile; }
+ public void setSslCrlFile(String sslCrlFile) { this.sslCrlFile = sslCrlFile; }
+
+
+ /**
+ * Trust max certificate length.
+ */
+ protected int sslTrustMaxCertLength = 5;
+ public int getSslTrustMaxCertLength() { return sslTrustMaxCertLength; }
+ public void setSslTrustMaxCertLength(int sslTrustMaxCertLength) { this.sslTrustMaxCertLength = sslTrustMaxCertLength; }
+
+
+ /**
+ * Trust store file.
+ */
+ protected String sslTrustStore = System.getProperty("javax.net.ssl.trustStore");
+ public String getSslTrustStore() { return sslTrustStore; }
+ public void setSslTrustStore(String sslTrustStore) { this.sslTrustStore = sslTrustStore; }
+
+
+ /**
+ * Trust store password.
+ */
+ protected String sslTrustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword");
+ public String getSslTrustStorePassword() { return sslTrustStorePassword; }
+ public void setSslTrustStorePassword(String sslTrustStorePassword) { this.sslTrustStorePassword = sslTrustStorePassword; }
+
+
+ /**
+ * Trust store type.
+ */
+ protected String sslTrustStoreType = System.getProperty("javax.net.ssl.trustStoreType");
+ public String getSslTrustStoreType() { return sslTrustStoreType; }
+ public void setSslTrustStoreType(String sslTrustStoreType) { this.sslTrustStoreType = sslTrustStoreType; }
+
+
+ /**
+ * Trust store provider.
+ */
+ protected String sslTrustStoreProvider = System.getProperty("javax.net.ssl.trustStoreProvider");
+ public String getSslTrustStoreProvider() { return sslTrustStoreProvider; }
+ public void setSslTrustStoreProvider(String sslTrustStoreProvider) { this.sslTrustStoreProvider = sslTrustStoreProvider; }
+
+
+ // ---------------------------------------------- LifecycleListener Methods
+
+
+ /**
+ * Acknowledge the occurrence of the specified event.
+ * Note: Will never be called when the listener is associated to a Server,
+ * since it is not a Container.
+ *
+ * @param event ContainerEvent that has occurred
+ */
+ public void containerEvent(ContainerEvent event) {
+
+ Container container = event.getContainer();
+ Object child = event.getData();
+ String type = event.getType();
+
+ if (type.equals(Container.ADD_CHILD_EVENT)) {
+ if (container instanceof Host) {
+ // Deploying a webapp
+ ((Lifecycle) child).addLifecycleListener(this);
+ addContext((Context) child, -1);
+ } else if (container instanceof Engine) {
+ // Deploying a host
+ container.addContainerListener(this);
+ }
+ } else if (type.equals(Container.REMOVE_CHILD_EVENT)) {
+ if (container instanceof Host) {
+ // Undeploying a webapp
+ ((Lifecycle) child).removeLifecycleListener(this);
+ removeContext((Context) child, -1);
+ } else if (container instanceof Engine) {
+ // Undeploying a host
+ container.removeContainerListener(this);
+ }
+ }
+
+ }
+
+
+ /**
+ * Primary entry point for startup and shutdown events.
+ *
+ * @param event The event that has occurred
+ */
+ public void lifecycleEvent(LifecycleEvent event) {
+
+ Object source = event.getLifecycle();
+
+ if (Lifecycle.START_EVENT.equals(event.getType())) {
+ if (source instanceof Context) {
+ // Start a webapp
+ startContext((Context) source, -1);
+ } else {
+ return;
+ }
+ } else if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
+ if (source instanceof Server) {
+
+ if (this.proxyList == null) {
+ if (advertise != 0) {
+ proxies = new Proxy[0];
+ startListener();
+ } else {
+ // Default to a httpd on localhost on the default port
+ proxies = new Proxy[1];
+ proxies[0] = new Proxy();
+ }
+ } else {
+ ArrayList proxyList = new ArrayList();
+ StringTokenizer tok = new StringTokenizer(this.proxyList, ",");
+ while (tok.hasMoreTokens()) {
+ String token = tok.nextToken().trim();
+ Proxy proxy = new Proxy();
+ int pos = token.indexOf(':');
+ String address = null;
+ if (pos < 0) {
+ address = token;
+ } else if (pos == 0) {
+ address = null;
+ proxy.port = Integer.parseInt(token.substring(1));
+ } else {
+ address = token.substring(0, pos);
+ proxy.port = Integer.parseInt(token.substring(pos + 1));
+ }
+ try {
+ if (address != null) {
+ proxy.address = InetAddress.getByName(address);
+ }
+ } catch (Exception e) {
+ log.error(sm.getString("clusterListener.error.invalidHost", address), e);
+ continue;
+ }
+ proxyList.add(proxy);
+ }
+ proxies = proxyList.toArray(new Proxy[0]);
+ }
+
+ connections = new Socket[proxies.length];
+ connectionReaders = new BufferedReader[proxies.length];
+ connectionWriters = new BufferedWriter[proxies.length];
+
+ sslInit();
+ startServer((Server) source, -1);
+
+ if (advertise == 1) {
+ startListener();
+ }
+
+ init = true;
+ } else {
+ return;
+ }
+ } else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
+ if (source instanceof Context) {
+ // Stop a webapp
+ stopContext((Context) source, -1);
+ } else if (source instanceof Server) {
+ stopListener();
+ stopServer((Server) source, -1);
+ for (int i = 0; i < connections.length; i++) {
+ closeConnection(i);
+ }
+ init = false;
+ } else {
+ return;
+ }
+ } else if (Lifecycle.PERIODIC_EVENT.equals(event.getType())) {
+ if (init && source instanceof Engine) {
+ status((Engine) source);
+ }
+ }
+
+ }
+
+
+ /**
+ * Add proxy.
+ */
+ public void addProxy(String address) {
+ int pos = address.indexOf(':');
+ String host = null;
+ int port = 0;
+ if (pos < 0) {
+ host = address;
+ } else if (pos == 0) {
+ host = null;
+ port = Integer.parseInt(address.substring(1));
+ } else {
+ host = address.substring(0, pos);
+ port = Integer.parseInt(address.substring(pos + 1));
+ }
+ addProxy(host, port);
+ }
+
+
+ /**
+ * Add proxy.
+ */
+ public synchronized void addProxy(String host, int port) {
+ Proxy proxy = new Proxy();
+ try {
+ proxy.address = InetAddress.getByName(host);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ if (port > 0) {
+ proxy.port = port;
+ }
+ proxy.state = State.ERROR;
+ addProxies.add(proxy);
+ }
+
+
+ /**
+ * Remove proxy.
+ */
+ public synchronized void removeProxy(String host, int port) {
+ Proxy proxy = new Proxy();
+ try {
+ proxy.address = InetAddress.getByName(host);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ if (port > 0) {
+ proxy.port = port;
+ }
+ removeProxies.add(proxy);
+ }
+
+
+ /**
+ * Retrieves the full proxy configuration. To be used through JMX or similar.
+ *
+ * response: HTTP/1.1 200 OK
+ * response:
+ * node: [1:1] JVMRoute: node1 Domain: [bla] Host: 127.0.0.1 Port: 8009 Type: ajp
+ * host: 1 [] vhost: 1 node: 1
+ * context: 1 [/] vhost: 1 node: 1 status: 1
+ * context: 2 [/myapp] vhost: 1 node: 1 status: 1
+ * context: 3 [/host-manager] vhost: 1 node: 1 status: 1
+ * context: 4 [/docs] vhost: 1 node: 1 status: 1
+ * context: 5 [/manager] vhost: 1 node: 1 status: 1
+ *
+ * @return the proxy confguration
+ */
+ public String getProxyConfiguration() {
+ HashMap parameters = new HashMap();
+ // Send DUMP * request
+ Proxy[] local = proxies;
+ StringBuffer result = new StringBuffer();
+ for (int i = 0; i < local.length; i++) {
+ result.append("Proxy[").append(i).append("]: [").append(local[i].address)
+ .append(':').append(local[i].port).append("]: \r\n");
+ result.append(sendRequest("DUMP", true, parameters, i));
+ result.append("\r\n");
+ }
+ return result.toString();
+ }
+ /**
+ * Retrieves the full proxy info message.
+ *
+ *
+ * @return the proxy confguration
+ */
+ public String getProxyInfo() {
+ HashMap parameters = new HashMap();
+ // Send INFO * request
+ Proxy[] local = proxies;
+ StringBuffer result = new StringBuffer();
+ for (int i = 0; i < local.length; i++) {
+ result.append("Proxy[").append(i).append("]: [").append(local[i].address)
+ .append(':').append(local[i].port).append("]: \r\n");
+ result.append(sendRequest("INFO", true, parameters, i));
+ result.append("\r\n");
+ }
+ return result.toString();
+ }
+
+
+ /**
+ * Reset a DOWN connection to the proxy up to ERROR, where the configuration will
+ * be refreshed. To be used through JMX or similar.
+ */
+ public void reset() {
+ Proxy[] local = proxies;
+ for (int i = 0; i < local.length; i++) {
+ if (local[i].state == State.DOWN) {
+ local[i].state = State.ERROR;
+ }
+ }
+ }
+
+
+ /**
+ * Refresh configuration. To be used through JMX or similar.
+ */
+ public void refresh() {
+ // Set as error, and the periodic event will refresh the configuration
+ Proxy[] local = proxies;
+ for (int i = 0; i < local.length; i++) {
+ if (local[i].state == State.OK) {
+ local[i].state = State.ERROR;
+ }
+ }
+ }
+
+
+ /**
+ * Disable all webapps for all engines. To be used through JMX or similar.
+ */
+ public boolean disable() {
+ Service[] services = ServerFactory.getServer().findServices();
+ for (int i = 0; i < services.length; i++) {
+ Engine engine = (Engine) services[i].getContainer();
+ HashMap parameters = new HashMap();
+ parameters.put("JVMRoute", engine.getJvmRoute());
+ // Send DISABLE-APP * request
+ sendRequest("DISABLE-APP", true, parameters);
+ }
+ return (proxies[0].state == State.OK);
+ }
+
+
+ /**
+ * Enable all webapps for all engines. To be used through JMX or similar.
+ */
+ public boolean enable() {
+ Service[] services = ServerFactory.getServer().findServices();
+ for (int i = 0; i < services.length; i++) {
+ Engine engine = (Engine) services[i].getContainer();
+ HashMap parameters = new HashMap();
+ parameters.put("JVMRoute", engine.getJvmRoute());
+ // Send ENABLE-APP * request
+ sendRequest("ENABLE-APP", true, parameters);
+ }
+ return (proxies[0].state == State.OK);
+ }
+
+
+ /**
+ * Start the advertise listener.
+ */
+ protected void startListener() {
+ listener = new AdvertiseListener(this);
+ if (advertiseGroupAddress != null) {
+ listener.setGroupAddress(advertiseGroupAddress);
+ }
+ if (advertisePort > 0) {
+ listener.setAdvertisePort(advertisePort);
+ }
+ try {
+ if (advertiseSecurityKey != null) {
+ listener.setSecurityKey(advertiseSecurityKey);
+ }
+ listener.start();
+ } catch (IOException e) {
+ log.error(sm.getString("clusterListener.error.startListener"), e);
+ } catch (NoSuchAlgorithmException e) {
+ // Should never happen
+ log.error(sm.getString("clusterListener.error.startListener"), e);
+ }
+ }
+
+
+ /**
+ * Stop the advertise listener.
+ */
+ protected void stopListener() {
+ if (listener != null) {
+ try {
+ listener.destroy();
+ } catch (IOException e) {
+ log.error(sm.getString("clusterListener.error.stopListener"), e);
+ }
+ listener = null;
+ }
+ }
+
+
+ /**
+ * Send commands to the front end server assocaited with the startup of the
+ * node.
+ */
+ protected void startServer(Server server, int pos) {
+
+ // JMX registration
+ if (oname==null) {
+ try {
+ oname = new ObjectName(((StandardServer) server).getDomain() + ":type=ClusterListener");
+ Registry.getRegistry(null, null).registerComponent(this, oname, null);
+ } catch (Exception e) {
+ log.error(sm.getString("clusterListener.error.jmxRegister"), e);
+ }
+ }
+
+ Service[] services = server.findServices();
+ for (int i = 0; i < services.length; i++) {
+ services[i].getContainer().addContainerListener(this);
+
+ Engine engine = (Engine) services[i].getContainer();
+ ((Lifecycle) engine).addLifecycleListener(this);
+ Connector connector = findProxyConnector(engine.getService().findConnectors());
+ InetAddress localAddress =
+ (InetAddress) IntrospectionUtils.getProperty(connector.getProtocolHandler(), "address");
+ if ((engine.getJvmRoute() == null || localAddress == null) && proxies.length > 0) {
+ // Automagical JVM route (address + port + engineName)
+ try {
+ if (localAddress == null) {
+ Socket connection = getConnection(0);
+ localAddress = connection.getLocalAddress();
+ if (localAddress != null) {
+ IntrospectionUtils.setProperty(connector.getProtocolHandler(), "address", localAddress.getHostAddress());
+ } else {
+ // Should not happen
+ IntrospectionUtils.setProperty(connector.getProtocolHandler(), "address", "127.0.0.1");
+ }
+ log.info(sm.getString("clusterListener.address", localAddress.getHostAddress()));
+ }
+ if (engine.getJvmRoute() == null) {
+ String hostName = null;
+ if (localAddress != null) {
+ hostName = localAddress.getHostName();
+ } else {
+ // Fallback
+ hostName = "127.0.0.1";
+ }
+ String jvmRoute = hostName + ":" + connector.getPort() + ":" + engine.getName();
+ engine.setJvmRoute(jvmRoute);
+ log.info(sm.getString("clusterListener.jvmRoute", engine.getName(), jvmRoute));
+ }
+ } catch (Exception e) {
+ proxies[0].state = State.ERROR;
+ log.info(sm.getString("clusterListener.error.addressJvmRoute"), e);
+ return;
+ }
+ }
+
+ config(engine, pos);
+ Container[] children = engine.findChildren();
+ for (int j = 0; j < children.length; j++) {
+ children[j].addContainerListener(this);
+ Container[] children2 = children[j].findChildren();
+ for (int k = 0; k < children2.length; k++) {
+ ((Lifecycle) children2[k]).addLifecycleListener(this);
+ addContext((Context) children2[k], pos);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Send commands to the front end server associated with the shutdown of the
+ * node.
+ */
+ protected void stopServer(Server server, int pos) {
+
+ // JMX unregistration
+ if (oname==null) {
+ try {
+ Registry.getRegistry(null, null).unregisterComponent(oname);
+ } catch (Exception e) {
+ log.error(sm.getString("clusterListener.error.jmxUnregister"), e);
+ }
+ }
+
+ Service[] services = server.findServices();
+ for (int i = 0; i < services.length; i++) {
+ services[i].getContainer().removeContainerListener(this);
+ ((Lifecycle) services[i].getContainer()).removeLifecycleListener(this);
+ removeAll((Engine) services[i].getContainer(), pos);
+ Container[] children = services[i].getContainer().findChildren();
+ for (int j = 0; j < children.length; j++) {
+ children[j].removeContainerListener(this);
+ Container[] children2 = children[j].findChildren();
+ for (int k = 0; k < children2.length; k++) {
+ ((Lifecycle) children2[k]).removeLifecycleListener(this);
+ removeContext((Context) children2[k], pos);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Reset configuration for a particular proxy following an error.
+ */
+ protected void reset(int pos) {
+
+ Service[] services = ServerFactory.getServer().findServices();
+ for (int i = 0; i < services.length; i++) {
+ Engine engine = (Engine) services[i].getContainer();
+ removeAll((Engine) services[i].getContainer(), pos);
+ config(engine, pos);
+ Container[] children = engine.findChildren();
+ for (int j = 0; j < children.length; j++) {
+ Container[] children2 = children[j].findChildren();
+ for (int k = 0; k < children2.length; k++) {
+ addContext((Context) children2[k], pos);
+ }
+ }
+ }
+
+ }
+
+
+ /**
+ * Send the configuration for the specified engine to the proxy.
+ *
+ * @param engine
+ */
+ protected void config(Engine engine, int pos) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("clusterListener.config", engine.getName()));
+ }
+ // Collect configuration from the connectors and service and call CONFIG
+ Connector connector = findProxyConnector(engine.getService().findConnectors());
+ HashMap parameters = new HashMap();
+ parameters.put("JVMRoute", engine.getJvmRoute());
+ boolean reverseConnection =
+ Boolean.TRUE.equals(IntrospectionUtils.getProperty(connector.getProtocolHandler(), "reverseConnection"));
+ boolean ssl =
+ Boolean.TRUE.equals(IntrospectionUtils.getProperty(connector.getProtocolHandler(), "SSLEnabled"));
+ boolean ajp = ((String) IntrospectionUtils.getProperty(connector.getProtocolHandler(), "name")).startsWith("ajp-");
+
+ if (reverseConnection) {
+ parameters.put("Reversed", "true");
+ }
+ parameters.put("Host", getAddress(connector));
+ parameters.put("Port", "" + connector.getPort());
+ if (ajp) {
+ parameters.put("Type", "ajp");
+ } else if (ssl) {
+ parameters.put("Type", "https");
+ } else {
+ parameters.put("Type", "http");
+ }
+
+ // Other configuration parameters
+ if (domain != null) {
+ parameters.put("Domain", domain);
+ }
+ if (flushPackets) {
+ parameters.put("flushpackets", "On");
+ }
+ if (flushWait != -1) {
+ parameters.put("flushwait", "" + flushWait);
+ }
+ if (ping != -1) {
+ parameters.put("ping", "" + ping);
+ }
+ if (smax != -1) {
+ parameters.put("smax", "" + smax);
+ }
+ if (ttl != -1) {
+ parameters.put("ttl", "" + ttl);
+ }
+ if (nodeTimeout != -1) {
+ parameters.put("Timeout", "" + nodeTimeout);
+ }
+ if (balancer != null) {
+ parameters.put("Balancer", balancer);
+ }
+ if (!stickySession) {
+ parameters.put("StickySession", "No");
+ }
+ if (!org.apache.catalina.Globals.SESSION_COOKIE_NAME.equals("JSESSIONID")) {
+ parameters.put("StickySessionCookie", org.apache.catalina.Globals.SESSION_COOKIE_NAME);
+ }
+ if (!org.apache.catalina.Globals.SESSION_PARAMETER_NAME.equals("jsessionid")) {
+ parameters.put("StickySessionPath", org.apache.catalina.Globals.SESSION_PARAMETER_NAME);
+ }
+ if (stickySessionRemove) {
+ parameters.put("StickSessionRemove", "Yes");
+ }
+ if (!stickySessionForce) {
+ parameters.put("StickySessionForce", "No");
+ }
+ if (workerTimeout != -1) {
+ parameters.put("WaitWorker", "" + workerTimeout);
+ }
+ if (maxAttempts != -1) {
+ parameters.put("Maxattempts", "" + maxAttempts);
+ }
+
+ // Send CONFIG request
+ sendRequest("CONFIG", false, parameters, pos);
+ }
+
+
+ /**
+ * Remove all contexts from the specified engine.
+ *
+ * @param engine
+ */
+ protected void removeAll(Engine engine, int pos) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("clusterListener.stop", engine.getName()));
+ }
+
+ // JVMRoute can be null here if nothing was ever initialized
+ if (engine.getJvmRoute() != null) {
+ HashMap parameters = new HashMap();
+ parameters.put("JVMRoute", engine.getJvmRoute());
+
+ // Send REMOVE-APP * request
+ sendRequest("REMOVE-APP", true, parameters, pos);
+ }
+ }
+
+
+ /**
+ * Send a periodic status request. If in error state, the listener will attempt to refresh
+ * the configuration on the front end server.
+ *
+ * @param engine
+ */
+ protected synchronized void status(Engine engine) {
+
+ // Check to add or remove proxies, and rebuild a new list if needed
+ if (!addProxies.isEmpty() || !removeProxies.isEmpty()) {
+ ArrayList currentProxies = new ArrayList();
+ for (int i = 0; i < proxies.length; i++) {
+ currentProxies.add(proxies[i]);
+ }
+ for (int i = 0; i < addProxies.size(); i++) {
+ if (!currentProxies.contains(addProxies.get(i))) {
+ currentProxies.add(addProxies.get(i));
+ }
+ }
+ for (int i = 0; i < removeProxies.size(); i++) {
+ if (currentProxies.contains(removeProxies.get(i))) {
+ currentProxies.remove(removeProxies.get(i));
+ }
+ }
+ addProxies.clear();
+ removeProxies.clear();
+ proxies = currentProxies.toArray(new Proxy[0]);
+ // Reset all connections
+ if (connections != null) {
+ for (int i = 0; i < connections.length; i++) {
+ closeConnection(i);
+ }
+ }
+ connections = new Socket[proxies.length];
+ connectionReaders = new BufferedReader[proxies.length];
+ connectionWriters = new BufferedWriter[proxies.length];
+ }
+
+ Proxy[] local = proxies;
+ for (int i = 0; i < local.length; i++) {
+ if (local[i].state == State.ERROR) {
+ local[i].state = State.OK;
+ // Something went wrong in a status at some point, so fully restore the configuration
+ reset(i);
+ } else if (local[i].state == State.OK) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("clusterListener.status", engine.getName()));
+ }
+ HashMap parameters = new HashMap();
+ parameters.put("JVMRoute", engine.getJvmRoute());
+ parameters.put("Load", "1");
+ // Send STATUS request
+ sendRequest("STATUS", false, parameters, i);
+ }
+ }
+ }
+
+
+ /**
+ * Add a new context.
+ *
+ * @param context
+ */
+ protected void addContext(Context context, int pos) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("clusterListener.context.enable", context.getPath(), context.getParent().getName(), ((StandardContext) context).getState()));
+ }
+
+ HashMap parameters = new HashMap();
+ parameters.put("JVMRoute", getJvmRoute(context));
+ parameters.put("Context", ("".equals(context.getPath())) ? "/" : context.getPath());
+ parameters.put("Alias", getHost(context));
+
+ // Send ENABLE-APP if state is started
+ if (context.isStarted()) {
+ sendRequest("ENABLE-APP", false, parameters, pos);
+ }
+ }
+
+
+ /**
+ * Remove a context.
+ *
+ * @param context
+ */
+ protected void removeContext(Context context, int pos) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("clusterListener.context.disable", context.getPath(), context.getParent().getName(), ((StandardContext) context).getState()));
+ }
+
+ HashMap parameters = new HashMap();
+ String jvmRoute = getJvmRoute(context);
+ // JVMRoute can be null here if nothing was ever initialized
+ if (jvmRoute != null) {
+ parameters.put("JVMRoute", jvmRoute);
+ parameters.put("Context", ("".equals(context.getPath())) ? "/" : context.getPath());
+ parameters.put("Alias", getHost(context));
+
+ // Send REMOVE-APP
+ sendRequest("REMOVE-APP", false, parameters, pos);
+ }
+ }
+
+
+ /**
+ * Start a context.
+ *
+ * @param context
+ */
+ protected void startContext(Context context, int pos) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("clusterListener.context.start", context.getPath(), context.getParent().getName()));
+ }
+
+ HashMap parameters = new HashMap();
+ parameters.put("JVMRoute", getJvmRoute(context));
+ parameters.put("Context", ("".equals(context.getPath())) ? "/" : context.getPath());
+ parameters.put("Alias", getHost(context));
+
+ // Send ENABLE-APP
+ sendRequest("ENABLE-APP", false, parameters, pos);
+ }
+
+
+ /**
+ * Stop a context.
+ *
+ * @param context
+ */
+ protected void stopContext(Context context, int pos) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("clusterListener.context.stop", context.getPath(), context.getParent().getName()));
+ }
+
+ HashMap parameters = new HashMap();
+ parameters.put("JVMRoute", getJvmRoute(context));
+ parameters.put("Context", ("".equals(context.getPath())) ? "/" : context.getPath());
+ parameters.put("Alias", getHost(context));
+
+ // Send STOP-APP
+ sendRequest("STOP-APP", false, parameters, pos);
+ }
+
+
+ /**
+ * Return the JvmRoute for the specified context.
+ *
+ * @param context
+ * @return
+ */
+ protected String getJvmRoute(Context context) {
+ return ((Engine) context.getParent().getParent()).getJvmRoute();
+ }
+
+
+ /**
+ * Return the host and its alias list with which the context is associated.
+ *
+ * @param context
+ * @return
+ */
+ protected String getHost(Context context) {
+ StringBuffer result = new StringBuffer();
+ Host host = (Host) context.getParent();
+ result.append(host.getName());
+ String[] aliases = host.findAliases();
+ for (int i = 0; i < aliases.length; i++) {
+ result.append(',');
+ result.append(aliases[i]);
+ }
+ return result.toString();
+ }
+
+
+ /**
+ * Find the most likely connector the proxy server should connect to, or
+ * accept connections from.
+ *
+ * @param connectors
+ * @return
+ */
+ protected Connector findProxyConnector(Connector[] connectors) {
+ int pos = 0;
+ int maxThreads = 0;
+ for (int i = 0; i < connectors.length; i++) {
+ if (connectors[i].getProtocol().startsWith("AJP")) {
+ // Return any AJP connector found
+ return connectors[i];
+ }
+ if (Boolean.TRUE.equals(IntrospectionUtils.getProperty(connectors[i].getProtocolHandler(), "reverseConnection"))) {
+ return connectors[i];
+ }
+ Integer mt = (Integer) IntrospectionUtils.getProperty(connectors[i].getProtocolHandler(), "maxThreads");
+ if (mt.intValue() > maxThreads) {
+ maxThreads = mt.intValue();
+ pos = i;
+ }
+ }
+ // If no AJP connector and no reverse, return the connector with the most threads
+ return connectors[pos];
+ }
+
+
+ /**
+ * Return the address on which the connector is bound.
+ *
+ * @param connector
+ * @return
+ */
+ protected String getAddress(Connector connector) {
+ InetAddress inetAddress =
+ (InetAddress) IntrospectionUtils.getProperty(connector.getProtocolHandler(), "address");
+ if (inetAddress == null) {
+ // Should not happen
+ return "127.0.0.1";
+ } else {
+ return inetAddress.getHostAddress();
+ }
+ }
+
+
+ /**
+ * Send HTTP request, with the specified list of parameters. If an IO error occurs, the error state will
+ * be set. If the front end server reports an error, will mark as error state. Other unexpected exceptions
+ * will be thrown and the error state will be set.
+ *
+ * @param command
+ * @param wildcard
+ * @param parameters
+ * @return the response body as a String; null if in error state or a normal error occurs
+ */
+ protected void sendRequest(String command, boolean wildcard, HashMap parameters) {
+ sendRequest(command, wildcard, parameters, -1);
+ }
+
+ protected synchronized String sendRequest(String command, boolean wildcard, HashMap parameters, int pos) {
+
+ BufferedReader reader = null;
+ BufferedWriter writer = null;
+ CharChunk body = null;
+
+ // First, encode the POST body
+ try {
+ body = encoder.encodeURL("", 0, 0);
+ body.recycle();
+ Iterator keys = parameters.keySet().iterator();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ String value = parameters.get(key);
+ if (value == null) {
+ throw new IllegalArgumentException(sm.getString("clusterListener.error.nullAttribute", key));
+ }
+ body = encoder.encodeURL(key, 0, key.length());
+ body.append('=');
+ if (value != null) {
+ body = encoder.encodeURL(value, 0, value.length());
+ }
+ if (keys.hasNext()) {
+ body.append('&');
+ }
+ }
+ } catch (IOException e) {
+ body.recycle();
+ // Error encoding URL, should not happen
+ throw new IllegalArgumentException(e);
+ }
+
+ int start = 0;
+ int end = proxies.length;
+ if (pos != -1) {
+ start = pos;
+ end = pos + 1;
+ }
+
+ for (int i = start; i < end; i++) {
+
+ // If there was an error, do nothing until the next periodic event, where the whole configuration
+ // will be refreshed
+ if (proxies[i].state != State.OK) {
+ continue;
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("clusterListener.request", command, wildcard, proxies[i]));
+ }
+
+ try {
+
+ // Then, connect to the proxy
+ getConnection(i);
+ writer = getConnectionWriter(i);
+ // Check connection to see if it is still alive (not really allowed,
+ // but httpd deals with the extra CRLF)
+ try {
+ writer.write("\r\n");
+ writer.flush();
+ } catch (IOException e) {
+ // Get a new connection; if it fails this second time, it is an error
+ closeConnection(i);
+ getConnection(i);
+ writer = getConnectionWriter(i);
+ }
+
+ // Generate and write request
+ String url = proxyURL;
+ if (url == null) {
+ url = (wildcard) ? "/*" : "/";
+ } else {
+ if (url.endsWith("/") && wildcard) {
+ url = url + "*";
+ } else if (wildcard) {
+ url = url + "/*";
+ }
+ }
+ String requestLine = command + " " + url + " HTTP/1.0";
+ writer.write(requestLine);
+ writer.write("\r\n");
+ writer.write("Content-Length: " + body.getLength() + "\r\n");
+ writer.write("User-Agent: ClusterListener/1.0\r\n");
+ writer.write("Connection: Keep-Alive\r\n");
+ writer.write("\r\n");
+ writer.write(body.getBuffer(), body.getStart(), body.getLength());
+ writer.write("\r\n");
+ writer.flush();
+
+ // Read the response to a string
+ reader = getConnectionReader(i);
+ // Read the first response line and skip the rest of the HTTP header
+ String responseStatus = reader.readLine();
+ // Parse the line, which is formed like HTTP/1.x YYY Message
+ int status = 500;
+ String version = "0";
+ String message = null;
+ String errorType = null;
+ int contentLength = 0;
+ if (responseStatus != null) {
+ try {
+ responseStatus = responseStatus.substring(responseStatus.indexOf(' ') + 1, responseStatus.indexOf(' ', responseStatus.indexOf(' ') + 1));
+ status = Integer.parseInt(responseStatus);
+ String header = reader.readLine();
+ while (!"".equals(header)) {
+ int colon = header.indexOf(':');
+ String headerName = header.substring(0, colon).trim();
+ String headerValue = header.substring(colon + 1).trim();
+ if ("version".equalsIgnoreCase(headerName)) {
+ version = headerValue;
+ } else if ("type".equalsIgnoreCase(headerName)) {
+ errorType = headerValue;
+ } else if ("mess".equalsIgnoreCase(headerName)) {
+ message = headerValue;
+ } else if ("content-length".equalsIgnoreCase(headerName)) {
+ contentLength = Integer.parseInt(headerValue);
+ }
+ header = reader.readLine();
+ }
+ } catch (Exception e) {
+ log.info(sm.getString("clusterListener.error.parse", command), e);
+ }
+ }
+
+ // Mark as error if the front end server did not return 200; the configuration will
+ // be refreshed during the next periodic event
+ if (status == 200) {
+ // Read the request body
+ StringBuffer result = new StringBuffer();
+ if (contentLength > 0) {
+ int thisTime = contentLength;
+ char[] buf = new char[512];
+ while (contentLength > 0) {
+ thisTime = (contentLength > buf.length) ? buf.length : contentLength;
+ int n = reader.read(buf, 0, thisTime);
+ if (n <= 0) {
+ break;
+ } else {
+ result.append(buf, 0, n);
+ contentLength -= n;
+ }
+ }
+ }
+ if (pos != -1) {
+ return result.toString();
+ }
+ } else {
+ if ("SYNTAX".equals(errorType)) {
+ // Syntax error means the protocol is incorrect, which cannot be automatically fixed
+ proxies[i].state = State.DOWN;
+ log.error(sm.getString("clusterListener.error.syntax", command, proxies[i], errorType, message));
+ } else {
+ proxies[i].state = State.ERROR;
+ log.error(sm.getString("clusterListener.error.other", command, proxies[i], errorType, message));
+ }
+ }
+
+ } catch (IOException e) {
+ // Most likely this is a connection error with the proxy
+ proxies[i].state = State.ERROR;
+ log.info(sm.getString("clusterListener.error.io", command, proxies[i]), e);
+ } finally {
+ // If there's an error of any sort, or if the proxy did not return 200, it is an error
+ if (proxies[i].state != State.OK) {
+ closeConnection(i);
+ }
+ }
+
+ }
+
+ return null;
+
+ }
+
+
+ /**
+ * SSL init.
+ */
+ protected void sslInit() {
+ if (ssl) {
+ sslSocketFactory = new JSSESocketFactory(this);
+ }
+ }
+
+
+ /**
+ * Return a reader to the proxy.
+ */
+ protected Socket getConnection(int i)
+ throws IOException {
+ if (connections[i] == null) {
+ InetAddress address = (proxies[i].address == null) ? InetAddress.getLocalHost() : proxies[i].address;
+ if (ssl) {
+ connections[i] = sslSocketFactory.createSocket(address, proxies[i].port);
+ } else {
+ connections[i] = new Socket(address, proxies[i].port);
+ }
+ connections[i].setSoTimeout(socketTimeout);
+ }
+ return connections[i];
+ }
+
+
+ /**
+ * Return a reader to the proxy.
+ */
+ protected BufferedReader getConnectionReader(int i)
+ throws IOException {
+ if (connectionReaders[i] == null) {
+ connectionReaders[i] = new BufferedReader(new InputStreamReader(connections[i].getInputStream()));
+ }
+ return connectionReaders[i];
+ }
+
+
+ /**
+ * Return a writer to the proxy.
+ */
+ protected BufferedWriter getConnectionWriter(int i)
+ throws IOException {
+ if (connectionWriters[i] == null) {
+ connectionWriters[i] = new BufferedWriter(new OutputStreamWriter(connections[i].getOutputStream()));
+ }
+ return connectionWriters[i];
+ }
+
+
+ /**
+ * Close connection.
+ */
+ protected void closeConnection(int i) {
+ try {
+ if (connectionReaders[i] != null) {
+ connectionReaders[i].close();
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+ connectionReaders[i] = null;
+ try {
+ if (connectionWriters[i] != null) {
+ connectionWriters[i].close();
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+ connectionWriters[i] = null;
+ try {
+ if (connections[i] != null) {
+ connections[i].close();
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+ connections[i] = null;
+ }
+
+
+ // ------------------------------------------------------ Proxy Inner Class
+
+
+ /**
+ * This class represents a front-end httpd server.
+ */
+ protected static class Proxy {
+ public InetAddress address = null;
+ public int port = 8000;
+ public State state = State.OK;
+
+ public String toString() {
+ if (address == null) {
+ return ":" + port;
+ } else {
+ return address.getHostAddress() + ":" + port;
+ }
+ }
+
+ public boolean equals(Object o) {
+ if (o instanceof Proxy) {
+ Proxy compare = (Proxy) o;
+ if (port != compare.port) {
+ return false;
+ }
+ if (compare.address == null) {
+ if (address == null) {
+ return true;
+ }
+ } else if ((compare.address.equals(address)) && port == compare.port) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ }
+
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/cluster/Constants.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/cluster/Constants.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/cluster/Constants.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,31 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+
+package org.jboss.web.cluster;
+
+
+public class Constants {
+
+ public static final String Package = "org.jboss.web.cluster";
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/cluster/JSSEKeyManager.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/cluster/JSSEKeyManager.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/cluster/JSSEKeyManager.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jboss.web.cluster;
+
+import java.net.Socket;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.X509KeyManager;
+
+/**
+ * X509KeyManager which allows selection of a specific keypair and certificate
+ * chain (identified by their keystore alias name) to be used by the server to
+ * authenticate itself to SSL clients.
+ *
+ * @author Jan Luehe
+ */
+public final class JSSEKeyManager implements X509KeyManager {
+
+ private X509KeyManager delegate;
+ private String serverKeyAlias;
+
+ /**
+ * Constructor.
+ *
+ * @param mgr The X509KeyManager used as a delegate
+ * @param serverKeyAlias The alias name of the server's keypair and
+ * supporting certificate chain
+ */
+ public JSSEKeyManager(X509KeyManager mgr, String serverKeyAlias) {
+ this.delegate = mgr;
+ this.serverKeyAlias = serverKeyAlias;
+ }
+
+ /**
+ * Choose an alias to authenticate the client side of a secure socket,
+ * given the public key type and the list of certificate issuer authorities
+ * recognized by the peer (if any).
+ *
+ * @param keyType The key algorithm type name(s), ordered with the
+ * most-preferred key type first
+ * @param issuers The list of acceptable CA issuer subject names, or null
+ * if it does not matter which issuers are used
+ * @param socket The socket to be used for this connection. This parameter
+ * can be null, in which case this method will return the most generic
+ * alias to use
+ *
+ * @return The alias name for the desired key, or null if there are no
+ * matches
+ */
+ public String chooseClientAlias(String[] keyType, Principal[] issuers,
+ Socket socket) {
+ return delegate.chooseClientAlias(keyType, issuers, socket);
+ }
+
+ /**
+ * Returns this key manager's server key alias that was provided in the
+ * constructor.
+ *
+ * @param keyType The key algorithm type name (ignored)
+ * @param issuers The list of acceptable CA issuer subject names, or null
+ * if it does not matter which issuers are used (ignored)
+ * @param socket The socket to be used for this connection. This parameter
+ * can be null, in which case this method will return the most generic
+ * alias to use (ignored)
+ *
+ * @return Alias name for the desired key
+ */
+ public String chooseServerAlias(String keyType, Principal[] issuers,
+ Socket socket) {
+ return serverKeyAlias;
+ }
+
+ /**
+ * Returns the certificate chain associated with the given alias.
+ *
+ * @param alias The alias name
+ *
+ * @return Certificate chain (ordered with the user's certificate first
+ * and the root certificate authority last), or null if the alias can't be
+ * found
+ */
+ public X509Certificate[] getCertificateChain(String alias) {
+ return delegate.getCertificateChain(alias);
+ }
+
+ /**
+ * Get the matching aliases for authenticating the client side of a secure
+ * socket, given the public key type and the list of certificate issuer
+ * authorities recognized by the peer (if any).
+ *
+ * @param keyType The key algorithm type name
+ * @param issuers The list of acceptable CA issuer subject names, or null
+ * if it does not matter which issuers are used
+ *
+ * @return Array of the matching alias names, or null if there were no
+ * matches
+ */
+ public String[] getClientAliases(String keyType, Principal[] issuers) {
+ return delegate.getClientAliases(keyType, issuers);
+ }
+
+ /**
+ * Get the matching aliases for authenticating the server side of a secure
+ * socket, given the public key type and the list of certificate issuer
+ * authorities recognized by the peer (if any).
+ *
+ * @param keyType The key algorithm type name
+ * @param issuers The list of acceptable CA issuer subject names, or null
+ * if it does not matter which issuers are used
+ *
+ * @return Array of the matching alias names, or null if there were no
+ * matches
+ */
+ public String[] getServerAliases(String keyType, Principal[] issuers) {
+ return delegate.getServerAliases(keyType, issuers);
+ }
+
+ /**
+ * Returns the key associated with the given alias.
+ *
+ * @param alias The alias name
+ *
+ * @return The requested key, or null if the alias can't be found
+ */
+ public PrivateKey getPrivateKey(String alias) {
+ return delegate.getPrivateKey(alias);
+ }
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/cluster/JSSESocketFactory.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/cluster/JSSESocketFactory.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/cluster/JSSESocketFactory.java 17 Aug 2012 14:43:38 -0000 1.1
@@ -0,0 +1,551 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jboss.web.cluster;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.security.cert.CRL;
+import java.security.cert.CRLException;
+import java.security.cert.CertPathParameters;
+import java.security.cert.CertStore;
+import java.security.cert.CertStoreParameters;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CollectionCertStoreParameters;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.cert.X509CertSelector;
+import java.util.Collection;
+import java.util.Vector;
+
+import javax.net.ssl.CertPathTrustManagerParameters;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.ManagerFactoryParameters;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509KeyManager;
+
+import org.apache.tomcat.util.res.StringManager;
+
+/*
+ 1. Make the JSSE's jars available, either as an installed
+ extension (copy them into jre/lib/ext) or by adding
+ them to the Tomcat classpath.
+ 2. keytool -genkey -alias tomcat -keyalg RSA
+ Use "changeit" as password ( this is the default we use )
+ */
+
+/**
+ * SSL server socket factory. It _requires_ a valid RSA key and
+ * JSSE.
+ *
+ * @author Harish Prabandham
+ * @author Costin Manolache
+ * @author Stefan Freyr Stefansson
+ * @author EKR -- renamed to JSSESocketFactory
+ * @author Jan Luehe
+ * @author Bill Barker
+ */
+public class JSSESocketFactory {
+
+ private static StringManager sm =
+ StringManager.getManager("org.apache.tomcat.util.net.jsse.res");
+
+ static org.jboss.logging.Logger log =
+ org.jboss.logging.Logger.getLogger(JSSESocketFactory.class);
+
+ protected boolean initialized;
+ //protected String clientAuth = "false";
+ protected SSLSocketFactory sslProxy = null;
+ protected String[] enabledCiphers;
+ protected ClusterListener listener = null;
+
+ /**
+ * Flag to state that we require client authentication.
+ */
+ //protected boolean requireClientAuth = false;
+
+ /**
+ * Flag to state that we would like client authentication.
+ */
+ //protected boolean wantClientAuth = false;
+
+
+ public JSSESocketFactory (ClusterListener listener) {
+ this.listener = listener;
+ }
+
+ public Socket createSocket (InetAddress ifAddress, int port)
+ throws IOException
+ {
+ if (!initialized) init();
+ Socket socket = sslProxy.createSocket(ifAddress, port);
+ initSocket(socket);
+ return socket;
+ }
+
+ public void handshake(Socket sock) throws IOException {
+ ((SSLSocket)sock).startHandshake();
+ }
+
+ /*
+ * Determines the SSL cipher suites to be enabled.
+ *
+ * @param requestedCiphers Comma-separated list of requested ciphers
+ * @param supportedCiphers Array of supported ciphers
+ *
+ * @return Array of SSL cipher suites to be enabled, or null if none of the
+ * requested ciphers are supported
+ */
+ protected String[] getEnabledCiphers(String requestedCiphers,
+ String[] supportedCiphers) {
+
+ String[] enabledCiphers = null;
+
+ if (requestedCiphers != null) {
+ Vector vec = null;
+ String cipher = requestedCiphers;
+ int index = requestedCiphers.indexOf(',');
+ if (index != -1) {
+ int fromIndex = 0;
+ while (index != -1) {
+ cipher = requestedCiphers.substring(fromIndex, index).trim();
+ if (cipher.length() > 0) {
+ /*
+ * Check to see if the requested cipher is among the
+ * supported ciphers, i.e., may be enabled
+ */
+ for (int i=0; supportedCiphers != null
+ && i 0) {
+ /*
+ * Check to see if the requested cipher is among the
+ * supported ciphers, i.e., may be enabled
+ */
+ for (int i=0; supportedCiphers != null
+ && iPKIX is supported.
+ *
+ * @param algorithm The algorithm to get parameters for.
+ * @param crlf The path to the CRL file.
+ * @param trustStore The configured TrustStore.
+ * @return The parameters including the CRLs and TrustStore.
+ */
+ protected CertPathParameters getParameters(String algorithm,
+ String crlf,
+ KeyStore trustStore)
+ throws Exception {
+ CertPathParameters params = null;
+ if("PKIX".equalsIgnoreCase(algorithm)) {
+ PKIXBuilderParameters xparams = new PKIXBuilderParameters(trustStore,
+ new X509CertSelector());
+ Collection crls = getCRLs(crlf);
+ CertStoreParameters csp = new CollectionCertStoreParameters(crls);
+ CertStore store = CertStore.getInstance("Collection", csp);
+ xparams.addCertStore(store);
+ xparams.setRevocationEnabled(true);
+ xparams.setMaxPathLength(listener.getSslTrustMaxCertLength());
+
+ params = xparams;
+ } else {
+ throw new CRLException("CRLs not supported for type: "+algorithm);
+ }
+ return params;
+ }
+
+
+ /**
+ * Load the collection of CRLs.
+ *
+ */
+ protected Collection extends CRL> getCRLs(String crlf)
+ throws IOException, CRLException, CertificateException {
+
+ File crlFile = new File(crlf);
+ if( !crlFile.isAbsolute() ) {
+ crlFile = new File(System.getProperty("catalina.base"), crlf);
+ }
+ Collection extends CRL> crls = null;
+ InputStream is = null;
+ try {
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ is = new FileInputStream(crlFile);
+ crls = cf.generateCRLs(is);
+ } catch(IOException iex) {
+ throw iex;
+ } catch(CRLException crle) {
+ throw crle;
+ } catch(CertificateException ce) {
+ throw ce;
+ } finally {
+ if(is != null) {
+ try{
+ is.close();
+ } catch(Exception ex) {
+ }
+ }
+ }
+ return crls;
+ }
+
+ /**
+ * Set the SSL protocol variants to be enabled.
+ * @param socket the SSLServerSocket.
+ * @param protocols the protocols to use.
+ */
+ protected void setEnabledProtocols(SSLSocket socket, String []protocols){
+ if (protocols != null) {
+ socket.setEnabledProtocols(protocols);
+ }
+ }
+
+ /**
+ * Determines the SSL protocol variants to be enabled.
+ *
+ * @param socket The socket to get supported list from.
+ * @param requestedProtocols Comma-separated list of requested SSL
+ * protocol variants
+ *
+ * @return Array of SSL protocol variants to be enabled, or null if none of
+ * the requested protocol variants are supported
+ */
+ protected String[] getEnabledProtocols(SSLSocket socket,
+ String requestedProtocols){
+ String[] supportedProtocols = socket.getSupportedProtocols();
+
+ String[] enabledProtocols = null;
+
+ if (requestedProtocols != null) {
+ Vector vec = null;
+ String protocol = requestedProtocols;
+ int index = requestedProtocols.indexOf(',');
+ if (index != -1) {
+ int fromIndex = 0;
+ while (index != -1) {
+ protocol = requestedProtocols.substring(fromIndex, index).trim();
+ if (protocol.length() > 0) {
+ /*
+ * Check to see if the requested protocol is among the
+ * supported protocols, i.e., may be enabled
+ */
+ for (int i=0; supportedProtocols != null
+ && i 0) {
+ /*
+ * Check to see if the requested protocol is among the
+ * supported protocols, i.e., may be enabled
+ */
+ for (int i=0; supportedProtocols != null
+ && i
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jbossweb/org/jboss/web/cluster/advertise/AdvertiseEventType.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/cluster/advertise/AdvertiseEventType.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/cluster/advertise/AdvertiseEventType.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,62 @@
+/*
+ *
+ * Copyright(c) 2008 Red Hat Middleware, LLC,
+ * and individual contributors as indicated by the @authors tag.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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 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 in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ */
+
+package org.jboss.web.cluster.advertise;
+
+/**
+ * Set what type of event the AdvertiseEvent signals.
+ * @param type The type of event. One of:
+ *
+ * ON_NEW_SERVER -- New AdvertisedServer detected
+ * ON_STATUS_CHANGE -- AdvertisedServer server changed status
+ *
+ */
+public enum AdvertiseEventType
+{
+ /** New AdvertisedServer detected */
+ ON_NEW_SERVER( 0),
+ /** AdvertisedServer server changed status */
+ ON_STATUS_CHANGE( 1);
+
+ private int value;
+ private AdvertiseEventType(int v)
+ {
+ value = v;
+ }
+
+ public int valueOf()
+ {
+ return value;
+ }
+
+ public static AdvertiseEventType valueOf(int value)
+ {
+ for (AdvertiseEventType e : values()) {
+ if (e.value == value)
+ return e;
+ }
+ throw new IllegalArgumentException("Invalid initializer: " + value);
+ }
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/cluster/advertise/AdvertiseListener.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/cluster/advertise/AdvertiseListener.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/cluster/advertise/AdvertiseListener.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,448 @@
+/*
+ *
+ * Copyright(c) 2008 Red Hat Middleware, LLC,
+ * and individual contributors as indicated by the @authors tag.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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 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 in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ */
+
+package org.jboss.web.cluster.advertise;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+import java.net.MulticastSocket;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+
+import org.jboss.web.cluster.ClusterListener;
+
+
+/** AdvertiseListener
+ * Listens for Advertise messages from mod_cluster
+ *
+ * @author Mladen Turk
+ *
+ */
+public class AdvertiseListener
+{
+ /** Default port for listening Advertise messages.
+ */
+ public static int DEFAULT_PORT = 23364;
+ /** Default Multicast group address for listening Advertise messages.
+ */
+ public static String DEFAULT_GROUP = "224.0.1.105";
+
+ private static String RFC_822_FMT = "EEE, d MMM yyyy HH:mm:ss Z";
+ private int advertisePort = DEFAULT_PORT;
+ private String groupAddress = DEFAULT_GROUP;
+ private MulticastSocket ms;
+ private SimpleDateFormat df;
+ private boolean listening = true;
+ private boolean initialized = false;
+ private boolean running = false;
+ private boolean paused = false;
+ private boolean daemon = true;
+ private byte [] secure = new byte[16];
+ private String securityKey = null;
+ private MessageDigest md = null;
+
+ private HashMap servers;
+
+ private ClusterListener listener;
+ private Thread workerThread;
+
+
+ private static void digestString(MessageDigest md, String s)
+ {
+ int len = s.length();
+ byte [] b = new byte[len];
+ for (int i = 0; i < len; i++) {
+ char c = s.charAt(i);
+ if (c < 127)
+ b[i] = (byte)c;
+ else
+ b[i] = '?';
+ }
+ md.update(b);
+ }
+
+ /** Create AdvertiseListener instance
+ * @param eventHandler The event handler that will be used for
+ * status and new server notifications.
+ */
+ public AdvertiseListener(ClusterListener listener)
+ {
+ df = new SimpleDateFormat(RFC_822_FMT, Locale.US);
+ servers = new HashMap();
+ this.listener = listener;
+ }
+
+ /**
+ * The default is true - the control thread will be
+ * in daemon mode. If set to false, the control thread
+ * will not be daemon - and will keep the process alive.
+ */
+ public void setDaemon(boolean b)
+ {
+ daemon = b;
+ }
+
+ public boolean getDaemon()
+ {
+ return daemon;
+ }
+
+ /** Set Advertise security key
+ * @param key The key to use.
+ * Security key must match the AdvertiseKey
+ * on the advertised server.
+ */
+ public void setSecurityKey(String key)
+ throws NoSuchAlgorithmException
+ {
+ securityKey = key;
+ if (md == null)
+ md = MessageDigest.getInstance("MD5");
+ }
+
+ /** Set Advertise port
+ * @param port The UDP port to use.
+ */
+ public void setAdvertisePort(int port)
+ {
+ advertisePort = port;
+ }
+
+ public int getAdvertisePort()
+ {
+ return advertisePort;
+ }
+
+ /** Set Advertise Multicaset group address
+ * @param address The IP or host address to use.
+ */
+ public void setGroupAddress(String address)
+ {
+ groupAddress = address;
+ }
+
+ /** Get Advertise Multicaset group address
+ */
+ public String getGroupAddress()
+ {
+ return groupAddress;
+ }
+
+ /** Get Collection of all AdvertisedServer instances.
+ */
+ public Collection getServers()
+ {
+ return servers.values();
+ }
+
+ /** Get AdvertiseServer server.
+ * @param name Server name to get.
+ */
+ public AdvertisedServer getServer(String name)
+ {
+ return servers.get(name);
+ }
+
+ /** Remove the AdvertisedServer from the collection.
+ * @param server Server to remove.
+ */
+ public void removeServer(AdvertisedServer server)
+ {
+ servers.remove(server);
+ }
+
+ private void init()
+ throws IOException
+ {
+ ms = new MulticastSocket(advertisePort);
+ ms.setTimeToLive(16);
+ ms.joinGroup(InetAddress.getByName(groupAddress));
+ initialized = true;
+ }
+
+ private void interruptDatagramReader()
+ {
+ if (!initialized)
+ return;
+ try {
+ // Restrict to localhost.
+ ms.setTimeToLive(0);
+ DatagramPacket dp = new DatagramPacket(secure, secure.length,
+ InetAddress.getByName(groupAddress),
+ advertisePort);
+ ms.send(dp);
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+
+ /** Start the Listener, creating listener thread.
+ */
+ public void start()
+ throws IOException
+ {
+ if (!initialized) {
+ init();
+ }
+ if (!running) {
+ SecureRandom random = new SecureRandom();
+ random.nextBytes(secure);
+ secure[0] = 0;
+ running = true;
+ paused = false;
+ listening = true;
+ AdvertiseListenerWorker aw = new AdvertiseListenerWorker();
+ workerThread = new Thread(aw);
+ workerThread.setDaemon(daemon);
+ workerThread.start();
+ }
+ }
+
+ /**
+ * Pause the listener, which will make it stop accepting new advertise
+ * messages.
+ */
+ public void pause()
+ {
+ if (running && !paused) {
+ paused = true;
+ interruptDatagramReader();
+ }
+ }
+
+
+ /**
+ * Resume the listener, which will make it start accepting new advertise
+ * messages again.
+ */
+ public void resume()
+ {
+ if (running && paused) {
+ // Genererate new private secure
+ SecureRandom random = new SecureRandom();
+ random.nextBytes(secure);
+ secure[0] = 0;
+ paused = false;
+ }
+ }
+
+
+ /**
+ * Stop the endpoint. This will cause all processing threads to stop.
+ */
+ public void stop()
+ {
+ if (running) {
+ running = false;
+ interruptDatagramReader();
+ workerThread = null;
+ }
+ }
+
+
+ /**
+ * Deallocate listener and close sockets.
+ */
+ public void destroy()
+ throws IOException
+ {
+ if (running) {
+ stop();
+ }
+ if (initialized) {
+ ms.leaveGroup(InetAddress.getByName(groupAddress));
+ ms.close();
+ initialized = false;
+ ms = null;
+ }
+ }
+
+ private boolean verifyDigest(String digest, String server, String date)
+ {
+ if (md == null)
+ return true;
+ md.reset();
+ digestString(md, securityKey);
+ digestString(md, date);
+ digestString(md, server);
+ byte [] our = md.digest();
+ byte [] dst = new byte[digest.length() * 2];
+ for (int i = 0, j = 0; i < digest.length(); i++) {
+ char ch = digest.charAt(i);
+ dst[j++] = (byte)((ch >= 'A') ? ((ch & 0xdf) - 'A') + 10 : (ch - '0'));
+ }
+ return true;
+ }
+
+ /**
+ * True if listener is accepting the advetise messages.
+ * If false it means that listener is experiencing some
+ * network problems if running.
+ */
+ public boolean isListening()
+ {
+ return listening;
+ }
+
+
+ // ------------------------------------ AdvertiseListenerWorker Inner Class
+ private class AdvertiseListenerWorker implements Runnable
+ {
+
+ protected AdvertiseListenerWorker()
+ {
+ // Nothing
+ }
+ /**
+ * The background thread that listens for incoming Advertise packets
+ * and hands them off to an appropriate AdvertiseEvent handler.
+ */
+ public void run() {
+ byte[] buffer = new byte[512];
+ // Loop until we receive a shutdown command
+ while (running) {
+ // Loop if endpoint is paused
+ while (paused) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ }
+ try {
+ DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
+ ms.receive(dp);
+ if (!running)
+ break;
+ byte [] data = dp.getData();
+ boolean intr = false;
+ if (dp.getLength() == secure.length) {
+ int i;
+ for (i = 0; i < secure.length; i++) {
+ if (data[i] != secure[i])
+ break;
+ }
+ if (i == secure.length)
+ intr = true;
+ }
+ if (intr)
+ continue;
+ String s = new String(data, 0, dp.getLength(), "8859_1");
+ if (!s.startsWith("HTTP/1."))
+ continue;
+
+ String [] headers = s.split("\r\n");
+ String date_str = null;
+ Date date = null;
+ int status = 0;
+ String status_desc = null;
+ String digest = null;
+ String server_name = null;
+ AdvertisedServer server = null;
+ boolean added = false;
+ for (int i = 0; i < headers.length; i++) {
+ if (i == 0) {
+ String [] sline = headers[i].split(" ", 3);
+ if (sline == null || sline.length != 3)
+ break;
+ status = Integer.parseInt(sline[1]);
+ if (status < 100)
+ break;
+ status_desc = sline[2];
+ }
+ else {
+ String [] hdrv = headers[i].split(": ", 2);
+ if (hdrv == null || hdrv.length != 2)
+ break;
+ if (hdrv[0].equals("Date")) {
+ date_str = hdrv[1];
+ try {
+ date = df.parse(date_str);
+ } catch (ParseException e) {
+ date = new Date();
+ }
+ }
+ else if (hdrv[0].equals("Digest")) {
+ digest = hdrv[1];
+ }
+ else if (hdrv[0].equals("Server")) {
+ server_name = hdrv[1];
+ server = servers.get(server_name);
+ if (server == null) {
+ server = new AdvertisedServer(server_name);
+ added = true;
+ }
+ }
+ else if (server != null) {
+ server.setParameter(hdrv[0], hdrv[1]);
+ }
+ }
+ }
+ if (server != null && status > 0) {
+ if (md != null) {
+ /* We need a digest to match */
+ if (!verifyDigest(digest, server_name, date_str)) {
+ System.out.println("Digest mismatch");
+ continue;
+ }
+ }
+ server.setDate(date);
+ boolean rc = server.setStatus(status, status_desc);
+ if (added) {
+ servers.put(server_name, server);
+ // Call the new server callback
+ //eventHandler.onEvent(AdvertiseEventType.ON_NEW_SERVER, server);
+ String proxy = server.getParameter(AdvertisedServer.MANAGER_ADDRESS);
+ if (proxy != null) {
+ listener.addProxy(proxy);
+ }
+ }
+ else if (rc) {
+ // Call the status change callback
+ //eventHandler.onEvent(AdvertiseEventType.ON_STATUS_CHANGE, server);
+ }
+ }
+ listening = true;
+ } catch (IOException e) {
+ // Do not blow the CPU in case of communication error
+ listening = false;
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException x) {
+ // Ignore
+ }
+ }
+ }
+ }
+ }
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/cluster/advertise/AdvertisedServer.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/cluster/advertise/AdvertisedServer.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/cluster/advertise/AdvertisedServer.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,122 @@
+/*
+ *
+ * Copyright(c) 2008 Red Hat Middleware, LLC,
+ * and individual contributors as indicated by the @authors tag.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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 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 in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ */
+
+package org.jboss.web.cluster.advertise;
+
+import java.util.Date;
+import java.util.HashMap;
+
+/**
+ * Advertised server instance
+ *
+ * @author Mladen Turk
+ *
+ */
+public class AdvertisedServer
+{
+ private String server;
+ private Date date;
+ private int status;
+ private String status_desc;
+ private HashMap headers;
+
+ /** Manager-Address header */
+ public static String MANAGER_ADDRESS = "X-Manager-Address";
+ /** Manager-Url header */
+ public static String MANAGER_URL = "X-Manager-Url";
+ /** Manager-Protocol header */
+ public static String MANAGER_PROTOCOL = "X-Manager-Protocol";
+ /** Manager-Version header */
+ public static String MANAGER_VERSION = "X-Manager-Version";
+ /** Manager-Host header */
+ public static String MANAGER_HOST = "X-Manager-Host";
+
+ protected AdvertisedServer(String server)
+ {
+ this.server = server;
+ headers = new HashMap();
+ }
+
+ protected boolean setStatus(int status, String desc)
+ {
+ boolean rv = false;
+ status_desc = desc;
+ if (this.status == 0 ) {
+ // First time
+ this.status = status;
+ }
+ else if (this.status != status) {
+ this.status = status;
+ rv = true;
+ }
+ return rv;
+ }
+
+ /** Set the Date of the last Advertise message
+ */
+ protected void setDate(Date date)
+ {
+ this.date = date;
+ }
+
+ /** Set the Header
+ */
+ protected void setParameter(String name, String value)
+ {
+ headers.put(name, value);
+ }
+
+ /** Get Date of the last Advertise message
+ */
+ public Date getDate()
+ {
+ return date;
+ }
+
+ /** Get Status code of the last Advertise message
+ */
+ public int getStatusCode()
+ {
+ return status;
+ }
+
+ /** Get Status description of the last Advertise message
+ */
+ public String getStatusDescription()
+ {
+ return status_desc;
+ }
+
+ /** Get Advertise parameter
+ */
+ public String getParameter(String name)
+ {
+ return headers.get(name);
+ }
+
+ public String toString()
+ {
+ return server;
+ }
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/php/Constants.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/php/Constants.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/php/Constants.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,37 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.web.php;
+
+
+/**
+ * Package Constants
+ *
+ * @author Mladen Turk
+ * @version $Revision: 1.1 $, $Date: 2012/08/17 14:43:39 $
+ * @since 1.0
+ */
+ public class Constants {
+
+ public static final String Package = "org.jboss.web.php";
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/php/Handler.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/php/Handler.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/php/Handler.java 17 Aug 2012 14:43:40 -0000 1.1
@@ -0,0 +1,219 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.web.php;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.UnavailableException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.catalina.Globals;
+import org.apache.catalina.util.StringManager;
+
+/**
+ * Handler.
+ *
+ * @author Mladen Turk
+ * @version $Revision: 1.1 $, $Date: 2012/08/17 14:43:40 $
+ * @since 1.0
+ */
+public class Handler extends HttpServlet
+{
+
+ /** the debugging detail level for this servlet. */
+ private int debug = 0;
+
+ /** Buffer size. */
+ private int bufferSize = 4096;
+
+ /**
+ * The Servlet configuration object we are associated with. If this value
+ * is null, this filter instance is not currently configured.
+ */
+ private ServletConfig servletConfig = null;
+
+ /**
+ * The string manager for this package.
+ */
+ private StringManager sm =
+ StringManager.getManager(Constants.Package);
+
+
+ /** Are doing source sysntax highlight. */
+ protected boolean syntaxHighlight = false;
+
+ /** the encoding to use for parameters */
+ private String parameterEncoding = System.getProperty("file.encoding",
+ "UTF-8");
+
+ /**
+ * The Script search path will start at
+ * webAppRootDir + File.separator + scriptPathPrefix
+ * (or webAppRootDir alone if scriptPathPrefix is
+ * null)
+ */
+ private String scriptPathPrefix = null;
+
+ /**
+ * Sets instance variables.
+ *
+ * Modified from Craig R. McClanahan's InvokerServlet
+ *
+ *
+ * @param config a ServletConfig
object
+ * containing the servlet's
+ * configuration and initialization
+ * parameters
+ *
+ * @exception ServletException if an exception has occurred that
+ * interferes with the servlet's normal
+ * operation
+ */
+ public void init(ServletConfig servletConfig)
+ throws ServletException
+ {
+ super.init(servletConfig);
+
+ if (!Library.isInitialized()) {
+ // try to load the library.
+ try {
+ Library.initialize(null);
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ if (!Library.isInitialized())
+ throw new UnavailableException
+ (sm.getString("handler.missing"));
+
+ this.servletConfig = servletConfig;
+
+ // Verify that we were not accessed using the invoker servlet
+ String servletName = servletConfig.getServletName();
+ if (servletName == null)
+ servletName = "";
+ if (servletName.startsWith("org.apache.catalina.INVOKER."))
+ throw new UnavailableException
+ ("Cannot invoke Handler through the invoker");
+
+
+ // Set our properties from the initialization parameters
+ String value = null;
+ try {
+ value = servletConfig.getInitParameter("debug");
+ debug = Integer.parseInt(value);
+ scriptPathPrefix =
+ servletConfig.getInitParameter("scriptPathPrefix");
+ value = servletConfig.getInitParameter("bufferSize");
+ if (value != null) {
+ bufferSize = Integer.parseInt(value);
+ if (bufferSize < 1024)
+ bufferSize = 1024;
+ log("init: bufferSize set to " + bufferSize);
+ }
+ } catch (Throwable t) {
+ // Nothing.
+ }
+ log("init: loglevel set to " + debug);
+
+ value = servletConfig.getInitParameter("parameterEncoding");
+ if (value != null) {
+ parameterEncoding = value;
+ }
+ }
+
+ /**
+ * Finalize this servlet.
+ */
+ public void destroy()
+ {
+ this.servletConfig = null;
+ }
+
+ private static native int php(byte[] buf,
+ ScriptEnvironment env,
+ HttpServletRequest req,
+ HttpServletResponse res,
+ String requestMethod,
+ String queryString,
+ String contentType,
+ String authUser,
+ String requestURI,
+ String pathTranslated,
+ int contentLength,
+ boolean syntaxHighlight);
+
+ /**
+ * Provides PHP Gateway service
+ *
+ * @param req HttpServletRequest passed in by servlet container
+ * @param res HttpServletResponse passed in by servlet container
+ *
+ * @exception ServletException if a servlet-specific exception occurs
+ * @exception IOException if a read/write exception occurs
+ *
+ * @see javax.servlet.http.HttpServlet
+ *
+ */
+ protected void service(HttpServletRequest req, HttpServletResponse res)
+ throws ServletException, IOException
+ {
+
+ // Verify that we were not accessed using the invoker servlet
+ if (req.getAttribute(Globals.INVOKED_ATTR) != null)
+ throw new UnavailableException
+ ("Cannot invoke PHP Gateway Handler through the invoker");
+
+ ScriptEnvironment env = new ScriptEnvironment(req,
+ getServletContext(),
+ scriptPathPrefix);
+ if (env.isValid()) {
+ byte[] buf = new byte[bufferSize];
+ int rv = php(buf,
+ env,
+ req,
+ res,
+ req.getMethod(),
+ req.getQueryString(),
+ req.getContentType(),
+ req.getRemoteUser(),
+ req.getRequestURI(),
+ env.getFullPath(),
+ req.getContentLength(),
+ syntaxHighlight);
+ }
+ else {
+ res.setStatus(HttpServletResponse.SC_NOT_FOUND);
+ }
+ }
+
+ public static void log(Handler handler, String msg)
+ {
+ // TODO: Log the message
+ }
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/php/Highlight.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/php/Highlight.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/php/Highlight.java 17 Aug 2012 14:43:40 -0000 1.1
@@ -0,0 +1,58 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.web.php;
+
+import java.io.IOException;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+/**
+ * Highlight.
+ *
+ * @author Mladen Turk
+ * @version $Revision: 1.1 $, $Date: 2012/08/17 14:43:40 $
+ * @since 1.0
+ */
+public class Highlight extends Handler
+{
+
+ /**
+ * Provides PHP Highlight Gateway service
+ *
+ * @param req HttpServletRequest passed in by servlet container
+ * @param res HttpServletResponse passed in by servlet container
+ *
+ * @exception ServletException if a servlet-specific exception occurs
+ * @exception IOException if a read/write exception occurs
+ *
+ * @see org.apache.catalina.servlets.php.Handler
+ *
+ */
+ protected void service(HttpServletRequest req, HttpServletResponse res)
+ throws ServletException, IOException
+ {
+ syntaxHighlight = true;
+ super.service(req, res);
+ }
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/php/Library.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/php/Library.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/php/Library.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,146 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.web.php;
+
+/**
+ * Library class.
+ *
+ * @author Mladen Turk
+ * @version $Revision: 1.1 $, $Date: 2012/08/17 14:43:39 $
+ * @since 1.0
+ */
+public class Library {
+
+ /* Default library names */
+ private static String [] NAMES = { "php5servlet", "libphp5servlet" };
+
+ /*
+ * A handle to the unique Library singleton instance.
+ */
+ private static Library engine = null;
+ private static boolean inited = false;
+
+ static PhpThread phpthread = null;
+
+ private Library()
+ {
+ boolean loaded = false;
+ String err = "";
+ for (int i = 0; i < NAMES.length; i++) {
+ try {
+ System.loadLibrary(NAMES[i]);
+ loaded = true;
+ } catch (Throwable e) {
+ if ( i > 0)
+ err += ", ";
+ err += e.getMessage();
+ }
+ if (loaded)
+ break;
+ }
+ if (!loaded) {
+ err += "(";
+ err += System.getProperty("java.library.path");
+ err += ")";
+ throw new UnsatisfiedLinkError(err);
+ }
+ }
+
+ private Library(String libraryName)
+ {
+ System.loadLibrary(libraryName);
+ }
+
+ /* PHP_MAJOR_VERSION */
+ public static int PHP_MAJOR_VERSION = 0;
+ /* PHP_MINOR_VERSION */
+ public static int PHP_MINOR_VERSION = 0;
+ /* PHP_PATCH_VERSION */
+ public static int PHP_PATCH_VERSION = 0;
+
+ /* Initialize PHP Engine
+ * This has to be the first call to PHP Module.
+ */
+ public static native boolean startup();
+
+ /* destroy global PHP Engine
+ * This has to be the last call to PHP Module.
+ */
+ public static native void shutdown();
+
+ /* Internal function for obtaining PHP Module version */
+ private static native int version(int index);
+
+ /**
+ * Setup any PHP internal data structures. This MUST be the
+ * first function called for PHP module.
+ * @param libraryName the name of the library to load
+ */
+ public static boolean initialize(String libraryName)
+ throws Exception
+ {
+ if (engine == null) {
+ if (libraryName == null)
+ engine = new Library();
+ else
+ engine = new Library(libraryName);
+ PHP_MAJOR_VERSION = version(1);
+ PHP_MINOR_VERSION = version(2);
+ PHP_PATCH_VERSION = version(3);
+ }
+
+ phpthread = new PhpThread();
+ phpthread.setDaemon(true);
+ phpthread.start();
+ // Wait until the startup is done.
+ while (!inited && phpthread.isAlive()) {
+ Thread.currentThread().sleep(3000);
+ }
+ return inited;
+ }
+
+ /**
+ * Check if PHP module is initialized.
+ */
+ public static boolean isInitialized()
+ {
+ return inited;
+ }
+
+ /**
+ * Terminate PHP Engine.
+ */
+ public static void terminate()
+ {
+ if (engine != null) {
+ if (phpthread != null && phpthread.isAlive()) {
+ phpthread.interrupt();
+ }
+ engine = null;
+ inited = false;
+ }
+ }
+ public static void StartUp() {
+ inited = startup();
+ }
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/php/LifecycleListener.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/php/LifecycleListener.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/php/LifecycleListener.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,125 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.web.php;
+
+import java.lang.reflect.Method;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleEvent;
+import org.apache.catalina.util.StringManager;
+import org.jboss.logging.Logger;
+import org.jboss.logging.Logger;
+
+/**
+ * Implementation of LifecycleListener
that will init and
+ * and destroy PHP.
+ *
+ * @author Mladen Turk
+ * @version $Revision: 1.1 $ $Date: 2012/08/17 14:43:39 $
+ * @since 1.0
+ */
+
+public class LifecycleListener
+ implements org.apache.catalina.LifecycleListener {
+
+ private static Logger log = Logger.getLogger(LifecycleListener.class);
+
+ /**
+ * The string manager for this package.
+ */
+ protected StringManager sm =
+ StringManager.getManager(Constants.Package);
+
+ // -------------------------------------------------------------- Constants
+
+
+ protected static final int REQUIRED_MAJOR = 5;
+ protected static final int REQUIRED_MINOR = 2;
+ protected static final int REQUIRED_PATCH = 3;
+
+
+ // ---------------------------------------------- LifecycleListener Methods
+
+
+ /**
+ * Primary entry point for startup and shutdown events.
+ *
+ * @param event The event that has occurred
+ */
+ public void lifecycleEvent(LifecycleEvent event) {
+
+ if (Lifecycle.INIT_EVENT.equals(event.getType())) {
+ int major = 0;
+ int minor = 0;
+ int patch = 0;
+ try {
+ String methodName = "initialize";
+ Class paramTypes[] = new Class[1];
+ paramTypes[0] = String.class;
+ Object paramValues[] = new Object[1];
+ paramValues[0] = null;
+ Class clazz = Class.forName("org.jboss.web.php.Library");
+ Method method = clazz.getMethod(methodName, paramTypes);
+ // TODO: Use sm to obtain optional library name.
+ method.invoke(null, paramValues);
+ major = clazz.getField("PHP_MAJOR_VERSION").getInt(null);
+ minor = clazz.getField("PHP_MINOR_VERSION").getInt(null);
+ patch = clazz.getField("PHP_PATCH_VERSION").getInt(null);
+ } catch (Throwable t) {
+ if (!log.isDebugEnabled()) {
+ log.info(sm.getString("listener.initialize",
+ System.getProperty("java.library.path")));
+ }
+ else {
+ log.debug(sm.getString("listener.initialize",
+ System.getProperty("java.library.path")), t);
+ }
+ return;
+ }
+ // Check if the PHP Native module matches required version.
+ if ((major != REQUIRED_MAJOR) ||
+ (minor != REQUIRED_MINOR) ||
+ (patch < REQUIRED_PATCH)) {
+ log.error(sm.getString("listener.invalid", major + "."
+ + minor + "." + patch, REQUIRED_MAJOR + "."
+ + REQUIRED_MINOR + "."
+ + REQUIRED_PATCH));
+ }
+ }
+ else if (Lifecycle.AFTER_STOP_EVENT.equals(event.getType())) {
+ try {
+ String methodName = "terminate";
+ Method method = Class.forName("org.jboss.php.servlets.php.Library")
+ .getMethod(methodName, (Class [])null);
+ method.invoke(null, (Object []) null);
+ }
+ catch (Throwable t) {
+ if (!log.isDebugEnabled()) {
+ log.info(sm.getString("listener.terminate"));
+ }
+ else {
+ log.debug(sm.getString("listener.terminate"), t);
+ }
+ }
+ }
+ }
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/php/LocalStrings.properties
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/php/LocalStrings.properties,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/php/LocalStrings.properties 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,4 @@
+listener.initialize=The PHP Native library which allows executing PHP scripts was not found on the java.library.path: {0}
+listener.invalid=An incompatible version {0} of the PHP Native library is installed, while Tomcat requires version {1}
+listener.terminate=Failed shutdown of PHP Module
+handler.missing=The PHP Native library which allows executing PHP scripts was not loaded
Index: 3rdParty_sources/jbossweb/org/jboss/web/php/PhpThread.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/php/PhpThread.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/php/PhpThread.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,44 @@
+/*
+ * Copyright(c) 2007 Red Hat Middleware, LLC,
+ * and individual contributors as indicated by the @authors tag.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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 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 in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * @author Jean-Frederic Clere
+ * @version $Revision: 1.1 $, $Date: 2012/08/17 14:43:39 $
+ */
+package org.jboss.web.php;
+
+import java.lang.Thread;
+import java.lang.InterruptedException;
+
+/* Thread that handle the php startup and shutdown */
+public class PhpThread extends Thread {
+ public void run() {
+ boolean ok = true;
+ Library.StartUp();
+ while (ok) {
+ try {
+ sleep(60000);
+ } catch (InterruptedException e) {
+ ok = false;
+ }
+ }
+ Library.shutdown();
+ }
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/php/SAPI.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/php/SAPI.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/php/SAPI.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,116 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.web.php;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+
+/**
+ * PHP SAPI interface.
+ *
+ * @author Mladen Turk
+ * @version $Revision: 1.1 $, $Date: 2012/08/17 14:43:39 $
+ * @since 1.0
+ */
+public final class SAPI
+{
+
+ public static int write(HttpServletResponse res,
+ byte[] buf, int len)
+ {
+ try {
+ res.getOutputStream().write(buf, 0, len);
+ return len;
+ } catch (IOException e) {
+ return -1;
+ }
+ }
+
+ public static int read(HttpServletRequest req,
+ byte[] buf, int len)
+ {
+ try {
+ return req.getInputStream().read(buf, 0, len);
+ } catch (IOException e) {
+ return -1;
+ }
+ }
+
+ public static void log(Handler h, String msg)
+ {
+ h.log("php: " + msg);
+ }
+
+ public static int flush(HttpServletResponse res)
+ {
+ try {
+ res.getOutputStream().flush();
+ return 0;
+ } catch (IOException e) {
+ return -1;
+ }
+ }
+
+ public static void header(boolean set,
+ HttpServletResponse res,
+ String name, String value)
+ {
+ if (name.equalsIgnoreCase("Content-type")) {
+ res.setContentType(value);
+ }
+ else if (name.equalsIgnoreCase("Location")) {
+ try {
+ res.sendRedirect(value);
+ } catch (IOException e) {
+ // Nothing.
+ }
+ }
+ else {
+ if (set)
+ res.setHeader(name, value);
+ else
+ res.addHeader(name, value);
+ }
+ }
+
+ public static void status(HttpServletResponse res,
+ int sc)
+ {
+ res.setStatus(sc);
+ }
+
+ public static String[] env(ScriptEnvironment e)
+ {
+ return e.getEnvironmentArray();
+ }
+
+ public static String cookies(ScriptEnvironment e)
+ {
+ return (String)e.getEnvironment().get("HTTP_COOKIE");
+ }
+
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/php/ScriptEnvironment.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/php/ScriptEnvironment.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/php/ScriptEnvironment.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,742 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.web.php;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.catalina.Globals;
+import org.apache.catalina.util.IOTools;
+import org.jboss.logging.Logger;
+import org.jboss.logging.Logger;
+
+
+/**
+ * Encapsulates the Script Environment and rules to derive
+ * that environment from the servlet container and request information.
+ *
+ * @author Mladen Turk
+ * @version $Revision: 1.1 $, $Date: 2012/08/17 14:43:39 $
+ * @since 1.0
+ */
+public class ScriptEnvironment {
+
+ private static Logger log = Logger.getLogger(ScriptEnvironment.class);
+
+ /**
+ * The Request attribute key for the client certificate chain.
+ */
+ private static final String CERTIFICATE_KEY = "javax.servlet.request.X509Certificate";
+ private static final String CIPHER_SUITE = "javax.servlet.request.cipher_suite";
+ private static final String SSL_SESSION = "javax.servlet.request.ssl_session";
+ private static final String KEY_SIZE = "javax.servlet.request.key_size";
+
+ /** context of the enclosing servlet */
+ private ServletContext context = null;
+
+ /** full path to the script file */
+ private String scriptFullPath = null;
+
+ /** context path of enclosing servlet */
+ private String contextPath = null;
+
+ /** servlet URI of the enclosing servlet */
+ private String servletPath = null;
+
+ /** pathInfo for the current request */
+ private String pathInfo = null;
+
+ /** real file system directory of the enclosing servlet's web app */
+ private String webAppRootDir = null;
+
+ /** tempdir for context - used to expand scripts in unexpanded wars */
+ private File tempDir = null;
+
+ /** derived script environment */
+ private Hashtable env = null;
+
+ /** script's desired working directory */
+ private File workingDirectory = null;
+
+ /** script's desired working directory */
+ private File scriptFile = null;
+
+ /** query parameters */
+ private ArrayList queryParameters = new ArrayList();
+
+ /** whether or not this object is valid or not */
+ private boolean valid = false;
+
+ /** object used to ensure multiple threads don't try to expand same file */
+ private static Object expandFileLock = new Object();
+
+ /**
+ * The Script search path will start at
+ * webAppRootDir + File.separator + scriptPathPrefix
+ * (or webAppRootDir alone if scriptPathPrefix is
+ * null)
+ */
+ private String scriptPathPrefix = null;
+
+ /**
+ * Resolves core information about the php script.
+ *
+ *
+ * Example URI:
+ *
/servlet/scriptGateway/dir1/realScript/pathinfo1
+ *
+ * path
= $CATALINA_HOME/mywebapp/dir1/realScript
+ * scriptName
= /servlet/scriptGateway/dir1/realScript
+ * fullName
= /dir1/realScript
+ * name
= realScript
+ *
+ *
+ *
+ * Script search algorithm: search the real path below
+ * <my-webapp-root> and find the first non-directory in
+ * the getPathTranslated("/"), reading/searching from left-to-right.
+ *
+ *
+ * The Script search path will start at
+ * webAppRootDir + File.separator + scriptPathPrefix
+ * (or webAppRootDir alone if scriptPathPrefix is
+ * null).
+ *
+ *
+ * scriptPathPrefix is defined by setting
+ * this servlet's scriptPathPrefix init parameter
+ *
+ *
+ *
+ * @param pathInfo String from HttpServletRequest.getPathInfo()
+ * @param webAppRootDir String from context.getRealPath("/")
+ * @param contextPath String as from
+ * HttpServletRequest.getContextPath()
+ * @param servletPath String as from
+ * HttpServletRequest.getServletPath()
+ * @param scriptPathPrefix Subdirectory of webAppRootDir below which
+ * the web app's Scripts may be stored; can be null.
+ * The Script search path will start at
+ * webAppRootDir + File.separator + scriptPathPrefix
+ * (or webAppRootDir alone if scriptPathPrefix is
+ * null). scriptPathPrefix is defined by setting
+ * the servlet's scriptPathPrefix init parameter.
+ *
+ *
+ * @return
+ *
+ *
+ * path
- full file-system path to valid script file,
+ * or null if no script file was found
+ *
+ * scriptName
-
+ * Script variable SCRIPT_NAME; the full URL path
+ * to valid script file or null if no script was
+ * found
+ *
+ * fullName
- servlet pathInfo fragment corresponding to
+ * the script itself, or null if not found
+ *
+ * name
- simple name (no directories) of the
+ * script, or null if no script was found
+ *
+ *
+ */
+ protected String[] findScript(String pathInfo, String webAppRootDir,
+ String contextPath, String servletPath,
+ String scriptPathPrefix)
+ {
+ String path = null;
+ String name = null;
+ String scriptName = null;
+ String fullName = null;
+
+ if ((webAppRootDir != null)
+ && (webAppRootDir.lastIndexOf(File.separator) ==
+ (webAppRootDir.length() - 1))) {
+ //strip the trailing "/" from the webAppRootDir
+ webAppRootDir =
+ webAppRootDir.substring(0, (webAppRootDir.length() - 1));
+ }
+
+ if (scriptPathPrefix != null) {
+ webAppRootDir = webAppRootDir + File.separator
+ + scriptPathPrefix;
+ }
+ File currentLocation = new File(webAppRootDir);
+ StringTokenizer dirWalker = new StringTokenizer(pathInfo, "/");
+
+ while (!currentLocation.isFile() && dirWalker.hasMoreElements()) {
+ currentLocation = new File(currentLocation,
+ (String)dirWalker.nextElement());
+ }
+ if (!currentLocation.isFile()) {
+ return new String[] { null, null, null, null };
+ }
+ else {
+
+ path = currentLocation.getAbsolutePath();
+ name = currentLocation.getName();
+ fullName =
+ currentLocation.getParent().substring(webAppRootDir.length())
+ + File.separator + name;
+ // NOTE: Original CGI messes the Win path.
+ fullName = fullName.replace(File.separatorChar, '/');
+
+ if (contextPath != null && ! "".equals(contextPath) && ! "/".equals(contextPath)) {
+ scriptName = contextPath + fullName;
+ }
+ else {
+ // NOTE: set scriptName to fullName
+ scriptName = fullName;
+ }
+
+ }
+
+ return new String[] { path, scriptName, fullName, name };
+ }
+
+ /**
+ * Extracts requested resource from web app archive to context work
+ * directory to enable script to be executed.
+ */
+ protected void expandScript()
+ {
+ StringBuffer srcPath = new StringBuffer();
+ StringBuffer dstPath = new StringBuffer();
+ InputStream is = null;
+
+ // paths depend on mapping
+ if (scriptPathPrefix == null) {
+ srcPath.append(pathInfo);
+ is = context.getResourceAsStream(srcPath.toString());
+ dstPath.append(tempDir);
+ dstPath.append(pathInfo);
+ }
+ else {
+ // essentially same search algorithm as findScript()
+ srcPath.append(scriptPathPrefix);
+ StringTokenizer dirWalker = new StringTokenizer(pathInfo, "/");
+ // start with first element
+ while (dirWalker.hasMoreElements() && (is == null)) {
+ srcPath.append("/");
+ srcPath.append(dirWalker.nextElement());
+ is = context.getResourceAsStream(srcPath.toString());
+ }
+ dstPath.append(tempDir);
+ dstPath.append("/");
+ dstPath.append(srcPath);
+ }
+
+ if (is == null) {
+ // didn't find anything, give up now
+ return;
+ }
+
+ File f = new File(dstPath.toString());
+ if (f.exists()) {
+ // Don't need to expand if it already exists
+ return;
+ }
+
+ // create directories
+ String dirPath = new String(dstPath.toString().substring( 0,
+ dstPath.toString().lastIndexOf("/")));
+ File dir = new File(dirPath);
+ dir.mkdirs();
+
+ try {
+ synchronized (expandFileLock) {
+ // make sure file doesn't exist
+ if (f.exists()) {
+ return;
+ }
+
+ // create file
+ if (!f.createNewFile()) {
+ return;
+ }
+ FileOutputStream fos = new FileOutputStream(f);
+
+ // copy data
+ IOTools.flow(is, fos);
+ is.close();
+ fos.close();
+ }
+ } catch (IOException ioe) {
+ // delete in case file is corrupted
+ if (f.exists()) {
+ f.delete();
+ }
+ }
+ }
+
+ /**
+ * Constructs the CGI environment to be supplied to the invoked CGI
+ * script; relies heavliy on Servlet API methods and findCGI
+ *
+ * @param req request associated with the CGI
+ * invokation
+ *
+ * @return true if environment was set OK, false if there
+ * was a problem and no environment was set
+ */
+ protected boolean setEnvironment(HttpServletRequest req)
+ throws IOException
+ {
+
+ /*
+ * This method is slightly ugly; c'est la vie.
+ * "You cannot stop [ugliness], you can only hope to contain [it]"
+ * (apologies to Marv Albert regarding MJ)
+ */
+
+ Hashtable envp = new Hashtable();
+
+ // Add the shell environment variables (if any)
+ // envp.putAll(shellEnv);
+
+ // Add the Script environment variables
+ String sPathInfoOrig = null;
+ String sPathTranslatedOrig = null;
+ String sPathInfo = null;
+ String sPathTranslated = null;
+ String sFullPath = null;
+ String sScriptName = null;
+ String sFullName = null;
+ String sName = null;
+ String[] sScriptNames;
+
+
+ sPathInfoOrig = this.pathInfo;
+ sPathInfoOrig = sPathInfoOrig == null ? "" : sPathInfoOrig;
+
+ sPathTranslatedOrig = req.getPathTranslated();
+ sPathTranslatedOrig =
+ sPathTranslatedOrig == null ? "" : sPathTranslatedOrig;
+
+ if (webAppRootDir == null ) {
+ // The app has not been deployed in exploded form
+ webAppRootDir = tempDir.toString();
+ expandScript();
+ }
+
+ sScriptNames = findScript(sPathInfoOrig,
+ webAppRootDir,
+ contextPath,
+ servletPath,
+ scriptPathPrefix);
+
+ sFullPath = sScriptNames[0];
+ sScriptName = sScriptNames[1];
+ sFullName = sScriptNames[2];
+ sName = sScriptNames[3];
+
+ if (sFullPath == null
+ || sScriptName == null
+ || sFullName == null
+ || sName == null) {
+ log.error("Invalid script names");
+ return false;
+ }
+
+ envp.put("SERVER_SOFTWARE", "JBossWebServer");
+ envp.put("SERVER_NAME", nullsToBlanks(req.getServerName()));
+ envp.put("GATEWAY_INTERFACE", "CGI/1.1");
+ envp.put("SERVER_PROTOCOL", nullsToBlanks(req.getProtocol()));
+
+ int port = req.getServerPort();
+ Integer sPort = (port == 0 ? new Integer(-1) : new Integer(port));
+ envp.put("SERVER_PORT", sPort.toString());
+
+ /*
+ * Local addres and port
+ */
+ envp.put("LOCAL_NAME", nullsToBlanks(req.getLocalName()));
+ port = req.getLocalPort();
+ Integer iPort = (port == 0 ? new Integer(-1) : new Integer(port));
+ envp.put("LOCAL_PORT", iPort.toString());
+ envp.put("LOCAL_ADDR", nullsToBlanks(req.getLocalAddr()));
+
+ envp.put("REQUEST_METHOD", nullsToBlanks(req.getMethod()));
+
+ /*-
+ * PATH_INFO should be determined by using sFullName:
+ * 1) Let sFullName not end in a "/" (see method findScript)
+ * 2) Let sFullName equal the pathInfo fragment which
+ * corresponds to the actual script.
+ * 3) Thus, PATH_INFO = request.getPathInfo().substring(
+ * sFullName.length())
+ *
+ * (see method findScript, where the real work is done)
+ *
+ */
+ if (pathInfo == null
+ || (pathInfo.substring(sFullName.length()).length() <= 0)) {
+ sPathInfo = "";
+ }
+ else {
+ sPathInfo = pathInfo.substring(sFullName.length());
+ }
+ envp.put("PATH_INFO", sPathInfo);
+
+ /*-
+ * PATH_TRANSLATED must be determined after PATH_INFO (and the
+ * implied real cgi-script) has been taken into account.
+ *
+ * The following example demonstrates:
+ *
+ * servlet info = /servlet/cgigw/dir1/dir2/cgi1/trans1/trans2
+ * cgifullpath = /servlet/cgigw/dir1/dir2/cgi1
+ * path_info = /trans1/trans2
+ * webAppRootDir = servletContext.getRealPath("/")
+ *
+ * path_translated = servletContext.getRealPath("/trans1/trans2")
+ *
+ * That is, PATH_TRANSLATED = webAppRootDir + sPathInfo
+ * (unless sPathInfo is null or blank, then the CGI
+ * specification dictates that the PATH_TRANSLATED metavariable
+ * SHOULD NOT be defined.
+ *
+ */
+ if (sPathInfo != null && !("".equals(sPathInfo))) {
+ sPathTranslated = context.getRealPath(sPathInfo);
+ }
+ else {
+ sPathTranslated = null;
+ }
+ if (sPathTranslated == null || "".equals(sPathTranslated)) {
+ // Nothing.
+ }
+ else {
+ envp.put("PATH_TRANSLATED", nullsToBlanks(sPathTranslated));
+ }
+
+
+ envp.put("SCRIPT_NAME", nullsToBlanks(sScriptName));
+ envp.put("QUERY_STRING", nullsToBlanks(req.getQueryString()));
+ envp.put("REMOTE_HOST", nullsToBlanks(req.getRemoteHost()));
+ envp.put("REMOTE_ADDR", nullsToBlanks(req.getRemoteAddr()));
+ envp.put("AUTH_TYPE", nullsToBlanks(req.getAuthType()));
+ envp.put("REMOTE_USER", nullsToBlanks(req.getRemoteUser()));
+ envp.put("REMOTE_IDENT", ""); //not necessary for full compliance
+ envp.put("CONTENT_TYPE", nullsToBlanks(req.getContentType()));
+
+
+ /* Note CGI spec says CONTENT_LENGTH must be NULL ("") or undefined
+ * if there is no content, so we cannot put 0 or -1 in as per the
+ * Servlet API spec.
+ */
+ int contentLength = req.getContentLength();
+ String sContentLength = (contentLength <= 0 ? "" :
+ (new Integer(contentLength)).toString());
+ envp.put("CONTENT_LENGTH", sContentLength);
+
+
+ Enumeration headers = req.getHeaderNames();
+ String header = null;
+
+ while (headers.hasMoreElements()) {
+ header = null;
+ header = ((String)headers.nextElement()).toUpperCase();
+ //REMIND: rewrite multiple headers as if received as single
+ //REMIND: change character set
+ //REMIND: I forgot what the previous REMIND means
+ if ("AUTHORIZATION".equalsIgnoreCase(header) ||
+ "PROXY_AUTHORIZATION".equalsIgnoreCase(header)) {
+ //NOOP per CGI specification section 11.2
+ }
+ else {
+ envp.put("HTTP_" + header.replace('-', '_'),
+ req.getHeader(header));
+ }
+ }
+
+ scriptFile = new File(sFullPath);
+ scriptFullPath = scriptFile.getCanonicalPath();
+ workingDirectory = new File(scriptFullPath.substring(0,
+ scriptFullPath.lastIndexOf(File.separator)));
+
+ envp.put("SCRIPT_FILENAME", scriptFullPath);
+
+ envp.put("CONTEXT_PATH", nullsToBlanks(contextPath));
+
+ String self = "";
+ if (contextPath != null && ! "".equals(contextPath) && ! "/".equals(contextPath)) {
+ self = contextPath;
+ }
+ if (servletPath != null && ! "".equals(servletPath) && ! "/".equals(servletPath)) {
+ self = self.concat(servletPath);
+ }
+
+ envp.put("PHP_SELF", nullsToBlanks(self));
+
+ if (req.isSecure()) {
+ envp.put("HTTPS", "ON");
+ envp.put("SSL_CIPHER", req.getAttribute(CIPHER_SUITE));
+ envp.put("SSL_SESSION_ID", req.getAttribute(SSL_SESSION));
+ envp.put("SSL_CIPHER_USEKEYSIZE", String.valueOf(req.getAttribute(KEY_SIZE)));
+ X509Certificate[] certs =
+ (X509Certificate[])req.getAttribute(CERTIFICATE_KEY);
+ if (certs != null) {
+ // Well use the first, normaly the client certificate.
+ envp.put("SSL_SERVER_V_START", certs[0].getNotAfter().toString());
+ envp.put("SSL_SERVER_V_END", certs[0].getNotBefore().toString());
+
+ envp.put("SSL_CLIENT_A_KEY", certs[0].getSigAlgName());
+
+ // Oops getEncoded gives a DER not PEM encoded ... envp.put("SSL_CLIENT_CERT", certs[0].getEncoded());
+
+ envp.put("SSL_SERVER_M_SERIAL", certs[0].getSerialNumber().toString());
+ envp.put("SSL_SERVER_M_VERSION", String.valueOf(certs[0].getVersion()));
+
+ // Subject
+ envp.put("SSL_CLIENT_S_DN", certs[0].getSubjectX500Principal().getName());
+ // To fill the elements C,ST... Email
+ String pr = certs[0].getSubjectX500Principal().getName();
+ String prs[] = pr.split(", ");
+ for (int c = 0; c < prs.length; c++) {
+ String pprs[] = prs[c].split("=");
+ envp.put("SSL_CLIENT_S_DN_" + pprs[0], pprs[1]);
+ }
+
+ // Issuer
+ envp.put("SSL_CLIENT_I_DN", certs[0].getIssuerX500Principal().getName());
+ // To fill the elements C,ST... Email Still to TODO.
+ pr = certs[0].getSubjectX500Principal().getName();
+ prs = pr.split(", ");
+ for (int c = 0; c < prs.length; c++) {
+ String pprs[] = prs[c].split("=");
+ envp.put("SSL_CLIENT_I_DN_" + pprs[0], pprs[1]);
+ }
+
+
+ // envp.put("CERT_ISSUER",
+ // nullsToBlanks(certs[c].getIssuerX500Principal().getName()));
+ }
+ }
+
+ this.env = envp;
+ return true;
+ }
+
+
+ /**
+ * Creates a CGIEnvironment and derives the necessary environment,
+ * query parameters, working directory, cgi command, etc.
+ *
+ * @param req HttpServletRequest for information provided by
+ * the Servlet API
+ * @param context ServletContext for information provided by the
+ * Servlet API
+ *
+ */
+ public ScriptEnvironment(HttpServletRequest req,
+ ServletContext context,
+ String scriptPathPrefix)
+ throws IOException
+ {
+ this.scriptPathPrefix = scriptPathPrefix;
+ this.context = context;
+ this.webAppRootDir = context.getRealPath("/");
+ this.tempDir = (File)context.getAttribute(Globals.WORK_DIR_ATTR);
+
+
+ if (req.getAttribute(Globals.INCLUDE_CONTEXT_PATH_ATTR) != null) {
+ // Include
+ this.contextPath = (String) req.getAttribute(Globals.INCLUDE_CONTEXT_PATH_ATTR);
+ this.servletPath = (String) req.getAttribute(Globals.INCLUDE_SERVLET_PATH_ATTR);
+ this.pathInfo = (String) req.getAttribute(Globals.INCLUDE_PATH_INFO_ATTR);
+ }
+ else {
+ // Direct call
+ this.contextPath = req.getContextPath();
+ this.servletPath = req.getServletPath();
+ this.pathInfo = req.getPathInfo();
+ }
+
+ // If getPathInfo() returns null, must be using extension mapping
+ // In this case, pathInfo should be same as servletPath
+ if (this.pathInfo == null) {
+ this.pathInfo = this.servletPath;
+ }
+ this.valid = setEnvironment(req);
+ }
+
+
+ /**
+ * Gets derived script full path
+ *
+ * @return full script path
+ *
+ */
+ public String getFullPath()
+ {
+ return scriptFullPath;
+ }
+
+ /**
+ * Gets derived Script file
+ *
+ * @return Script file
+ *
+ */
+ public File getScriptFile()
+ {
+ return scriptFile;
+ }
+
+ /**
+ * Gets derived Script working directory
+ *
+ * @return working directory
+ *
+ */
+ public File getWorkingDirectory()
+ {
+ return workingDirectory;
+ }
+
+ /**
+ * Gets derived Script environment
+ *
+ * @return Script environment
+ *
+ */
+ public Hashtable getEnvironment()
+ {
+ return env;
+ }
+
+ /**
+ * Gets derived Script query parameters
+ *
+ * @return Script query parameters
+ *
+ */
+ public ArrayList getParameters()
+ {
+ return queryParameters;
+ }
+
+ /**
+ * Gets validity status
+ *
+ * @return true if this environment is valid, false
+ * otherwise
+ *
+ */
+ public boolean isValid()
+ {
+ return valid;
+ }
+
+ /**
+ * Converts null strings to blank strings ("")
+ *
+ * @param s string to be converted if necessary
+ * @return a non-null string, either the original or the empty string
+ * ("") if the original was null
+ */
+ protected String nullsToBlanks(String s)
+ {
+ return nullsToString(s, "");
+ }
+
+ /**
+ * Converts null strings to another string
+ *
+ * @param couldBeNull string to be converted if necessary
+ * @param subForNulls string to return instead of a null string
+ * @return a non-null string, either the original or the substitute
+ * string if the original was null
+ */
+ protected String nullsToString(String couldBeNull,
+ String subForNulls)
+ {
+ return (couldBeNull == null ? subForNulls : couldBeNull);
+ }
+
+ /**
+ * Converts blank strings to another string
+ *
+ * @param couldBeBlank string to be converted if necessary
+ * @param subForBlanks string to return instead of a blank string
+ * @return a non-null string, either the original or the substitute
+ * string if the original was null
or empty ("")
+ */
+ protected String blanksToString(String couldBeBlank,
+ String subForBlanks)
+ {
+ return (("".equals(couldBeBlank) || couldBeBlank == null)
+ ? subForBlanks
+ : couldBeBlank);
+ }
+
+ /**
+ * Converts Environment Hastable to String array
+ *
+ * @return Srring array containing name value pairs.
+ * @exception NullPointerException if a hash key has a null value
+ */
+ public String[] getEnvironmentArray()
+ throws NullPointerException
+ {
+ return hashToStringArray(env);
+ }
+
+ /**
+ * Converts a Hashtable to a String array by converting each
+ * key/value pair in the Hashtable to two consecutive Strings
+ *
+ * @param h Hashtable to convert
+ * @return converted string array
+ * @exception NullPointerException if a hash key has a null value
+ */
+ public static String[] hashToStringArray(Hashtable h)
+ throws NullPointerException
+ {
+ Vector v = new Vector();
+ Enumeration e = h.keys();
+ while (e.hasMoreElements()) {
+ String k = e.nextElement().toString();
+ v.add(k);
+ v.add(h.get(k));
+ }
+ String[] strArr = new String[v.size()];
+ v.copyInto(strArr);
+ return strArr;
+ }
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/rewrite/Resolver.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/rewrite/Resolver.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/rewrite/Resolver.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+
+package org.jboss.web.rewrite;
+
+public abstract class Resolver {
+
+ public abstract String resolve(String key);
+
+ public String resolveEnv(String key) {
+ return System.getProperty(key);
+ }
+
+ public abstract String resolveSsl(String key);
+
+ public abstract String resolveHttp(String key);
+
+ public abstract boolean resolveResource(int type, String name);
+
+}
\ No newline at end of file
Index: 3rdParty_sources/jbossweb/org/jboss/web/rewrite/RewriteCond.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/rewrite/RewriteCond.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/rewrite/RewriteCond.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,273 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+
+package org.jboss.web.rewrite;
+
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class RewriteCond {
+
+ public abstract class Condition {
+ public abstract boolean evaluate(String value, Resolver resolver);
+ }
+
+ public class PatternCondition extends Condition {
+ public Pattern pattern;
+ public Matcher matcher = null;
+ public boolean evaluate(String value, Resolver resolver) {
+ Matcher m = pattern.matcher(value);
+ if (m.matches()) {
+ matcher = m;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public class LexicalCondition extends Condition {
+ /**
+ * -1: <
+ * 0: =
+ * 1: >
+ */
+ public int type = 0;
+ public String condition;
+ public boolean evaluate(String value, Resolver resolver) {
+ int result = value.compareTo(condition);
+ switch (type) {
+ case -1:
+ return (result < 0);
+ case 0:
+ return (result == 0);
+ case 1:
+ return (result > 0);
+ default:
+ return false;
+ }
+
+ }
+ }
+
+ public class ResourceCondition extends Condition {
+ /**
+ * 0: -d (is directory ?)
+ * 1: -f (is regular file ?)
+ * 2: -s (is regular file with size ?)
+ */
+ public int type = 0;
+ public boolean evaluate(String value, Resolver resolver) {
+ switch (type) {
+ case 0:
+ return true;
+ case 1:
+ return true;
+ case 2:
+ return true;
+ default:
+ return false;
+ }
+
+ }
+ }
+
+ protected String testString = null;
+ protected String condPattern = null;
+
+ public String getCondPattern() {
+ return condPattern;
+ }
+
+ public void setCondPattern(String condPattern) {
+ this.condPattern = condPattern;
+ }
+
+ public String getTestString() {
+ return testString;
+ }
+
+ public void setTestString(String testString) {
+ this.testString = testString;
+ }
+
+ public void parse(Map maps) {
+ test = new Substitution();
+ test.setSub(testString);
+ test.parse(maps);
+ if (condPattern.startsWith("!")) {
+ positive = false;
+ condPattern = condPattern.substring(1);
+ }
+ if (condPattern.startsWith("<")) {
+ LexicalCondition condition = new LexicalCondition();
+ condition.type = -1;
+ condition.condition = condPattern.substring(1);
+ } else if (condPattern.startsWith(">")) {
+ LexicalCondition condition = new LexicalCondition();
+ condition.type = 1;
+ condition.condition = condPattern.substring(1);
+ } else if (condPattern.startsWith("=")) {
+ LexicalCondition condition = new LexicalCondition();
+ condition.type = 0;
+ condition.condition = condPattern.substring(1);
+ } else if (condPattern.equals("-d")) {
+ ResourceCondition ncondition = new ResourceCondition();
+ ncondition.type = 0;
+ } else if (condPattern.equals("-f")) {
+ ResourceCondition ncondition = new ResourceCondition();
+ ncondition.type = 1;
+ } else if (condPattern.equals("-s")) {
+ ResourceCondition ncondition = new ResourceCondition();
+ ncondition.type = 2;
+ } else {
+ PatternCondition condition = new PatternCondition();
+ int flags = 0;
+ if (isNocase()) {
+ flags |= Pattern.CASE_INSENSITIVE;
+ }
+ condition.pattern = Pattern.compile(condPattern, flags);
+ }
+ }
+
+ public Matcher getMatcher() {
+ Object condition = this.condition.get();
+ if (condition instanceof PatternCondition) {
+ return ((PatternCondition) condition).matcher;
+ }
+ return null;
+ }
+
+ /**
+ * String representation.
+ */
+ public String toString() {
+ // FIXME: Add flags if possible
+ return "RewriteCond " + testString + " " + condPattern;
+ }
+
+
+ protected boolean positive = true;
+
+ protected Substitution test = null;
+
+ protected ThreadLocal condition = new ThreadLocal();
+
+ /**
+ * This makes the test case-insensitive, i.e., there is no difference between
+ * 'A-Z' and 'a-z' both in the expanded TestString and the CondPattern. This
+ * flag is effective only for comparisons between TestString and CondPattern.
+ * It has no effect on filesystem and subrequest checks.
+ */
+ public boolean nocase = false;
+
+ /**
+ * Use this to combine rule conditions with a local OR instead of the implicit AND.
+ */
+ public boolean ornext = false;
+
+ /**
+ * Evaluate the condition based on the context
+ *
+ * @param rule corresponding matched rule
+ * @param cond last matched condition
+ * @return
+ */
+ public boolean evaluate(Matcher rule, Matcher cond, Resolver resolver) {
+ String value = test.evaluate(rule, cond, resolver);
+ if (nocase) {
+ value = value.toLowerCase();
+ }
+ Condition condition = this.condition.get();
+ if (condition == null) {
+ if (condPattern.startsWith("<")) {
+ LexicalCondition ncondition = new LexicalCondition();
+ ncondition.type = -1;
+ ncondition.condition = condPattern.substring(1);
+ condition = ncondition;
+ } else if (condPattern.startsWith(">")) {
+ LexicalCondition ncondition = new LexicalCondition();
+ ncondition.type = 1;
+ ncondition.condition = condPattern.substring(1);
+ condition = ncondition;
+ } else if (condPattern.startsWith("=")) {
+ LexicalCondition ncondition = new LexicalCondition();
+ ncondition.type = 0;
+ ncondition.condition = condPattern.substring(1);
+ condition = ncondition;
+ } else if (condPattern.equals("-d")) {
+ ResourceCondition ncondition = new ResourceCondition();
+ ncondition.type = 0;
+ condition = ncondition;
+ } else if (condPattern.equals("-f")) {
+ ResourceCondition ncondition = new ResourceCondition();
+ ncondition.type = 1;
+ condition = ncondition;
+ } else if (condPattern.equals("-s")) {
+ ResourceCondition ncondition = new ResourceCondition();
+ ncondition.type = 2;
+ condition = ncondition;
+ } else {
+ PatternCondition ncondition = new PatternCondition();
+ int flags = 0;
+ if (isNocase()) {
+ flags |= Pattern.CASE_INSENSITIVE;
+ }
+ ncondition.pattern = Pattern.compile(condPattern, flags);
+ condition = ncondition;
+ }
+ this.condition.set(condition);
+ }
+ if (positive) {
+ return condition.evaluate(value, resolver);
+ } else {
+ return !condition.evaluate(value, resolver);
+ }
+ }
+
+ public boolean isNocase() {
+ return nocase;
+ }
+
+ public void setNocase(boolean nocase) {
+ this.nocase = nocase;
+ }
+
+ public boolean isOrnext() {
+ return ornext;
+ }
+
+ public void setOrnext(boolean ornext) {
+ this.ornext = ornext;
+ }
+
+ public boolean isPositive() {
+ return positive;
+ }
+
+ public void setPositive(boolean positive) {
+ this.positive = positive;
+ }
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/rewrite/RewriteMap.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/rewrite/RewriteMap.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/rewrite/RewriteMap.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,32 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+
+package org.jboss.web.rewrite;
+
+public interface RewriteMap {
+
+ public String setParameters(String params);
+
+ public String lookup(String key);
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/rewrite/RewriteRule.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/rewrite/RewriteRule.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/rewrite/RewriteRule.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,539 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+
+package org.jboss.web.rewrite;
+
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class RewriteRule {
+
+ protected RewriteCond[] conditions = new RewriteCond[0];
+
+ protected ThreadLocal pattern = new ThreadLocal();
+ protected Substitution substitution = null;
+
+ protected String patternString = null;
+ protected String substitutionString = null;
+
+ public void parse(Map maps) {
+ // Parse the substitution
+ if (!"-".equals(substitutionString)) {
+ substitution = new Substitution();
+ substitution.setSub(substitutionString);
+ substitution.parse(maps);
+ }
+ // Parse the pattern
+ int flags = 0;
+ if (isNocase()) {
+ flags |= Pattern.CASE_INSENSITIVE;
+ }
+ Pattern.compile(patternString, flags);
+ // Parse conditions
+ for (int i = 0; i < conditions.length; i++) {
+ conditions[i].parse(maps);
+ }
+ // Parse flag which have substitution values
+ if (isEnv()) {
+ for (int i = 0; i < envValue.size(); i++) {
+ Substitution newEnvSubstitution = new Substitution();
+ newEnvSubstitution.setSub(envValue.get(i));
+ newEnvSubstitution.parse(maps);
+ envSubstitution.add(newEnvSubstitution);
+ envResult.add(new ThreadLocal());
+ }
+ }
+ if (isCookie()) {
+ cookieSubstitution = new Substitution();
+ cookieSubstitution.setSub(cookieValue);
+ cookieSubstitution.parse(maps);
+ }
+ }
+
+ public void addCondition(RewriteCond condition) {
+ RewriteCond[] conditions = new RewriteCond[this.conditions.length + 1];
+ for (int i = 0; i < this.conditions.length; i++) {
+ conditions[i] = this.conditions[i];
+ }
+ conditions[this.conditions.length] = condition;
+ this.conditions = conditions;
+ }
+
+ /**
+ * Evaluate the rule based on the context
+ *
+ * @return null if no rewrite took place
+ */
+ public CharSequence evaluate(CharSequence url, Resolver resolver) {
+ Pattern pattern = this.pattern.get();
+ if (pattern == null) {
+ // Parse the pattern
+ int flags = 0;
+ if (isNocase()) {
+ flags |= Pattern.CASE_INSENSITIVE;
+ }
+ pattern = Pattern.compile(patternString, flags);
+ this.pattern.set(pattern);
+ }
+ Matcher matcher = pattern.matcher(url);
+ if (!matcher.matches()) {
+ // Evaluation done
+ return null;
+ }
+ // Evaluate conditions
+ boolean done = false;
+ boolean rewrite = true;
+ Matcher lastMatcher = null;
+ int pos = 0;
+ while (!done) {
+ if (pos < conditions.length) {
+ rewrite = conditions[pos].evaluate(matcher, lastMatcher, resolver);
+ if (rewrite) {
+ Matcher lastMatcher2 = conditions[pos].getMatcher();
+ if (lastMatcher2 != null) {
+ lastMatcher = lastMatcher2;
+ }
+ while (pos < conditions.length && conditions[pos].isOrnext()) {
+ pos++;
+ }
+ } else if (!conditions[pos].isOrnext()) {
+ done = true;
+ }
+ pos++;
+ } else {
+ done = true;
+ }
+ }
+ // Use the substitution to rewrite the url
+ if (rewrite) {
+ if (isEnv()) {
+ for (int i = 0; i < envSubstitution.size(); i++) {
+ envResult.get(i).set(envSubstitution.get(i).evaluate(matcher, lastMatcher, resolver));
+ }
+ }
+ if (isCookie()) {
+ cookieResult.set(cookieSubstitution.evaluate(matcher, lastMatcher, resolver));
+ }
+ if (substitution != null) {
+ return substitution.evaluate(matcher, lastMatcher, resolver);
+ } else {
+ return url;
+ }
+ } else {
+ return null;
+ }
+ }
+
+
+ /**
+ * String representation.
+ */
+ public String toString() {
+ // FIXME: Add flags if possible
+ return "RewriteRule " + patternString + " " + substitutionString;
+ }
+
+
+ /**
+ * This flag chains the current rule with the next rule (which itself
+ * can be chained with the following rule, etc.). This has the following
+ * effect: if a rule matches, then processing continues as usual, i.e.,
+ * the flag has no effect. If the rule does not match, then all following
+ * chained rules are skipped. For instance, use it to remove the ``.www''
+ * part inside a per-directory rule set when you let an external redirect
+ * happen (where the ``.www'' part should not to occur!).
+ */
+ protected boolean chain = false;
+
+ /**
+ * This sets a cookie on the client's browser. The cookie's name is
+ * specified by NAME and the value is VAL. The domain field is the domain
+ * of the cookie, such as '.apache.org',the optional lifetime
+ * is the lifetime of the cookie in minutes, and the optional path is the
+ * path of the cookie
+ */
+ protected boolean cookie = false;
+ protected String cookieName = null;
+ protected String cookieValue = null;
+ protected String cookieDomain = null;
+ protected int cookieLifetime = -1;
+ protected String cookiePath = null;
+ protected boolean cookieSecure = false;
+ protected boolean cookieHttpOnly = false;
+ protected Substitution cookieSubstitution = null;
+ protected ThreadLocal cookieResult = new ThreadLocal();
+
+ /**
+ * This forces a request attribute named VAR to be set to the value VAL,
+ * where VAL can contain regexp back references $N and %N which will be
+ * expanded. Multiple env flags are allowed.
+ */
+ protected boolean env = false;
+ protected ArrayList envName = new ArrayList();
+ protected ArrayList envValue = new ArrayList();
+ protected ArrayList envSubstitution = new ArrayList();
+ protected ArrayList> envResult = new ArrayList>();
+
+ /**
+ * This forces the current URL to be forbidden, i.e., it immediately sends
+ * back a HTTP response of 403 (FORBIDDEN). Use this flag in conjunction
+ * with appropriate RewriteConds to conditionally block some URLs.
+ */
+ protected boolean forbidden = false;
+
+ /**
+ * This forces the current URL to be gone, i.e., it immediately sends
+ * back a HTTP response of 410 (GONE). Use this flag to mark pages which
+ * no longer exist as gone.
+ */
+ protected boolean gone = false;
+
+ /**
+ * Host. This means this rule and its associated conditions will apply to
+ * host, allowing host rewriting (ex: redirecting internally *.foo.com to
+ * bar.foo.com).
+ */
+ protected boolean host = false;
+
+ /**
+ * Stop the rewriting process here and don't apply any more rewriting
+ * rules. This corresponds to the Perl last command or the break command
+ * from the C language. Use this flag to prevent the currently rewritten
+ * URL from being rewritten further by following rules. For example, use
+ * it to rewrite the root-path URL ('/') to a real one, e.g., '/e/www/'.
+ */
+ protected boolean last = false;
+
+ /**
+ * Re-run the rewriting process (starting again with the first rewriting
+ * rule). Here the URL to match is again not the original URL but the URL
+ * from the last rewriting rule. This corresponds to the Perl next
+ * command or the continue command from the C language. Use this flag to
+ * restart the rewriting process, i.e., to immediately go to the top of
+ * the loop. But be careful not to create an infinite loop!
+ */
+ protected boolean next = false;
+
+ /**
+ * This makes the Pattern case-insensitive, i.e., there is no difference
+ * between 'A-Z' and 'a-z' when Pattern is matched against the current
+ * URL.
+ */
+ protected boolean nocase = false;
+
+ /**
+ * This flag keeps mod_rewrite from applying the usual URI escaping rules
+ * to the result of a rewrite. Ordinarily, special characters (such as
+ * '%', '$', ';', and so on) will be escaped into their hexcode
+ * equivalents ('%25', '%24', and '%3B', respectively); this flag
+ * prevents this from being done. This allows percent symbols to appear
+ * in the output, as in
+ * RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE]
+ * which would turn '/foo/zed' into a safe request for '/bar?arg=P1=zed'.
+ */
+ protected boolean noescape = false;
+
+ /**
+ * This flag forces the rewriting engine to skip a rewriting rule if the
+ * current request is an internal sub-request. For instance, sub-requests
+ * occur internally in Apache when mod_include tries to find out
+ * information about possible directory default files (index.xxx). On
+ * sub-requests it is not always useful and even sometimes causes a
+ * failure to if the complete set of rules are applied. Use this flag to
+ * exclude some rules. Use the following rule for your decision: whenever
+ * you prefix some URLs with CGI-scripts to force them to be processed by
+ * the CGI-script, the chance is high that you will run into problems (or
+ * even overhead) on sub-requests. In these cases, use this flag.
+ */
+ protected boolean nosubreq = false;
+
+ /**
+ * This flag forces the substitution part to be internally forced as a proxy
+ * request and immediately (i.e., rewriting rule processing stops here) put
+ * through the proxy module. You have to make sure that the substitution string
+ * is a valid URI (e.g., typically starting with http://hostname) which can be
+ * handled by the Apache proxy module. If not you get an error from the proxy
+ * module. Use this flag to achieve a more powerful implementation of the
+ * ProxyPass directive, to map some remote stuff into the namespace of
+ * the local server.
+ * FIXME: No proxy
+ */
+
+ /**
+ * FIXME: No passthrough ?
+ */
+
+ /**
+ * This flag forces the rewriting engine to append a query string part in
+ * the substitution string to the existing one instead of replacing it.
+ * Use this when you want to add more data to the query string via
+ * a rewrite rule.
+ */
+ protected boolean qsappend = false;
+
+ /**
+ * Prefix Substitution with http://thishost[:thisport]/ (which makes the
+ * new URL a URI) to force a external redirection. If no code is given
+ * a HTTP response of 302 (MOVED TEMPORARILY) is used. If you want to
+ * use other response codes in the range 300-400 just specify them as
+ * a number or use one of the following symbolic names: temp (default),
+ * permanent, seeother. Use it for rules which should canonicalize the
+ * URL and give it back to the client, e.g., translate ``/~'' into ``/u/''
+ * or always append a slash to /u/user, etc. Note: When you use this flag,
+ * make sure that the substitution field is a valid URL! If not, you are
+ * redirecting to an invalid location! And remember that this flag itself
+ * only prefixes the URL with http://thishost[:thisport]/, rewriting
+ * continues. Usually you also want to stop and do the redirection
+ * immediately. To stop the rewriting you also have to provide the
+ * 'L' flag.
+ */
+ protected boolean redirect = false;
+ protected int redirectCode = 0;
+
+ /**
+ * This flag forces the rewriting engine to skip the next num rules in
+ * sequence when the current rule matches. Use this to make pseudo
+ * if-then-else constructs: The last rule of the then-clause becomes
+ * skip=N where N is the number of rules in the else-clause.
+ * (This is not the same as the 'chain|C' flag!)
+ */
+ protected int skip = 0;
+
+ /**
+ * Force the MIME-type of the target file to be MIME-type. For instance,
+ * this can be used to setup the content-type based on some conditions.
+ * For example, the following snippet allows .php files to be displayed
+ * by mod_php if they are called with the .phps extension:
+ * RewriteRule ^(.+\.php)s$ $1 [T=application/x-httpd-php-source]
+ */
+ protected boolean type = false;
+ protected String typeValue = null;
+ public boolean isChain() {
+ return chain;
+ }
+ public void setChain(boolean chain) {
+ this.chain = chain;
+ }
+ public RewriteCond[] getConditions() {
+ return conditions;
+ }
+ public void setConditions(RewriteCond[] conditions) {
+ this.conditions = conditions;
+ }
+ public boolean isCookie() {
+ return cookie;
+ }
+ public void setCookie(boolean cookie) {
+ this.cookie = cookie;
+ }
+ public String getCookieName() {
+ return cookieName;
+ }
+ public void setCookieName(String cookieName) {
+ this.cookieName = cookieName;
+ }
+ public String getCookieValue() {
+ return cookieValue;
+ }
+ public void setCookieValue(String cookieValue) {
+ this.cookieValue = cookieValue;
+ }
+ public String getCookieResult() {
+ return cookieResult.get();
+ }
+ public boolean isEnv() {
+ return env;
+ }
+ public int getEnvSize() {
+ return envName.size();
+ }
+ public void setEnv(boolean env) {
+ this.env = env;
+ }
+ public String getEnvName(int i) {
+ return envName.get(i);
+ }
+ public void addEnvName(String envName) {
+ this.envName.add(envName);
+ }
+ public String getEnvValue(int i) {
+ return envValue.get(i);
+ }
+ public void addEnvValue(String envValue) {
+ this.envValue.add(envValue);
+ }
+ public String getEnvResult(int i) {
+ return envResult.get(i).get();
+ }
+ public boolean isForbidden() {
+ return forbidden;
+ }
+ public void setForbidden(boolean forbidden) {
+ this.forbidden = forbidden;
+ }
+ public boolean isGone() {
+ return gone;
+ }
+ public void setGone(boolean gone) {
+ this.gone = gone;
+ }
+ public boolean isLast() {
+ return last;
+ }
+ public void setLast(boolean last) {
+ this.last = last;
+ }
+ public boolean isNext() {
+ return next;
+ }
+ public void setNext(boolean next) {
+ this.next = next;
+ }
+ public boolean isNocase() {
+ return nocase;
+ }
+ public void setNocase(boolean nocase) {
+ this.nocase = nocase;
+ }
+ public boolean isNoescape() {
+ return noescape;
+ }
+ public void setNoescape(boolean noescape) {
+ this.noescape = noescape;
+ }
+ public boolean isNosubreq() {
+ return nosubreq;
+ }
+ public void setNosubreq(boolean nosubreq) {
+ this.nosubreq = nosubreq;
+ }
+ public boolean isQsappend() {
+ return qsappend;
+ }
+ public void setQsappend(boolean qsappend) {
+ this.qsappend = qsappend;
+ }
+ public boolean isRedirect() {
+ return redirect;
+ }
+ public void setRedirect(boolean redirect) {
+ this.redirect = redirect;
+ }
+ public int getRedirectCode() {
+ return redirectCode;
+ }
+ public void setRedirectCode(int redirectCode) {
+ this.redirectCode = redirectCode;
+ }
+ public int getSkip() {
+ return skip;
+ }
+ public void setSkip(int skip) {
+ this.skip = skip;
+ }
+ public Substitution getSubstitution() {
+ return substitution;
+ }
+ public void setSubstitution(Substitution substitution) {
+ this.substitution = substitution;
+ }
+ public boolean isType() {
+ return type;
+ }
+ public void setType(boolean type) {
+ this.type = type;
+ }
+ public String getTypeValue() {
+ return typeValue;
+ }
+ public void setTypeValue(String typeValue) {
+ this.typeValue = typeValue;
+ }
+
+ public String getPatternString() {
+ return patternString;
+ }
+
+ public void setPatternString(String patternString) {
+ this.patternString = patternString;
+ }
+
+ public String getSubstitutionString() {
+ return substitutionString;
+ }
+
+ public void setSubstitutionString(String substitutionString) {
+ this.substitutionString = substitutionString;
+ }
+
+ public boolean isHost() {
+ return host;
+ }
+
+ public void setHost(boolean host) {
+ this.host = host;
+ }
+
+ public String getCookieDomain() {
+ return cookieDomain;
+ }
+
+ public void setCookieDomain(String cookieDomain) {
+ this.cookieDomain = cookieDomain;
+ }
+
+ public int getCookieLifetime() {
+ return cookieLifetime;
+ }
+
+ public void setCookieLifetime(int cookieLifetime) {
+ this.cookieLifetime = cookieLifetime;
+ }
+
+ public String getCookiePath() {
+ return cookiePath;
+ }
+
+ public void setCookiePath(String cookiePath) {
+ this.cookiePath = cookiePath;
+ }
+
+ public boolean isCookieSecure() {
+ return cookieSecure;
+ }
+
+ public void setCookieSecure(boolean cookieSecure) {
+ this.cookieSecure = cookieSecure;
+ }
+
+ public boolean isCookieHttpOnly() {
+ return cookieHttpOnly;
+ }
+
+ public void setCookieHttpOnly(boolean cookieHttpOnly) {
+ this.cookieHttpOnly = cookieHttpOnly;
+ }
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/rewrite/RewriteValve.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/rewrite/RewriteValve.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/rewrite/RewriteValve.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,733 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+
+package org.jboss.web.rewrite;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.Context;
+import org.apache.catalina.Engine;
+import org.apache.catalina.Host;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.util.LifecycleSupport;
+import org.apache.catalina.valves.ValveBase;
+import org.apache.tomcat.util.buf.CharChunk;
+import org.apache.tomcat.util.buf.MessageBytes;
+import org.apache.tomcat.util.http.TomcatCookie;
+import org.apache.tomcat.util.net.URL;
+
+public class RewriteValve extends ValveBase
+ implements Lifecycle {
+
+ /**
+ * The lifecycle event support for this component.
+ */
+ protected LifecycleSupport lifecycle = new LifecycleSupport(this);
+
+
+ /**
+ * The rewrite rules that the valve will use.
+ */
+ protected RewriteRule[] rules = null;
+
+
+ /**
+ * If rewriting occurs, the whole request will be processed again.
+ */
+ protected ThreadLocal invoked = new ThreadLocal();
+
+
+ /**
+ * Relative path to the configuration file.
+ * Note: If the valve's container is a context, this will be relative to
+ * /WEB-INF/.
+ */
+ protected String resourcePath = "rewrite.properties";
+
+
+ /**
+ * Will be set to true if the valve is associated with a context.
+ */
+ protected boolean context = false;
+
+
+ /**
+ * Maps to be used by the rules.
+ */
+ protected Map maps = new Hashtable();
+
+
+ public void addLifecycleListener(LifecycleListener listener) {
+ lifecycle.addLifecycleListener(listener);
+ }
+
+ public LifecycleListener[] findLifecycleListeners() {
+ return lifecycle.findLifecycleListeners();
+ }
+
+ public void removeLifecycleListener(LifecycleListener listener) {
+ lifecycle.removeLifecycleListener(listener);
+ }
+
+ public void start() throws LifecycleException {
+
+ InputStream is = null;
+
+ // Process configuration file for this valve
+ if (getContainer() instanceof Context) {
+ context = true;
+ is = ((Context) getContainer()).getServletContext()
+ .getResourceAsStream("/WEB-INF/" + resourcePath);
+ if ((is == null) && (container.getLogger().isInfoEnabled())) {
+ container.getLogger().info("No configuration resource found: /WEB-INF/" + resourcePath);
+ }
+ } else {
+ String resourceName = getHostConfigPath(resourcePath);
+ File file = new File(getConfigBase(), resourceName);
+ try {
+ if (!file.exists()) {
+ if (resourceName != null) {
+ // Use getResource and getResourceAsStream
+ is = getClass().getClassLoader()
+ .getResourceAsStream(resourceName);
+ if (is != null && container.getLogger().isDebugEnabled()) {
+ container.getLogger().debug("Read configuration from CL at " + resourceName);
+ }
+ }
+ } else {
+ if (container.getLogger().isDebugEnabled()) {
+ container.getLogger().debug("Read configuration from " + file.getAbsolutePath());
+ }
+ is = new FileInputStream(file);
+ }
+ if ((is == null) && (container.getLogger().isInfoEnabled())) {
+ container.getLogger().info("No configuration resource found: " + resourceName +
+ " in " + getConfigBase().getAbsolutePath() + " or in the classloader");
+ }
+ } catch (Exception e) {
+ container.getLogger().error("Error opening configuration", e);
+ }
+ }
+
+ if (is == null) {
+ // Will use management operations to configure the valve dynamically
+ return;
+ }
+
+ BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+
+ try {
+ parse(reader);
+ } finally {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ container.getLogger().error("Error closing configuration", e);
+ }
+ try {
+ if (is != null) {
+ is.close();
+ }
+ } catch (IOException e) {
+ container.getLogger().error("Error closing configuration", e);
+ }
+ }
+
+ }
+
+ public void setConfiguration(String configuration)
+ throws Exception {
+ maps.clear();
+ parse(new BufferedReader(new StringReader(configuration)));
+ }
+
+ public String getConfiguration() {
+ StringBuffer buffer = new StringBuffer();
+ // FIXME: Output maps if possible
+ for (int i = 0; i < rules.length; i++) {
+ for (int j = 0; j < rules[i].getConditions().length; j++) {
+ buffer.append(rules[i].getConditions()[j].toString()).append("\r\n");
+ }
+ buffer.append(rules[i].toString()).append("\r\n").append("\r\n");
+ }
+ return buffer.toString();
+ }
+
+ protected void parse(BufferedReader reader) throws LifecycleException {
+ ArrayList rules = new ArrayList();
+ ArrayList conditions = new ArrayList();
+ while (true) {
+ try {
+ String line = reader.readLine();
+ if (line == null) {
+ break;
+ }
+ Object result = parse(line);
+ if (result instanceof RewriteRule) {
+ RewriteRule rule = (RewriteRule) result;
+ if (container.getLogger().isDebugEnabled()) {
+ container.getLogger().debug("Add rule with pattern " + rule.getPatternString()
+ + " and substitution " + rule.getSubstitutionString());
+ }
+ for (int i = (conditions.size() - 1); i > 0; i--) {
+ if (conditions.get(i - 1).isOrnext()) {
+ conditions.get(i).setOrnext(true);
+ }
+ }
+ for (int i = 0; i < conditions.size(); i++) {
+ if (container.getLogger().isDebugEnabled()) {
+ RewriteCond cond = conditions.get(i);
+ container.getLogger().debug("Add condition " + cond.getCondPattern()
+ + " test " + cond.getTestString() + " to rule with pattern "
+ + rule.getPatternString() + " and substitution "
+ + rule.getSubstitutionString() + (cond.isOrnext() ? " [OR]" : "")
+ + (cond.isNocase() ? " [NC]" : ""));
+ }
+ rule.addCondition(conditions.get(i));
+ }
+ conditions.clear();
+ rules.add(rule);
+ } else if (result instanceof RewriteCond) {
+ conditions.add((RewriteCond) result);
+ } else if (result instanceof Object[]) {
+ String mapName = (String) ((Object[]) result)[0];
+ RewriteMap map = (RewriteMap) ((Object[]) result)[1];
+ maps.put(mapName, map);
+ if (map instanceof Lifecycle) {
+ ((Lifecycle) map).start();
+ }
+ }
+ } catch (IOException e) {
+ container.getLogger().error("Error reading configuration", e);
+ }
+ }
+ this.rules = (RewriteRule[]) rules.toArray(new RewriteRule[0]);
+
+ // Finish parsing the rules
+ for (int i = 0; i < this.rules.length; i++) {
+ this.rules[i].parse(maps);
+ }
+ }
+
+ public void stop() throws LifecycleException {
+ Iterator values = maps.values().iterator();
+ while (values.hasNext()) {
+ RewriteMap map = values.next();
+ if (map instanceof Lifecycle) {
+ ((Lifecycle) map).stop();
+ }
+ }
+ maps.clear();
+ rules = null;
+ }
+
+
+ public void invoke(Request request, Response response)
+ throws IOException, ServletException {
+
+ if (rules == null || rules.length == 0) {
+ getNext().invoke(request, response);
+ return;
+ }
+
+ if (invoked.get() == Boolean.TRUE) {
+ getNext().invoke(request, response);
+ invoked.set(null);
+ return;
+ }
+
+ TomcatResolver resolver = new TomcatResolver(request);
+
+ invoked.set(Boolean.TRUE);
+
+ // As long as MB isn't a char sequence or affiliated, this has to be
+ // converted to a string
+ MessageBytes urlMB = context ? request.getRequestPathMB() : request.getDecodedRequestURIMB();
+ urlMB.toChars();
+ CharSequence url = urlMB.getCharChunk();
+ CharSequence host = request.getServerName();
+ boolean rewritten = false;
+ boolean done = false;
+ for (int i = 0; i < rules.length; i++) {
+ CharSequence test = (rules[i].isHost()) ? host : url;
+ CharSequence newtest = rules[i].evaluate(test, resolver);
+ if (newtest != null && !test.equals(newtest.toString())) {
+ if (container.getLogger().isDebugEnabled()) {
+ container.getLogger().debug("Rewrote " + test + " as " + newtest
+ + " with rule pattern " + rules[i].getPatternString());
+ }
+ if (rules[i].isHost()) {
+ host = newtest;
+ } else {
+ url = newtest;
+ }
+ rewritten = true;
+ }
+
+ // Final reply
+
+ // - forbidden
+ if (rules[i].isForbidden() && newtest != null) {
+ response.sendError(HttpServletResponse.SC_FORBIDDEN);
+ done = true;
+ break;
+ }
+ // - gone
+ if (rules[i].isGone() && newtest != null) {
+ response.sendError(HttpServletResponse.SC_GONE);
+ done = true;
+ break;
+ }
+ // - redirect (code)
+ if (rules[i].isRedirect() && newtest != null) {
+ // append the query string to the url if there is one and it hasn't been rewritten
+ String queryString = request.getQueryString();
+ StringBuffer urlString = new StringBuffer(url);
+ if (queryString != null && queryString.length() > 0) {
+ int index = urlString.indexOf("?");
+ if (index != -1) {
+ // if qsa is specified append the query
+ if (rules[i].isQsappend()) {
+ urlString.append('&');
+ urlString.append(queryString);
+ }
+ // if the ? is the last character delete it, its only purpose was to
+ // prevent the rewrite module from appending the query string
+ else if (index == urlString.length() - 1) {
+ urlString.deleteCharAt(index);
+ }
+ } else {
+ urlString.append('?');
+ urlString.append(queryString);
+ }
+ }
+ // Insert the context if
+ // 1. this valve is associated with a context
+ // 2. the url starts with a leading slash
+ // 3. the url isn't absolute
+ if (context && urlString.charAt(0) == '/' && !hasScheme(urlString)) {
+ urlString.insert(0, request.getContext().getEncodedPath());
+ }
+ response.sendRedirect(urlString.toString());
+ response.setStatus(rules[i].getRedirectCode());
+ done = true;
+ break;
+ }
+
+ // Reply modification
+
+ // - cookie
+ if (rules[i].isCookie() && newtest != null) {
+ TomcatCookie cookie = new TomcatCookie(rules[i].getCookieName(),
+ rules[i].getCookieResult());
+ cookie.setDomain(rules[i].getCookieDomain());
+ cookie.setMaxAge(rules[i].getCookieLifetime());
+ cookie.setPath(rules[i].getCookiePath());
+ cookie.setSecure(rules[i].isCookieSecure());
+ cookie.setHttpOnly(rules[i].isCookieHttpOnly());
+ response.addCookie(cookie);
+ }
+ // - env (note: this sets a request attribute)
+ if (rules[i].isEnv() && newtest != null) {
+ for (int j = 0; j < rules[i].getEnvSize(); j++) {
+ request.setAttribute(rules[i].getEnvName(j), rules[i].getEnvResult(j));
+ }
+ }
+ // - content type (note: this will not force the content type, use a filter
+ // to do that)
+ if (rules[i].isType() && newtest != null) {
+ request.setContentType(rules[i].getTypeValue());
+ }
+ // - qsappend
+ if (rules[i].isQsappend() && newtest != null) {
+ String queryString = request.getQueryString();
+ String urlString = url.toString();
+ if (urlString.indexOf('?') != -1 && queryString != null) {
+ url = urlString + "&" + queryString;
+ }
+ }
+
+ // Control flow processing
+
+ // - chain (skip remaining chained rules if this one does not match)
+ if (rules[i].isChain() && newtest == null) {
+ for (int j = i; j < rules.length; j++) {
+ if (!rules[j].isChain()) {
+ i = j;
+ break;
+ }
+ }
+ continue;
+ }
+ // - last (stop rewriting here)
+ if (rules[i].isLast() && newtest != null) {
+ break;
+ }
+ // - next (redo again)
+ if (rules[i].isNext() && newtest != null) {
+ i = 0;
+ continue;
+ }
+ // - skip (n rules)
+ if (newtest != null) {
+ i += rules[i].getSkip();
+ }
+
+ }
+
+ if (rewritten) {
+ if (!done) {
+ // See if we need to replace the query string
+ String urlString = url.toString();
+ String queryString = null;
+ int queryIndex = urlString.indexOf('?');
+ if (queryIndex != -1) {
+ queryString = urlString.substring(queryIndex+1);
+ urlString = urlString.substring(0, queryIndex);
+ }
+ // Set the new URL
+ CharChunk chunk = request.getCoyoteRequest().requestURI().getCharChunk();
+ chunk.recycle();
+ if (context) {
+ chunk.append(request.getContextPath());
+ }
+ chunk.append(urlString);
+ request.getCoyoteRequest().requestURI().toChars();
+ // Set the new Query if there is one
+ if (queryString != null) {
+ chunk = request.getCoyoteRequest().queryString().getCharChunk();
+ chunk.recycle();
+ chunk.append(queryString);
+ request.getCoyoteRequest().queryString().toChars();
+ }
+ // Set the new host if it changed
+ if (!host.equals(request.getServerName())) {
+ chunk = request.getCoyoteRequest().serverName().getCharChunk();
+ chunk.recycle();
+ chunk.append(host.toString());
+ request.getCoyoteRequest().serverName().toChars();
+ }
+ request.getMappingData().recycle();
+ // Reinvoke the whole request recursively
+ try {
+ request.getConnector().getProtocolHandler().getAdapter().service
+ (request.getCoyoteRequest(), response.getCoyoteResponse());
+ } catch (Exception e) {
+ // This doesn't actually happen in the Catalina adapter implementation
+ }
+ }
+ } else {
+ getNext().invoke(request, response);
+ }
+
+ invoked.set(null);
+
+ }
+
+
+ /**
+ * Get config base.
+ */
+ protected File getConfigBase() {
+ File configBase =
+ new File(System.getProperty("catalina.base"), "conf");
+ if (!configBase.exists()) {
+ return null;
+ } else {
+ return configBase;
+ }
+ }
+
+
+ /**
+ * Find the configuration path where the rewrite configuration file
+ * will be stored.
+ *
+ * @param resourceName
+ * @return
+ */
+ protected String getHostConfigPath(String resourceName) {
+ StringBuffer result = new StringBuffer();
+ Container container = getContainer();
+ Container host = null;
+ Container engine = null;
+ while (container != null) {
+ if (container instanceof Host)
+ host = container;
+ if (container instanceof Engine)
+ engine = container;
+ container = container.getParent();
+ }
+ if (engine != null) {
+ result.append(engine.getName()).append('/');
+ }
+ if (host != null) {
+ result.append(host.getName()).append('/');
+ }
+ result.append(resourceName);
+ return result.toString();
+ }
+
+
+ /**
+ * This factory method will parse a line formed like:
+ *
+ * Example:
+ * RewriteCond %{REMOTE_HOST} ^host1.* [OR]
+ *
+ * @param line
+ * @return
+ */
+ public static Object parse(String line) {
+ StringTokenizer tokenizer = new StringTokenizer(line);
+ if (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ if (token.equals("RewriteCond")) {
+ // RewriteCond TestString CondPattern [Flags]
+ RewriteCond condition = new RewriteCond();
+ if (tokenizer.countTokens() < 2) {
+ throw new IllegalArgumentException("Invalid line: " + line);
+ }
+ condition.setTestString(tokenizer.nextToken());
+ condition.setCondPattern(tokenizer.nextToken());
+ if (tokenizer.hasMoreTokens()) {
+ String flags = tokenizer.nextToken();
+ if (flags.startsWith("[") && flags.endsWith("]")) {
+ flags = flags.substring(1, flags.length() - 1);
+ }
+ StringTokenizer flagsTokenizer = new StringTokenizer(flags, ",");
+ while (flagsTokenizer.hasMoreElements()) {
+ parseCondFlag(line, condition, flagsTokenizer.nextToken());
+ }
+ }
+ return condition;
+ } else if (token.equals("RewriteRule")) {
+ // RewriteRule Pattern Substitution [Flags]
+ RewriteRule rule = new RewriteRule();
+ if (tokenizer.countTokens() < 2) {
+ throw new IllegalArgumentException("Invalid line: " + line);
+ }
+ rule.setPatternString(tokenizer.nextToken());
+ rule.setSubstitutionString(tokenizer.nextToken());
+ if (tokenizer.hasMoreTokens()) {
+ String flags = tokenizer.nextToken();
+ if (flags.startsWith("[") && flags.endsWith("]")) {
+ flags = flags.substring(1, flags.length() - 1);
+ }
+ StringTokenizer flagsTokenizer = new StringTokenizer(flags, ",");
+ while (flagsTokenizer.hasMoreElements()) {
+ parseRuleFlag(line, rule, flagsTokenizer.nextToken());
+ }
+ }
+ return rule;
+ } else if (token.equals("RewriteMap")) {
+ // RewriteMap name rewriteMapClassName whateverOptionalParameterInWhateverFormat
+ if (tokenizer.countTokens() < 2) {
+ throw new IllegalArgumentException("Invalid line: " + line);
+ }
+ String name = tokenizer.nextToken();
+ String rewriteMapClassName = tokenizer.nextToken();
+ RewriteMap map = null;
+ try {
+ map = (RewriteMap) (Class.forName(rewriteMapClassName).newInstance());
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Invalid map className: " + line);
+ }
+ if (tokenizer.hasMoreTokens()) {
+ map.setParameters(tokenizer.nextToken());
+ }
+ Object[] result = new Object[2];
+ result[0] = name;
+ result[1] = map;
+ return result;
+ } else if (token.startsWith("#")) {
+ // it's a comment, ignore it
+ } else {
+ throw new IllegalArgumentException("Invalid line: " + line);
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Parser for RewriteCond flags.
+ *
+ * @param condition
+ * @param flag
+ */
+ protected static void parseCondFlag(String line, RewriteCond condition, String flag) {
+ if (flag.equals("NC") || flag.equals("nocase")) {
+ condition.setNocase(true);
+ } else if (flag.equals("OR") || flag.equals("ornext")) {
+ condition.setOrnext(true);
+ } else {
+ throw new IllegalArgumentException("Invalid flag in: " + line + " flags: " + flag);
+ }
+ }
+
+
+ /**
+ * Parser for ReweriteRule flags.
+ *
+ * @param rule
+ * @param flag
+ */
+ protected static void parseRuleFlag(String line, RewriteRule rule, String flag) {
+ if (flag.equals("chain") || flag.equals("C")) {
+ rule.setChain(true);
+ } else if (flag.startsWith("cookie=") || flag.startsWith("C=")) {
+ rule.setCookie(true);
+ if (flag.startsWith("cookie")) {
+ flag = flag.substring("cookie=".length());
+ } else if (flag.startsWith("C=")) {
+ flag = flag.substring("C=".length());
+ }
+ StringTokenizer tokenizer = new StringTokenizer(flag, ":");
+ if (tokenizer.countTokens() < 2) {
+ throw new IllegalArgumentException("Invalid flag in: " + line);
+ }
+ rule.setCookieName(tokenizer.nextToken());
+ rule.setCookieValue(tokenizer.nextToken());
+ if (tokenizer.hasMoreTokens()) {
+ rule.setCookieDomain(tokenizer.nextToken());
+ }
+ if (tokenizer.hasMoreTokens()) {
+ try {
+ rule.setCookieLifetime(Integer.parseInt(tokenizer.nextToken()));
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid flag in: " + line, e);
+ }
+ }
+ if (tokenizer.hasMoreTokens()) {
+ rule.setCookiePath(tokenizer.nextToken());
+ }
+ if (tokenizer.hasMoreTokens()) {
+ rule.setCookieSecure(Boolean.parseBoolean(tokenizer.nextToken()));
+ }
+ if (tokenizer.hasMoreTokens()) {
+ rule.setCookieHttpOnly(Boolean.parseBoolean(tokenizer.nextToken()));
+ }
+ } else if (flag.startsWith("env=") || flag.startsWith("E=")) {
+ rule.setEnv(true);
+ if (flag.startsWith("env=")) {
+ flag = flag.substring("env=".length());
+ } else if (flag.startsWith("E=")) {
+ flag = flag.substring("E=".length());
+ }
+ int pos = flag.indexOf(':');
+ if (pos == -1 || (pos + 1) == flag.length()) {
+ throw new IllegalArgumentException("Invalid flag in: " + line);
+ }
+ rule.addEnvName(flag.substring(0, pos));
+ rule.addEnvValue(flag.substring(pos + 1));
+ } else if (flag.startsWith("forbidden") || flag.startsWith("F")) {
+ rule.setForbidden(true);
+ } else if (flag.startsWith("gone") || flag.startsWith("G")) {
+ rule.setGone(true);
+ } else if (flag.startsWith("host") || flag.startsWith("H")) {
+ rule.setHost(true);
+ } else if (flag.startsWith("last") || flag.startsWith("L")) {
+ rule.setLast(true);
+ } else if (flag.startsWith("next") || flag.startsWith("N")) {
+ rule.setNext(true);
+ } else if (flag.startsWith("nocase") || flag.startsWith("NC")) {
+ rule.setNocase(true);
+ } else if (flag.startsWith("noescape") || flag.startsWith("NE")) {
+ rule.setNoescape(true);
+ } else if (flag.startsWith("proxy") || flag.startsWith("P")) {
+ // FIXME: Proxy not supported at the moment, would require proxy capabilities
+ //rule.setProxy(true);
+ } else if (flag.startsWith("qsappend") || flag.startsWith("QSA")) {
+ rule.setQsappend(true);
+ } else if (flag.startsWith("redirect") || flag.startsWith("R")) {
+ if (flag.startsWith("redirect=")) {
+ flag = flag.substring("redirect=".length());
+ rule.setRedirect(true);
+ rule.setRedirectCode(Integer.parseInt(flag));
+ } else if (flag.startsWith("R=")) {
+ flag = flag.substring("R=".length());
+ rule.setRedirect(true);
+ rule.setRedirectCode(Integer.parseInt(flag));
+ } else {
+ rule.setRedirect(true);
+ rule.setRedirectCode(HttpServletResponse.SC_FOUND);
+ }
+ } else if (flag.startsWith("skip") || flag.startsWith("S")) {
+ if (flag.startsWith("skip=")) {
+ flag = flag.substring("skip=".length());
+ } else if (flag.startsWith("S=")) {
+ flag = flag.substring("S=".length());
+ }
+ rule.setSkip(Integer.parseInt(flag));
+ } else if (flag.startsWith("type") || flag.startsWith("T")) {
+ if (flag.startsWith("type=")) {
+ flag = flag.substring("type=".length());
+ } else if (flag.startsWith("T=")) {
+ flag = flag.substring("T=".length());
+ }
+ rule.setType(true);
+ rule.setTypeValue(flag);
+ } else {
+ throw new IllegalArgumentException("Invalid flag in: " + line + " flag: " + flag);
+ }
+ }
+
+
+ /**
+ * Determine if a URI string has a scheme
component.
+ */
+ protected static boolean hasScheme(StringBuffer uri) {
+ int len = uri.length();
+ for(int i=0; i < len ; i++) {
+ char c = uri.charAt(i);
+ if(c == ':') {
+ return i > 0;
+ } else if(!URL.isSchemeChar(c)) {
+ return false;
+ }
+ }
+ return false;
+ }
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/rewrite/Substitution.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/rewrite/Substitution.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/rewrite/Substitution.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,240 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+
+package org.jboss.web.rewrite;
+
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.regex.Matcher;
+
+public class Substitution {
+
+ public abstract class SubstitutionElement {
+ public abstract String evaluate(Matcher rule, Matcher cond, Resolver resolver);
+ }
+
+ public class StaticElement extends SubstitutionElement {
+ public String value;
+
+ public String evaluate
+ (Matcher rule, Matcher cond, Resolver resolver) {
+ return value;
+ }
+
+ }
+
+ public class RewriteRuleBackReferenceElement extends SubstitutionElement {
+ public int n;
+ public String evaluate(Matcher rule, Matcher cond, Resolver resolver) {
+ return rule.group(n);
+ }
+ }
+
+ public class RewriteCondBackReferenceElement extends SubstitutionElement {
+ public int n;
+ public String evaluate(Matcher rule, Matcher cond, Resolver resolver) {
+ return cond.group(n);
+ }
+ }
+
+ public class ServerVariableElement extends SubstitutionElement {
+ public String key;
+ public String evaluate(Matcher rule, Matcher cond, Resolver resolver) {
+ return resolver.resolve(key);
+ }
+ }
+
+ public class ServerVariableEnvElement extends SubstitutionElement {
+ public String key;
+ public String evaluate(Matcher rule, Matcher cond, Resolver resolver) {
+ return resolver.resolveEnv(key);
+ }
+ }
+
+ public class ServerVariableSslElement extends SubstitutionElement {
+ public String key;
+ public String evaluate(Matcher rule, Matcher cond, Resolver resolver) {
+ return resolver.resolveSsl(key);
+ }
+ }
+
+ public class ServerVariableHttpElement extends SubstitutionElement {
+ public String key;
+ public String evaluate(Matcher rule, Matcher cond, Resolver resolver) {
+ return resolver.resolveHttp(key);
+ }
+ }
+
+ public class MapElement extends SubstitutionElement {
+ public RewriteMap map = null;
+ public String key;
+ public String defaultValue = null;
+ public String evaluate(Matcher rule, Matcher cond, Resolver resolver) {
+ String result = map.lookup(key);
+ if (result == null) {
+ result = defaultValue;
+ }
+ return result;
+ }
+ }
+
+ protected SubstitutionElement[] elements = null;
+
+ protected String sub = null;
+ public String getSub() { return sub; }
+ public void setSub(String sub) { this.sub = sub; }
+
+ public void parse(Map maps) {
+
+ ArrayList elements = new ArrayList();
+ int pos = 0;
+ int percentPos = 0;
+ int dollarPos = 0;
+
+ while (pos < sub.length()) {
+ percentPos = sub.indexOf('%', pos);
+ dollarPos = sub.indexOf('$', pos);
+ if (percentPos == -1 && dollarPos == -1) {
+ // Static text
+ StaticElement newElement = new StaticElement();
+ newElement.value = sub.substring(pos, sub.length());
+ pos = sub.length();
+ elements.add(newElement);
+ } else if (percentPos == -1 || ((dollarPos != -1) && (dollarPos < percentPos))) {
+ // $: back reference to rule or map lookup
+ if (dollarPos + 1 == sub.length()) {
+ throw new IllegalArgumentException(sub);
+ }
+ if (pos < dollarPos) {
+ // Static text
+ StaticElement newElement = new StaticElement();
+ newElement.value = sub.substring(pos, dollarPos);
+ pos = dollarPos;
+ elements.add(newElement);
+ }
+ if (Character.isDigit(sub.charAt(dollarPos + 1))) {
+ // $: back reference to rule
+ RewriteRuleBackReferenceElement newElement = new RewriteRuleBackReferenceElement();
+ newElement.n = Character.digit(sub.charAt(dollarPos + 1), 10);
+ pos = dollarPos + 2;
+ elements.add(newElement);
+ } else {
+ // $: map lookup as ${mapname:key|default}
+ MapElement newElement = new MapElement();
+ int open = sub.indexOf('{', dollarPos);
+ int colon = sub.indexOf(':', dollarPos);
+ int def = sub.indexOf('|', dollarPos);
+ int close = sub.indexOf('}', dollarPos);
+ if (!(-1 < open && open < colon && colon < close)) {
+ throw new IllegalArgumentException(sub);
+ }
+ newElement.map = maps.get(sub.substring(open + 1, colon));
+ if (newElement.map == null) {
+ throw new IllegalArgumentException(sub + ": No map: " + sub.substring(open + 1, colon));
+ }
+ if (def > -1) {
+ if (!(colon < def && def < close)) {
+ throw new IllegalArgumentException(sub);
+ }
+ newElement.key = sub.substring(colon + 1, def);
+ newElement.defaultValue = sub.substring(def + 1, close);
+ } else {
+ newElement.key = sub.substring(colon + 1, close);
+ }
+ pos = close + 1;
+ elements.add(newElement);
+ }
+ } else {
+ // %: back reference to condition or server variable
+ if (percentPos + 1 == sub.length()) {
+ throw new IllegalArgumentException(sub);
+ }
+ if (pos < percentPos) {
+ // Static text
+ StaticElement newElement = new StaticElement();
+ newElement.value = sub.substring(pos, percentPos);
+ pos = percentPos;
+ elements.add(newElement);
+ }
+ if (Character.isDigit(sub.charAt(percentPos + 1))) {
+ // %: back reference to condition
+ RewriteCondBackReferenceElement newElement = new RewriteCondBackReferenceElement();
+ newElement.n = Character.digit(sub.charAt(percentPos + 1), 10);
+ pos = percentPos + 2;
+ elements.add(newElement);
+ } else {
+ // %: server variable as %{variable}
+ SubstitutionElement newElement = null;
+ int open = sub.indexOf('{', percentPos);
+ int colon = sub.indexOf(':', percentPos);
+ int close = sub.indexOf('}', percentPos);
+ if (!(-1 < open && open < close)) {
+ throw new IllegalArgumentException(sub);
+ }
+ if (colon > -1) {
+ if (!(open < colon && colon < close)) {
+ throw new IllegalArgumentException(sub);
+ }
+ String type = sub.substring(open + 1, colon);
+ if (type.equals("ENV")) {
+ newElement = new ServerVariableEnvElement();
+ ((ServerVariableEnvElement) newElement).key = sub.substring(colon + 1, close);
+ } else if (type.equals("SSL")) {
+ newElement = new ServerVariableSslElement();
+ ((ServerVariableSslElement) newElement).key = sub.substring(colon + 1, close);
+ } else if (type.equals("HTTP")) {
+ newElement = new ServerVariableHttpElement();
+ ((ServerVariableHttpElement) newElement).key = sub.substring(colon + 1, close);
+ } else {
+ throw new IllegalArgumentException(sub + ": Bad type: " + type);
+ }
+ } else {
+ newElement = new ServerVariableElement();
+ ((ServerVariableElement) newElement).key = sub.substring(open + 1, close);
+ }
+ pos = close + 1;
+ elements.add(newElement);
+ }
+ }
+ }
+
+ this.elements = (SubstitutionElement[]) elements.toArray(new SubstitutionElement[0]);
+
+ }
+
+ /**
+ * Evaluate the substitution based on the context
+ *
+ * @param rule corresponding matched rule
+ * @param cond last matched condition
+ * @return
+ */
+ public String evaluate(Matcher rule, Matcher cond, Resolver resolver) {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < elements.length; i++) {
+ buf.append(elements[i].evaluate(rule, cond, resolver));
+ }
+ return buf.toString();
+ }
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/rewrite/TomcatResolver.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/rewrite/TomcatResolver.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/rewrite/TomcatResolver.java 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,175 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+
+package org.jboss.web.rewrite;
+
+import java.util.Calendar;
+
+import org.apache.catalina.connector.Request;
+
+import org.apache.naming.resources.CacheEntry;
+import org.apache.naming.resources.ProxyDirContext;
+import org.apache.tomcat.util.http.FastHttpDateFormat;
+
+public class TomcatResolver extends Resolver {
+
+ protected Request request = null;
+
+ public TomcatResolver(Request request) {
+ this.request = request;
+ }
+
+ /**
+ * The following are not implemented:
+ * - SERVER_ADMIN
+ * - API_VERSION
+ * - IS_SUBREQ
+ */
+ public String resolve(String key) {
+ if (key.equals("HTTP_USER_AGENT")) {
+ return request.getHeader("user-agent");
+ } else if (key.equals("HTTP_REFERER")) {
+ return request.getHeader("referer");
+ } else if (key.equals("HTTP_COOKIE")) {
+ return request.getHeader("cookie");
+ } else if (key.equals("HTTP_FORWARDED")) {
+ return request.getHeader("forwarded");
+ } else if (key.equals("HTTP_HOST")) {
+ String host = request.getHeader("host");
+ int index = host.indexOf(':');
+ if (index != -1)
+ host = host.substring(0, index);
+ return host;
+ } else if (key.equals("HTTP_PROXY_CONNECTION")) {
+ return request.getHeader("proxy-connection");
+ } else if (key.equals("HTTP_ACCEPT")) {
+ return request.getHeader("accept");
+ } else if (key.equals("REMOTE_ADDR")) {
+ return request.getRemoteAddr();
+ } else if (key.equals("REMOTE_HOST")) {
+ return request.getRemoteHost();
+ } else if (key.equals("REMOTE_PORT")) {
+ return String.valueOf(request.getRemotePort());
+ } else if (key.equals("REMOTE_USER")) {
+ return request.getRemoteUser();
+ } else if (key.equals("REMOTE_IDENT")) {
+ return request.getRemoteUser();
+ } else if (key.equals("REQUEST_METHOD")) {
+ return request.getMethod();
+ } else if (key.equals("SCRIPT_FILENAME")) {
+ return request.getRealPath(request.getServletPath()); //FIXME ?
+ } else if (key.equals("REQUEST_PATH")) {
+ return request.getRequestPathMB().toString();
+ } else if (key.equals("CONTEXT_PATH")) {
+ return request.getContextPath();
+ } else if (key.equals("SERVLET_PATH")) {
+ return emptyStringIfNull(request.getServletPath());
+ } else if (key.equals("PATH_INFO")) {
+ return emptyStringIfNull(request.getPathInfo());
+ } else if (key.equals("QUERY_STRING")) {
+ return emptyStringIfNull(request.getQueryString());
+ } else if (key.equals("AUTH_TYPE")) {
+ return request.getAuthType();
+ } else if (key.equals("DOCUMENT_ROOT")) {
+ return request.getRealPath("/");
+ } else if (key.equals("SERVER_NAME")) {
+ return request.getLocalName();
+ } else if (key.equals("SERVER_ADDR")) {
+ return request.getLocalAddr();
+ } else if (key.equals("SERVER_PORT")) {
+ return String.valueOf(request.getLocalPort());
+ } else if (key.equals("SERVER_PROTOCOL")) {
+ return request.getProtocol();
+ } else if (key.equals("SERVER_SOFTWARE")) {
+ return "tomcat";
+ } else if (key.equals("THE_REQUEST")) {
+ return request.getMethod() + " " + request.getRequestURI()
+ + " " + request.getProtocol();
+ } else if (key.equals("REQUEST_URI")) {
+ return request.getRequestURI();
+ } else if (key.equals("REQUEST_FILENAME")) {
+ return request.getPathTranslated();
+ } else if (key.equals("HTTPS")) {
+ return request.isSecure() ? "on" : "off";
+ } else if (key.equals("TIME_YEAR")) {
+ return String.valueOf(Calendar.getInstance().get(Calendar.YEAR));
+ } else if (key.equals("TIME_MON")) {
+ return String.valueOf(Calendar.getInstance().get(Calendar.MONTH));
+ } else if (key.equals("TIME_DAY")) {
+ return String.valueOf(Calendar.getInstance().get(Calendar.DAY_OF_MONTH));
+ } else if (key.equals("TIME_HOUR")) {
+ return String.valueOf(Calendar.getInstance().get(Calendar.HOUR_OF_DAY));
+ } else if (key.equals("TIME_MIN")) {
+ return String.valueOf(Calendar.getInstance().get(Calendar.MINUTE));
+ } else if (key.equals("TIME_SEC")) {
+ return String.valueOf(Calendar.getInstance().get(Calendar.SECOND));
+ } else if (key.equals("TIME_WDAY")) {
+ return String.valueOf(Calendar.getInstance().get(Calendar.DAY_OF_WEEK));
+ } else if (key.equals("TIME")) {
+ return FastHttpDateFormat.getCurrentDate();
+ }
+ return null;
+ }
+
+ public String resolveEnv(String key) {
+ return System.getProperty(key);
+ }
+
+ public String resolveSsl(String key) {
+ // FIXME: Implement SSL environment variables
+ return null;
+ }
+
+ public String resolveHttp(String key) {
+ return request.getHeader(key);
+ }
+
+ public boolean resolveResource(int type, String name) {
+ ProxyDirContext resources = (ProxyDirContext) request.getContext().getResources();
+ CacheEntry cacheEntry = resources.lookupCache(name);
+ if (!cacheEntry.exists) {
+ return false;
+ } else {
+ switch (type) {
+ case 0:
+ return (cacheEntry.resource == null);
+ case 1:
+ return (cacheEntry.resource != null);
+ case 2:
+ return (cacheEntry.resource != null
+ && cacheEntry.attributes.getContentLength() > 0);
+ default:
+ return false;
+ }
+ }
+ }
+
+ private static final String emptyStringIfNull(String value) {
+ if (value == null) {
+ return "";
+ } else {
+ return value;
+ }
+ }
+
+}
Index: 3rdParty_sources/jbossweb/org/jboss/web/rewrite/mbeans-descriptors.xml
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jbossweb/org/jboss/web/rewrite/mbeans-descriptors.xml,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jbossweb/org/jboss/web/rewrite/mbeans-descriptors.xml 17 Aug 2012 14:43:39 -0000 1.1
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/common/Assert.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/common/Assert.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/common/Assert.java 17 Aug 2012 14:51:26 -0000 1.1
@@ -0,0 +1,61 @@
+/*********************************************************************
+*
+* Copyright (C) 2006 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package common;
+
+/**
+ * Simple assertion mechanism for use during development
+ */
+public final class Assert
+{
+ /**
+ * Throws an AssertionFailed exception if the specified condition is
+ * false
+ *
+ * @param condition The assertion condition which must be true
+ */
+ public static void verify(boolean condition)
+ {
+ if (!condition)
+ {
+ throw new AssertionFailed();
+ }
+ }
+
+ /**
+ * If the condition evaluates to false, an AssertionFailed is thrown
+ *
+ * @param message A message thrown with the failed assertion
+ * @param condition If this evaluates to false, an AssertionFailed is thrown
+ */
+ public static void verify(boolean condition, String message)
+ {
+ if (!condition)
+ {
+ throw new AssertionFailed(message);
+ }
+ }
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/common/AssertionFailed.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/common/AssertionFailed.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/common/AssertionFailed.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,48 @@
+/*********************************************************************
+*
+* Copyright (C) 2006 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+
+package common;
+
+/**
+ * An exception thrown when an assert (from the Assert class) fails
+ */
+public class AssertionFailed extends RuntimeException
+{
+ /**
+ * Default constructor
+ * Prints the stack trace
+ */
+ public AssertionFailed()
+ {
+ super();
+ printStackTrace();
+ }
+
+ /**
+ * Constructor with message
+ * Prints the stack trace
+ *
+ * @param s Message thrown with the assertion
+ */
+ public AssertionFailed(String s)
+ {
+ super(s);
+ }
+}
Index: 3rdParty_sources/jexcelapi/common/BaseUnit.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/common/BaseUnit.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/common/BaseUnit.java 17 Aug 2012 14:51:26 -0000 1.1
@@ -0,0 +1,35 @@
+/*********************************************************************
+*
+* Copyright (C) 2006 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package common;
+
+public class BaseUnit
+{
+ private int index;
+
+ protected BaseUnit(int ind)
+ {
+ index = ind;
+ }
+
+ protected int getIndex()
+ {
+ return index;
+ }
+}
Index: 3rdParty_sources/jexcelapi/common/LengthConverter.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/common/LengthConverter.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/common/LengthConverter.java 17 Aug 2012 14:51:26 -0000 1.1
@@ -0,0 +1,60 @@
+/*********************************************************************
+*
+* Copyright (C) 2006 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package common;
+
+public class LengthConverter
+{
+ private static double[][] factors =
+ new double[LengthUnit.getCount()][LengthUnit.getCount()];
+
+ static
+ {
+ // The identity factors
+ factors[LengthUnit.POINTS.getIndex()][LengthUnit.POINTS.getIndex()] = 1;
+ factors[LengthUnit.METRES.getIndex()][LengthUnit.METRES.getIndex()] = 1;
+ factors[LengthUnit.CENTIMETRES.getIndex()][LengthUnit.CENTIMETRES.getIndex()] = 1;
+ factors[LengthUnit.INCHES.getIndex()][LengthUnit.INCHES.getIndex()] = 1;
+
+ // The points conversion factors
+ factors[LengthUnit.POINTS.getIndex()][LengthUnit.METRES.getIndex()] = 0.00035277777778;
+ factors[LengthUnit.POINTS.getIndex()][LengthUnit.CENTIMETRES.getIndex()] = 0.035277777778;
+ factors[LengthUnit.POINTS.getIndex()][LengthUnit.INCHES.getIndex()] = 0.013888888889;
+
+ // The metres conversion factors
+ factors[LengthUnit.METRES.getIndex()][LengthUnit.POINTS.getIndex()] = 2877.84;
+ factors[LengthUnit.METRES.getIndex()][LengthUnit.CENTIMETRES.getIndex()] = 100;
+ factors[LengthUnit.METRES.getIndex()][LengthUnit.INCHES.getIndex()] = 39.37;
+
+ // The centimetres conversion factors
+ factors[LengthUnit.CENTIMETRES.getIndex()][LengthUnit.POINTS.getIndex()] = 28.34643;
+ factors[LengthUnit.CENTIMETRES.getIndex()][LengthUnit.METRES.getIndex()] = 0.01;
+ factors[LengthUnit.CENTIMETRES.getIndex()][LengthUnit.INCHES.getIndex()] = 0.3937;
+
+ // The inches conversion factors
+ factors[LengthUnit.INCHES.getIndex()][LengthUnit.POINTS.getIndex()] = 72;
+ factors[LengthUnit.INCHES.getIndex()][LengthUnit.METRES.getIndex()] = 0.0254;
+ factors[LengthUnit.INCHES.getIndex()][LengthUnit.CENTIMETRES.getIndex()] = 2.54;
+ }
+
+ public static double getConversionFactor(LengthUnit from, LengthUnit to)
+ {
+ return factors[from.getIndex()][to.getIndex()];
+ }
+}
Index: 3rdParty_sources/jexcelapi/common/LengthUnit.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/common/LengthUnit.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/common/LengthUnit.java 17 Aug 2012 14:51:26 -0000 1.1
@@ -0,0 +1,44 @@
+/*********************************************************************
+*
+* Copyright (C) 2006 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package common;
+
+
+/**
+ * Enumeration for units
+ */
+public class LengthUnit extends BaseUnit
+{
+ private static int count = 0;
+
+ private LengthUnit()
+ {
+ super(count++);
+ }
+
+ public static int getCount()
+ {
+ return count;
+ }
+
+ public static LengthUnit POINTS = new LengthUnit();
+ public static LengthUnit METRES = new LengthUnit();
+ public static LengthUnit CENTIMETRES = new LengthUnit();
+ public static LengthUnit INCHES = new LengthUnit();
+}
Index: 3rdParty_sources/jexcelapi/common/Logger.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/common/Logger.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/common/Logger.java 17 Aug 2012 14:51:26 -0000 1.1
@@ -0,0 +1,173 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package common;
+
+import java.security.AccessControlException;
+
+/**
+ * Abstract wrapper class for the logging interface of choice.
+ * The methods declared here are the same as those for the log4j
+ */
+public abstract class Logger
+{
+ /**
+ * The singleton logger
+ */
+ private static Logger logger = null;
+
+ /**
+ * Factory method to return the logger
+ */
+ public static final Logger getLogger(Class cl)
+ {
+ if (logger == null)
+ {
+ initializeLogger();
+ }
+
+ return logger.getLoggerImpl(cl);
+ }
+
+ /**
+ * Initializes the logger in a thread safe manner
+ */
+ private synchronized static void initializeLogger()
+ {
+ if (logger != null)
+ {
+ return;
+ }
+
+ String loggerName = common.log.LoggerName.NAME;
+
+ try
+ {
+ // First see if there was anything defined at run time
+ loggerName = System.getProperty("logger");
+
+ if (loggerName == null)
+ {
+ // Get the logger name from the compiled in logger
+ loggerName = common.log.LoggerName.NAME;
+ }
+
+ logger = (Logger) Class.forName(loggerName).newInstance();
+ }
+ catch(IllegalAccessException e)
+ {
+ logger = new common.log.SimpleLogger();
+ logger.warn("Could not instantiate logger " + loggerName +
+ " using default");
+ }
+ catch(InstantiationException e)
+ {
+ logger = new common.log.SimpleLogger();
+ logger.warn("Could not instantiate logger " + loggerName +
+ " using default");
+ }
+ catch (AccessControlException e)
+ {
+ logger = new common.log.SimpleLogger();
+ logger.warn("Could not instantiate logger " + loggerName +
+ " using default");
+ }
+ catch(ClassNotFoundException e)
+ {
+ logger = new common.log.SimpleLogger();
+ logger.warn("Could not instantiate logger " + loggerName +
+ " using default");
+ }
+ }
+
+ /**
+ * Constructor
+ */
+ protected Logger()
+ {
+ }
+
+ /**
+ * Log a debug message
+ */
+ public abstract void debug(Object message);
+
+ /**
+ * Log a debug message and exception
+ */
+ public abstract void debug(Object message, Throwable t);
+
+ /**
+ * Log an error message
+ */
+ public abstract void error(Object message);
+
+ /**
+ * Log an error message object and exception
+ */
+ public abstract void error(Object message, Throwable t);
+
+ /**
+ * Log a fatal message
+ */
+ public abstract void fatal(Object message);
+
+ /**
+ * Log a fatal message and exception
+ */
+ public abstract void fatal(Object message, Throwable t);
+
+ /**
+ * Log an information message
+ */
+ public abstract void info(Object message);
+
+ /**
+ * Logs an information message and an exception
+ */
+ public abstract void info(Object message, Throwable t);
+
+ /**
+ * Log a warning message object
+ */
+ public abstract void warn(Object message);
+
+ /**
+ * Log a warning message with exception
+ */
+ public abstract void warn(Object message, Throwable t);
+
+ /**
+ * Accessor to the logger implementation
+ */
+ protected abstract Logger getLoggerImpl(Class cl);
+
+ /**
+ * Empty implementation of the suppressWarnings. Subclasses may
+ * or may not override this method. This method is included
+ * primarily for backwards support of the jxl.nowarnings property, and
+ * is used only by the SimpleLogger
+ *
+ * @param w suppression flag
+ */
+ public void setSuppressWarnings(boolean w)
+ {
+ // default implementation does nothing
+ }
+}
Index: 3rdParty_sources/jexcelapi/common/log/Log4JLogger.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/common/log/Log4JLogger.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/common/log/Log4JLogger.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,142 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package common.log;
+
+import org.apache.log4j.Logger;
+
+/**
+ * A logger which uses the log4j library from jakarta. Each instance
+ * of this class acts as a wrapper to the log4j Logger class
+ */
+public class Log4JLogger extends common.Logger
+{
+ /**
+ * The log4j logger
+ */
+ private Logger log4jLogger;
+
+ /**
+ * Default constructor. This constructor is
+ */
+ public Log4JLogger()
+ {
+ super();
+ }
+
+ /**
+ * Constructor invoked by the getLoggerImpl method to return a logger
+ * for a particular class
+ */
+ private Log4JLogger(Logger l)
+ {
+ super();
+ log4jLogger = l;
+ }
+
+ /**
+ * Log a debug message
+ */
+ public void debug(Object message)
+ {
+ log4jLogger.debug(message);
+ }
+
+ /**
+ * Log a debug message and exception
+ */
+ public void debug(Object message, Throwable t)
+ {
+ log4jLogger.debug(message, t);
+ }
+
+ /**
+ * Log an error message
+ */
+ public void error(Object message)
+ {
+ log4jLogger.error(message);
+ }
+
+ /**
+ * Log an error message object and exception
+ */
+ public void error(Object message, Throwable t)
+ {
+ log4jLogger.error(message, t);
+ }
+
+ /**
+ * Log a fatal message
+ */
+ public void fatal(Object message)
+ {
+ log4jLogger.fatal(message);
+ }
+
+ /**
+ * Log a fatal message and exception
+ */
+ public void fatal(Object message, Throwable t)
+ {
+ log4jLogger.fatal(message,t);
+ }
+
+ /**
+ * Log an information message
+ */
+ public void info(Object message)
+ {
+ log4jLogger.info(message);
+ }
+
+ /**
+ * Logs an information message and an exception
+ */
+
+ public void info(Object message, Throwable t)
+ {
+ log4jLogger.info(message, t);
+ }
+
+ /**
+ * Log a warning message object
+ */
+ public void warn(Object message)
+ {
+ log4jLogger.warn(message);
+ }
+
+ /**
+ * Log a warning message with exception
+ */
+ public void warn(Object message, Throwable t)
+ {
+ log4jLogger.warn(message, t);
+ }
+
+ /**
+ * Accessor to the logger implementation
+ */
+ protected common.Logger getLoggerImpl(Class cl)
+ {
+ Logger l = Logger.getLogger(cl);
+ return new Log4JLogger(l);
+ }
+}
Index: 3rdParty_sources/jexcelapi/common/log/Log4jLoggerName.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/common/log/Log4jLoggerName.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/common/log/Log4jLoggerName.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,30 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package common.log;
+
+/**
+ * Static structure containing the class name of the logger. This may
+ * be overwritten at build time if loggers other than the default,
+ * no-dependency logger are required
+ */
+public class LoggerName
+{
+ public final static String NAME=common.log.Log4JLogger.class.getName();
+}
Index: 3rdParty_sources/jexcelapi/common/log/LoggerName.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/common/log/LoggerName.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/common/log/LoggerName.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,30 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package common.log;
+
+/**
+ * Static structure containing the class name of the logger. This may
+ * be overwritten at build time if loggers other than the default,
+ * no-dependency logger are required
+ */
+public class LoggerName
+{
+ public final static String NAME=common.log.SimpleLogger.class.getName();
+}
Index: 3rdParty_sources/jexcelapi/common/log/SimpleLogger.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/common/log/SimpleLogger.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/common/log/SimpleLogger.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,176 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package common.log;
+
+import common.Logger;
+
+/**
+ * The default logger. Simple writes everything out to stdout or stderr
+ */
+public class SimpleLogger extends Logger
+{
+ /**
+ * Flag to indicate whether or not warnings should be suppressed
+ */
+ private boolean suppressWarnings;
+
+ /**
+ * Constructor
+ */
+ public SimpleLogger()
+ {
+ suppressWarnings = false;
+ }
+
+ /**
+ * Log a debug message
+ */
+ public void debug(Object message)
+ {
+ if (!suppressWarnings)
+ {
+ System.out.print("Debug: ");
+ System.out.println(message);
+ }
+ }
+
+ /**
+ * Log a debug message and exception
+ */
+ public void debug(Object message, Throwable t)
+ {
+ if (!suppressWarnings)
+ {
+ System.out.print("Debug: ");
+ System.out.println(message);
+ t.printStackTrace();
+ }
+ }
+
+ /**
+ * Log an error message
+ */
+ public void error(Object message)
+ {
+ System.err.print("Error: ");
+ System.err.println(message);
+ }
+
+ /**
+ * Log an error message object and exception
+ */
+ public void error(Object message, Throwable t)
+ {
+ System.err.print("Error: ");
+ System.err.println(message);
+ t.printStackTrace();
+ }
+
+ /**
+ * Log a fatal message
+ */
+ public void fatal(Object message)
+ {
+ System.err.print("Fatal: ");
+ System.err.println(message);
+ }
+
+ /**
+ * Log a fatal message and exception
+ */
+ public void fatal(Object message, Throwable t)
+ {
+ System.err.print("Fatal: ");
+ System.err.println(message);
+ t.printStackTrace();
+ }
+
+ /**
+ * Log an information message
+ */
+ public void info(Object message)
+ {
+ if (!suppressWarnings)
+ {
+ System.out.println(message);
+ }
+ }
+
+ /**
+ * Logs an information message and an exception
+ */
+
+ public void info(Object message, Throwable t)
+ {
+ if (!suppressWarnings)
+ {
+ System.out.println(message);
+ t.printStackTrace();
+ }
+ }
+
+ /**
+ * Log a warning message object
+ */
+ public void warn(Object message)
+ {
+ if (!suppressWarnings)
+ {
+ System.err.print("Warning: ");
+ System.err.println(message);
+ }
+ }
+
+ /**
+ * Log a warning message with exception
+ */
+ public void warn(Object message, Throwable t)
+ {
+ if (!suppressWarnings)
+ {
+ System.err.print("Warning: ");
+ System.err.println(message);
+ t.printStackTrace();
+ }
+ }
+
+ /**
+ * Accessor to the logger implementation
+ */
+ protected Logger getLoggerImpl(Class c)
+ {
+ return this;
+ }
+
+ /**
+ * Overrides the method in the base class to suppress warnings - it can
+ * be set using the system property jxl.nowarnings.
+ * This method was originally present in the WorkbookSettings bean,
+ * but has been moved to the logger class. This means it is now present
+ * when the JVM is initialized, and subsequent to change it on
+ * a Workbook by Workbook basis will prove fruitless
+ *
+ * @param w suppression flag
+ */
+ public void setSuppressWarnings(boolean w)
+ {
+ suppressWarnings = w;
+ }
+}
Index: 3rdParty_sources/jexcelapi/common/log/SimpleLoggerName.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/common/log/SimpleLoggerName.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/common/log/SimpleLoggerName.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,30 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package common.log;
+
+/**
+ * Static structure containing the class name of the logger. This may
+ * be overwritten at build time if loggers other than the default,
+ * no-dependency logger are required
+ */
+public class LoggerName
+{
+ public final static String NAME=common.log.SimpleLogger.class.getName();
+}
Index: 3rdParty_sources/jexcelapi/jxl/BooleanCell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/BooleanCell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/BooleanCell.java 17 Aug 2012 14:51:24 -0000 1.1
@@ -0,0 +1,46 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+/**
+ * This type represents the Microsoft concept of a Boolean. Accordingly, this
+ * cell represents either TRUE, FALSE or an error condition. This third
+ * state naturally makes handling BooleanCells quite tricky, and use of
+ * the specific access methods should be handled with care
+ */
+public interface BooleanCell extends Cell
+{
+ /**
+ * Gets the boolean value stored in this cell. If this cell contains an
+ * error, then returns FALSE. Always query this cell type using the
+ * accessor method isError() prior to calling this method
+ *
+ * @return TRUE if this cell contains TRUE, FALSE if it contains FALSE or
+ * an error code
+ */
+ public boolean getValue();
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/BooleanFormulaCell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/BooleanFormulaCell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/BooleanFormulaCell.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,28 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+/**
+ * A mixin interface for numerical formulas, which combines the interfaces
+ * for formulas and for numbers
+ */
+public interface BooleanFormulaCell extends BooleanCell, FormulaCell
+{
+}
Index: 3rdParty_sources/jexcelapi/jxl/Cell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/Cell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/Cell.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,87 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+import jxl.format.CellFormat;
+
+/**
+ * Represents an individual Cell within a Sheet. May be queried for its
+ * type and its content
+ */
+public interface Cell
+{
+ /**
+ * Returns the row number of this cell
+ *
+ * @return the row number of this cell
+ */
+ public int getRow();
+
+ /**
+ * Returns the column number of this cell
+ *
+ * @return the column number of this cell
+ */
+ public int getColumn();
+
+ /**
+ * Returns the content type of this cell
+ *
+ * @return the content type for this cell
+ */
+ public CellType getType();
+
+ /**
+ * Indicates whether or not this cell is hidden, by virtue of either
+ * the entire row or column being collapsed
+ *
+ * @return TRUE if this cell is hidden, FALSE otherwise
+ */
+ public boolean isHidden();
+
+ /**
+ * Quick and dirty function to return the contents of this cell as a string.
+ * For more complex manipulation of the contents, it is necessary to cast
+ * this interface to correct subinterface
+ *
+ * @return the contents of this cell as a string
+ */
+ public String getContents();
+
+ /**
+ * Gets the cell format which applies to this cell
+ * Note that for cell with a cell type of EMPTY, which has no formatting
+ * information, this method will return null. Some empty cells (eg. on
+ * template spreadsheets) may have a cell type of EMPTY, but will
+ * actually contain formatting information
+ *
+ * @return the cell format applied to this cell, or NULL if this is an
+ * empty cell
+ */
+ public CellFormat getCellFormat();
+
+ /**
+ * Gets any special cell features, such as comments (notes) or cell
+ * validation present for this cell
+ *
+ * @return the cell features, or NULL if this cell has no special features
+ */
+ public CellFeatures getCellFeatures();
+}
Index: 3rdParty_sources/jexcelapi/jxl/CellFeatures.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/CellFeatures.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/CellFeatures.java 17 Aug 2012 14:51:24 -0000 1.1
@@ -0,0 +1,67 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+import jxl.biff.BaseCellFeatures;
+
+/**
+ * Container for any additional cell features
+ */
+public class CellFeatures extends BaseCellFeatures
+{
+ /**
+ * Constructor
+ */
+ public CellFeatures()
+ {
+ super();
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param cf cell to copy
+ */
+ protected CellFeatures(CellFeatures cf)
+ {
+ super(cf);
+ }
+
+ /**
+ * Accessor for the cell comment
+ *
+ * @return the cell comment, or NULL if this cell doesn't have
+ * a comment associated with it
+ */
+ public String getComment()
+ {
+ return super.getComment();
+ }
+
+ /**
+ * Gets the data validation list
+ *
+ * @return the data validation list
+ */
+ public String getDataValidationList()
+ {
+ return super.getDataValidationList();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/CellFormat.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/CellFormat.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/CellFormat.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,29 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+/**
+ * Interface for cell formats - used for typing information
+ *
+ * @deprecated Repackaged as jxl.format.CellFormat
+ */
+public interface CellFormat extends jxl.format.CellFormat
+{
+}
Index: 3rdParty_sources/jexcelapi/jxl/CellReferenceHelper.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/CellReferenceHelper.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/CellReferenceHelper.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,249 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+import jxl.write.WritableWorkbook;
+/**
+ * Exposes some cell reference helper methods to the public interface.
+ * This class merely delegates to the internally used reference helper
+ */
+public final class CellReferenceHelper
+{
+ /**
+ * Hide the default constructor
+ */
+ private CellReferenceHelper()
+ {
+ }
+
+ /**
+ * Appends the cell reference for the column and row passed in to the string
+ * buffer
+ *
+ * @param column the column
+ * @param row the row
+ * @param buf the string buffer to append
+ */
+ public static void getCellReference(int column, int row, StringBuffer buf)
+ {
+ jxl.biff.CellReferenceHelper.getCellReference(column, row, buf);
+ }
+
+ /**
+ * Overloaded method which prepends $ for absolute reference
+ *
+ * @param column the column number
+ * @param colabs TRUE if the column reference is absolute
+ * @param row the row number
+ * @param rowabs TRUE if the row reference is absolute
+ * @param buf the string buffer
+ */
+ public static void getCellReference(int column,
+ boolean colabs,
+ int row,
+ boolean rowabs,
+ StringBuffer buf)
+ {
+ jxl.biff.CellReferenceHelper.getCellReference(column, colabs,
+ row, rowabs,
+ buf);
+ }
+
+
+ /**
+ * Gets the cell reference for the specified column and row
+ *
+ * @param column the column
+ * @param row the row
+ * @return the cell reference
+ */
+ public static String getCellReference(int column, int row)
+ {
+ return jxl.biff.CellReferenceHelper.getCellReference(column, row);
+ }
+
+ /**
+ * Gets the columnn number of the string cell reference
+ *
+ * @param s the string to parse
+ * @return the column portion of the cell reference
+ */
+ public static int getColumn(String s)
+ {
+ return jxl.biff.CellReferenceHelper.getColumn(s);
+ }
+
+ /**
+ * Gets the column letter corresponding to the 0-based column number
+ *
+ * @param c the column number
+ * @return the letter for that column number
+ */
+ public static String getColumnReference(int c)
+ {
+ return jxl.biff.CellReferenceHelper.getColumnReference(c);
+ }
+
+ /**
+ * Gets the row number of the cell reference
+ * @param s the cell reference
+ * @return the row number
+ */
+ public static int getRow(String s)
+ {
+ return jxl.biff.CellReferenceHelper.getRow(s);
+ }
+
+ /**
+ * Sees if the column component is relative or not
+ *
+ * @param s the cell
+ * @return TRUE if the column is relative, FALSE otherwise
+ */
+ public static boolean isColumnRelative(String s)
+ {
+ return jxl.biff.CellReferenceHelper.isColumnRelative(s);
+ }
+
+ /**
+ * Sees if the row component is relative or not
+ *
+ * @param s the cell
+ * @return TRUE if the row is relative, FALSE otherwise
+ */
+ public static boolean isRowRelative(String s)
+ {
+ return jxl.biff.CellReferenceHelper.isRowRelative(s);
+ }
+
+ /**
+ * Gets the fully qualified cell reference given the column, row
+ * external sheet reference etc
+ *
+ * @param sheet the sheet index
+ * @param column the column index
+ * @param row the row index
+ * @param workbook the workbook
+ * @param buf a string buffer
+ */
+ public static void getCellReference
+ (int sheet, int column, int row,
+ Workbook workbook, StringBuffer buf)
+ {
+ jxl.biff.CellReferenceHelper.getCellReference
+ (sheet, column, row, (jxl.biff.formula.ExternalSheet) workbook, buf);
+ }
+
+ /**
+ * Gets the fully qualified cell reference given the column, row
+ * external sheet reference etc
+ *
+ * @param sheet the sheet
+ * @param column the column
+ * @param row the row
+ * @param workbook the workbook
+ * @param buf the buffer
+ */
+ public static void getCellReference(int sheet,
+ int column,
+ int row,
+ WritableWorkbook workbook,
+ StringBuffer buf)
+ {
+ jxl.biff.CellReferenceHelper.getCellReference
+ (sheet, column, row, (jxl.biff.formula.ExternalSheet) workbook, buf);
+ }
+
+ /**
+ * Gets the fully qualified cell reference given the column, row
+ * external sheet reference etc
+ *
+ * @param sheet the sheet
+ * @param column the column
+ * @param colabs TRUE if the column is an absolute reference
+ * @param row the row
+ * @param rowabs TRUE if the row is an absolute reference
+ * @param workbook the workbook
+ * @param buf the string buffer
+ */
+ public static void getCellReference (int sheet,
+ int column,
+ boolean colabs,
+ int row,
+ boolean rowabs,
+ Workbook workbook,
+ StringBuffer buf)
+ {
+ jxl.biff.CellReferenceHelper.getCellReference
+ (sheet, column, colabs, row, rowabs,
+ (jxl.biff.formula.ExternalSheet) workbook, buf);
+ }
+
+ /**
+ * Gets the fully qualified cell reference given the column, row
+ * external sheet reference etc
+ *
+ * @param sheet the sheet
+ * @param column the column
+ * @param row the row
+ * @param workbook the workbook
+ * @return the cell reference in the form 'Sheet 1'!A1
+ */
+ public static String getCellReference (int sheet,
+ int column,
+ int row,
+ Workbook workbook)
+ {
+ return jxl.biff.CellReferenceHelper.getCellReference
+ (sheet, column, row, (jxl.biff.formula.ExternalSheet) workbook);
+ }
+
+ /**
+ * Gets the fully qualified cell reference given the column, row
+ * external sheet reference etc
+ *
+ * @param sheet the sheet
+ * @param column the column
+ * @param row the row
+ * @param workbook the workbook
+ * @return the cell reference in the form 'Sheet 1'!A1
+ */
+ public static String getCellReference(int sheet,
+ int column,
+ int row,
+ WritableWorkbook workbook)
+ {
+ return jxl.biff.CellReferenceHelper.getCellReference
+ (sheet, column, row, (jxl.biff.formula.ExternalSheet) workbook);
+ }
+
+
+ /**
+ * Gets the sheet name from the cell reference string
+ *
+ * @param ref the cell reference
+ * @return the sheet name
+ */
+ public static String getSheet(String ref)
+ {
+ return jxl.biff.CellReferenceHelper.getSheet(ref);
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/CellType.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/CellType.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/CellType.java 17 Aug 2012 14:51:24 -0000 1.1
@@ -0,0 +1,89 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+/**
+ * An enumeration type listing the available content types for a cell
+ */
+public final class CellType
+{
+
+ /**
+ * The text description of this cell type
+ */
+ private String description;
+
+ /**
+ * Private constructor
+ * @param desc the description of this type
+ */
+ private CellType(String desc)
+ {
+ description = desc;
+ }
+
+ /**
+ * Returns a string description of this cell
+ *
+ * @return the string description for this type
+ */
+ public String toString()
+ {
+ return description;
+ }
+
+ /**
+ */
+ public static final CellType EMPTY = new CellType("Empty");
+ /**
+ */
+ public static final CellType LABEL = new CellType("Label");
+ /**
+ */
+ public static final CellType NUMBER = new CellType("Number");
+ /**
+ */
+ public static final CellType BOOLEAN = new CellType("Boolean");
+ /**
+ */
+ public static final CellType ERROR = new CellType("Error");
+ /**
+ */
+ public static final CellType NUMBER_FORMULA =
+ new CellType("Numerical Formula");
+ /**
+ */
+ public static final CellType DATE_FORMULA = new CellType("Date Formula");
+ /**
+ */
+ public static final CellType STRING_FORMULA = new CellType("String Formula");
+ /**
+ */
+ public static final CellType BOOLEAN_FORMULA =
+ new CellType("Boolean Formula");
+ /**
+ */
+ public static final CellType FORMULA_ERROR = new CellType("Formula Error");
+ /**
+ */
+ public static final CellType DATE = new CellType("Date");
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/CellView.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/CellView.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/CellView.java 17 Aug 2012 14:51:24 -0000 1.1
@@ -0,0 +1,210 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+import jxl.format.CellFormat;
+
+/**
+ * This is a bean which client applications may use to get/set various
+ * properties for a row or column on a spreadsheet
+ */
+public final class CellView
+{
+ /**
+ * The dimension for the associated group of cells. For columns this
+ * will be width in characters, for rows this will be the
+ * height in points
+ * This attribute is deprecated in favour of the size attribute
+ */
+ private int dimension;
+
+ /**
+ * The size for the associated group of cells. For columns this
+ * will be width in characters multiplied by 256, for rows this will be the
+ * height in points
+ */
+ private int size;
+
+ /**
+ * Indicates whether the deprecated function was used to set the dimension
+ */
+ private boolean depUsed;
+
+ /**
+ * Indicates whether or not this sheet is hidden
+ */
+ private boolean hidden;
+
+ /**
+ * The cell format for the row/column
+ */
+ private CellFormat format;
+
+ /**
+ * Indicates that this column/row should be autosized
+ */
+ private boolean autosize;
+
+ /**
+ * Default constructor
+ */
+ public CellView()
+ {
+ hidden = false;
+ depUsed = false;
+ dimension = 1;
+ size = 1;
+ autosize = false;
+ }
+
+ /**
+ * Copy constructor
+ */
+ public CellView(CellView cv)
+ {
+ hidden = cv.hidden;
+ depUsed = cv.depUsed;
+ dimension = cv.dimension;
+ size = cv.size;
+ autosize = cv.autosize;
+ }
+
+ /**
+ * Sets the hidden status of this row/column
+ *
+ * @param h the hidden flag
+ */
+ public void setHidden(boolean h)
+ {
+ hidden = h;
+ }
+
+ /**
+ * Accessor for the hidden nature of this row/column
+ *
+ * @return TRUE if this row/column is hidden, FALSE otherwise
+ */
+ public boolean isHidden()
+ {
+ return hidden;
+ }
+
+ /**
+ * Sets the dimension for this view
+ *
+ * @param d the width of the column in characters, or the height of the
+ * row in 1/20ths of a point
+ * @deprecated use the setSize method instead
+ */
+ public void setDimension(int d)
+ {
+ dimension = d;
+ depUsed = true;
+ }
+
+ /**
+ * Sets the dimension for this view
+ *
+ * @param d the width of the column in characters multiplied by 256,
+ * or the height of the row in 1/20ths of a point
+ */
+ public void setSize(int d)
+ {
+ size = d;
+ depUsed = false;
+ }
+
+ /**
+ * Gets the width of the column in characters or the height of the
+ * row in 1/20ths
+ *
+ * @return the dimension
+ * @deprecated use getSize() instead
+ */
+ public int getDimension()
+ {
+ return dimension;
+ }
+
+ /**
+ * Gets the width of the column in characters multiplied by 256, or the
+ * height of the row in 1/20ths of a point
+ *
+ * @return the dimension
+ */
+ public int getSize()
+ {
+ return size;
+ }
+
+ /**
+ * Sets the cell format for this group of cells
+ *
+ * @param cf the format for every cell in the column/row
+ */
+ public void setFormat(CellFormat cf)
+ {
+ format = cf;
+ }
+
+ /**
+ * Accessor for the cell format for this group.
+ *
+ * @return the format for the column/row, or NULL if no format was
+ * specified
+ */
+ public CellFormat getFormat()
+ {
+ return format;
+ }
+
+ /**
+ * Accessor for the depUsed attribute
+ *
+ * @return TRUE if the deprecated methods were used to set the size,
+ * FALSE otherwise
+ */
+ public boolean depUsed()
+ {
+ return depUsed;
+ }
+
+ /**
+ * Sets the autosize flag. Currently, this only works for column views
+ *
+ * @param a autosize
+ */
+ public void setAutosize(boolean a)
+ {
+ autosize = a;
+ }
+
+ /**
+ * Accessor for the autosize flag
+ * NOTE: use of the autosize function is very processor intensive, so
+ * use with care
+ *
+ * @return TRUE if this row/column is to be autosized
+ */
+ public boolean isAutosize()
+ {
+ return autosize;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/DateCell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/DateCell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/DateCell.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,54 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+import java.text.DateFormat;
+import java.util.Date;
+
+/**
+ * A date cell
+ */
+public interface DateCell extends Cell
+{
+ /**
+ * Gets the date contained in this cell
+ *
+ * @return the cell contents
+ */
+ public Date getDate();
+
+ /**
+ * Indicates whether the date value contained in this cell refers to a date,
+ * or merely a time
+ *
+ * @return TRUE if the value refers to a time
+ */
+ public boolean isTime();
+
+ /**
+ * Gets the DateFormat used to format the cell. This will normally be
+ * the format specified in the excel spreadsheet, but in the event of any
+ * difficulty parsing this, it will revert to the default date/time format.
+ *
+ * @return the DateFormat object used to format the date in the original
+ * excel cell
+ */
+ public DateFormat getDateFormat();
+}
Index: 3rdParty_sources/jexcelapi/jxl/DateFormulaCell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/DateFormulaCell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/DateFormulaCell.java 17 Aug 2012 14:51:24 -0000 1.1
@@ -0,0 +1,28 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+/**
+ * A mixin interface for date formulas, which combines the interfaces
+ * for formulas and for dates
+ */
+public interface DateFormulaCell extends DateCell, FormulaCell
+{
+}
Index: 3rdParty_sources/jexcelapi/jxl/ErrorCell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/ErrorCell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/ErrorCell.java 17 Aug 2012 14:51:24 -0000 1.1
@@ -0,0 +1,37 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+/**
+ * This type represents a cell which contains an error. This error will
+ * usually, but not always be the result of some error resulting from
+ * a formula
+ */
+public interface ErrorCell extends Cell
+{
+ /**
+ * Gets the error code for this cell. If this cell does not represent
+ * an error, then it returns 0. Always use the method isError() to
+ * determine this prior to calling this method
+ *
+ * @return the error code if this cell contains an error, 0 otherwise
+ */
+ public int getErrorCode();
+}
Index: 3rdParty_sources/jexcelapi/jxl/ErrorFormulaCell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/ErrorFormulaCell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/ErrorFormulaCell.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,28 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+/**
+ * A mixin interface for numerical formulas, which combines the interfaces
+ * for formulas and for numbers
+ */
+public interface ErrorFormulaCell extends ErrorCell, FormulaCell
+{
+}
Index: 3rdParty_sources/jexcelapi/jxl/FormulaCell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/FormulaCell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/FormulaCell.java 17 Aug 2012 14:51:24 -0000 1.1
@@ -0,0 +1,36 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+import jxl.biff.formula.FormulaException;
+
+/**
+ * Interface for formulas which allow clients to read the Excel formula
+ */
+public interface FormulaCell extends Cell
+{
+ /**
+ * Gets the formula as a string
+ *
+ * @return the formula as a string
+ * @exception FormulaException if an error occurred whilst parsing
+ */
+ public String getFormula() throws FormulaException;
+}
Index: 3rdParty_sources/jexcelapi/jxl/HeaderFooter.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/HeaderFooter.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/HeaderFooter.java 17 Aug 2012 14:51:24 -0000 1.1
@@ -0,0 +1,380 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan, Eric Jung
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+/**
+ * Class which represents an Excel header or footer.
+ */
+public final class HeaderFooter extends jxl.biff.HeaderFooter
+{
+ /**
+ * The contents - a simple wrapper around a string buffer
+ */
+ public static class Contents extends jxl.biff.HeaderFooter.Contents
+ {
+ /**
+ * The constructor
+ */
+ Contents()
+ {
+ super();
+ }
+
+ /**
+ * Constructor used when reading worksheets. The string contains all
+ * the formatting (but not alignment characters
+ *
+ * @param s the format string
+ */
+ Contents(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param copy the contents to copy
+ */
+ Contents(Contents copy)
+ {
+ super(copy);
+ }
+
+ /**
+ * Appends the text to the string buffer
+ *
+ * @param txt the text to append
+ */
+ public void append(String txt)
+ {
+ super.append(txt);
+ }
+
+ /**
+ * Turns bold printing on or off. Bold printing
+ * is initially off. Text subsequently appended to
+ * this object will be bolded until this method is
+ * called again.
+ */
+ public void toggleBold()
+ {
+ super.toggleBold();
+ }
+
+ /**
+ * Turns underline printing on or off. Underline printing
+ * is initially off. Text subsequently appended to
+ * this object will be underlined until this method is
+ * called again.
+ */
+ public void toggleUnderline()
+ {
+ super.toggleUnderline();
+ }
+
+ /**
+ * Turns italics printing on or off. Italics printing
+ * is initially off. Text subsequently appended to
+ * this object will be italicized until this method is
+ * called again.
+ */
+ public void toggleItalics()
+ {
+ super.toggleItalics();
+ }
+
+ /**
+ * Turns strikethrough printing on or off. Strikethrough printing
+ * is initially off. Text subsequently appended to
+ * this object will be striked out until this method is
+ * called again.
+ */
+ public void toggleStrikethrough()
+ {
+ super.toggleStrikethrough();
+ }
+
+ /**
+ * Turns double-underline printing on or off. Double-underline printing
+ * is initially off. Text subsequently appended to
+ * this object will be double-underlined until this method is
+ * called again.
+ */
+ public void toggleDoubleUnderline()
+ {
+ super.toggleDoubleUnderline();
+ }
+
+ /**
+ * Turns superscript printing on or off. Superscript printing
+ * is initially off. Text subsequently appended to
+ * this object will be superscripted until this method is
+ * called again.
+ */
+ public void toggleSuperScript()
+ {
+ super.toggleSuperScript();
+ }
+
+ /**
+ * Turns subscript printing on or off. Subscript printing
+ * is initially off. Text subsequently appended to
+ * this object will be subscripted until this method is
+ * called again.
+ */
+ public void toggleSubScript()
+ {
+ super.toggleSubScript();
+ }
+
+ /**
+ * Turns outline printing on or off (Macintosh only).
+ * Outline printing is initially off. Text subsequently appended
+ * to this object will be outlined until this method is
+ * called again.
+ */
+ public void toggleOutline()
+ {
+ super.toggleOutline();
+ }
+
+ /**
+ * Turns shadow printing on or off (Macintosh only).
+ * Shadow printing is initially off. Text subsequently appended
+ * to this object will be shadowed until this method is
+ * called again.
+ */
+ public void toggleShadow()
+ {
+ super.toggleShadow();
+ }
+
+ /**
+ * Sets the font of text subsequently appended to this
+ * object.. Previously appended text is not affected.
+ *
+ * Note: no checking is performed to
+ * determine if fontName is a valid font.
+ *
+ * @param fontName name of the font to use
+ */
+ public void setFontName(String fontName)
+ {
+ super.setFontName(fontName);
+ }
+
+ /**
+ * Sets the font size of text subsequently appended to this
+ * object. Previously appended text is not affected.
+ *
+ * Valid point sizes are between 1 and 99 (inclusive). If
+ * size is outside this range, this method returns false
+ * and does not change font size. If size is within this
+ * range, the font size is changed and true is returned.
+ *
+ * @param size The size in points. Valid point sizes are
+ * between 1 and 99 (inclusive).
+ * @return true if the font size was changed, false if font
+ * size was not changed because 1 > size > 99.
+ */
+ public boolean setFontSize(int size)
+ {
+ return super.setFontSize(size);
+ }
+
+ /**
+ * Appends the page number
+ */
+ public void appendPageNumber()
+ {
+ super.appendPageNumber();
+ }
+
+ /**
+ * Appends the total number of pages
+ */
+ public void appendTotalPages()
+ {
+ super.appendTotalPages();
+ }
+
+ /**
+ * Appends the current date
+ */
+ public void appendDate()
+ {
+ super.appendDate();
+ }
+
+ /**
+ * Appends the current time
+ */
+ public void appendTime()
+ {
+ super.appendTime();
+ }
+
+ /**
+ * Appends the workbook name
+ */
+ public void appendWorkbookName()
+ {
+ super.appendWorkbookName();
+ }
+
+ /**
+ * Appends the worksheet name
+ */
+ public void appendWorkSheetName()
+ {
+ super.appendWorkSheetName();
+ }
+
+ /**
+ * Clears the contents of this portion
+ */
+ public void clear()
+ {
+ super.clear();
+ }
+
+ /**
+ * Queries if the contents are empty
+ *
+ * @return TRUE if the contents are empty, FALSE otherwise
+ */
+ public boolean empty()
+ {
+ return super.empty();
+ }
+ }
+
+ /**
+ * Default constructor.
+ */
+ public HeaderFooter()
+ {
+ super();
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param hf the item to copy
+ */
+ public HeaderFooter(HeaderFooter hf)
+ {
+ super(hf);
+ }
+
+ /**
+ * Constructor used when reading workbooks to separate the left, right
+ * a central part of the strings into their constituent parts
+ *
+ * @param s the header string
+ */
+ public HeaderFooter(String s)
+ {
+ super(s);
+ }
+
+ /**
+ * Retrieves a String
ified
+ * version of this object
+ *
+ * @return the header string
+ */
+ public String toString()
+ {
+ return super.toString();
+ }
+
+ /**
+ * Accessor for the contents which appear on the right hand side of the page
+ *
+ * @return the right aligned contents
+ */
+ public Contents getRight()
+ {
+ return (Contents) super.getRightText();
+ }
+
+ /**
+ * Accessor for the contents which in the centre of the page
+ *
+ * @return the centrally aligned contents
+ */
+ public Contents getCentre()
+ {
+ return (Contents) super.getCentreText();
+ }
+
+ /**
+ * Accessor for the contents which appear on the left hand side of the page
+ *
+ * @return the left aligned contents
+ */
+ public Contents getLeft()
+ {
+ return (Contents) super.getLeftText();
+ }
+
+ /**
+ * Clears the contents of the header/footer
+ */
+ public void clear()
+ {
+ super.clear();
+ }
+
+ /**
+ * Creates internal class of the appropriate type
+ *
+ * @return the created contents
+ */
+ protected jxl.biff.HeaderFooter.Contents createContents()
+ {
+ return new Contents();
+ }
+
+ /**
+ * Creates internal class of the appropriate type
+ *
+ * @param s the string to create the contents
+ * @return the created contents
+ */
+ protected jxl.biff.HeaderFooter.Contents createContents(String s)
+ {
+ return new Contents(s);
+ }
+
+ /**
+ * Creates internal class of the appropriate type
+ *
+ * @param c the contents to copy
+ * @return the new contents
+ */
+ protected jxl.biff.HeaderFooter.Contents
+ createContents(jxl.biff.HeaderFooter.Contents c)
+ {
+ return new Contents((Contents) c);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/Hyperlink.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/Hyperlink.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/Hyperlink.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,107 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+import java.io.File;
+import java.net.URL;
+
+/**
+ * Hyperlink information. Only URLs or file links are supported
+ *
+ * Hyperlinks may apply to a range of cells; in such cases the methods
+ * getRow and getColumn return the cell at the top left of the range
+ * the hyperlink refers to. Hyperlinks have no specific cell format
+ * information applied to them, so the getCellFormat method will return null
+ */
+public interface Hyperlink
+{
+ /**
+ * Returns the row number of this cell
+ *
+ * @return the row number of this cell
+ */
+ public int getRow();
+
+ /**
+ * Returns the column number of this cell
+ *
+ * @return the column number of this cell
+ */
+ public int getColumn();
+
+ /**
+ * Gets the range of cells which activate this hyperlink
+ * The get sheet index methods will all return -1, because the
+ * cells will all be present on the same sheet
+ *
+ * @return the range of cells which activate the hyperlink
+ */
+ public Range getRange();
+
+ /**
+ * Determines whether this is a hyperlink to a file
+ *
+ * @return TRUE if this is a hyperlink to a file, FALSE otherwise
+ */
+ public boolean isFile();
+
+ /**
+ * Determines whether this is a hyperlink to a web resource
+ *
+ * @return TRUE if this is a URL
+ */
+ public boolean isURL();
+
+ /**
+ * Determines whether this is a hyperlink to a location in this workbook
+ *
+ * @return TRUE if this is a link to an internal location
+ */
+ public boolean isLocation();
+
+ /**
+ * Returns the row number of the bottom right cell
+ *
+ * @return the row number of this cell
+ */
+ public int getLastRow();
+
+ /**
+ * Returns the column number of the bottom right cell
+ *
+ * @return the column number of this cell
+ */
+ public int getLastColumn();
+
+ /**
+ * Gets the URL referenced by this Hyperlink
+ *
+ * @return the URL, or NULL if this hyperlink is not a URL
+ */
+ public URL getURL();
+
+ /**
+ * Returns the local file eferenced by this Hyperlink
+ *
+ * @return the file, or NULL if this hyperlink is not a file
+ */
+ public File getFile();
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/Image.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/Image.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/Image.java 17 Aug 2012 14:51:24 -0000 1.1
@@ -0,0 +1,122 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+import common.LengthUnit;
+
+import java.io.File;
+
+/**
+ * Accessor functions for an image
+ */
+public interface Image
+{
+ /**
+ * Accessor for the image position
+ *
+ * @return the column number at which the image is positioned
+ */
+ public double getColumn();
+
+ /**
+ * Accessor for the image position
+ *
+ * @return the row number at which the image is positioned
+ */
+ public double getRow();
+
+ /**
+ * Accessor for the image dimensions
+ *
+ * @return the number of columns this image spans
+ */
+ public double getWidth();
+
+ /**
+ * Accessor for the image dimensions
+ *
+ * @return the number of rows which this image spans
+ */
+ public double getHeight();
+
+ /**
+ * Accessor for the image file
+ *
+ * @return the file which the image references
+ */
+ public File getImageFile();
+
+ /**
+ * Accessor for the image data
+ *
+ * @return the image data
+ */
+ public byte[] getImageData();
+
+ /**
+ * Get the width of this image as rendered within Excel
+ *
+ * @param unit the unit of measurement
+ * @return the width of the image within Excel
+ */
+ public double getWidth(LengthUnit unit);
+
+ /**
+ * Get the height of this image as rendered within Excel
+ *
+ * @param unit the unit of measurement
+ * @return the height of the image within Excel
+ */
+ public double getHeight(LengthUnit unit);
+
+ /**
+ * Gets the width of the image. Note that this is the width of the
+ * underlying image, and does not take into account any size manipulations
+ * that may have occurred when the image was added into Excel
+ *
+ * @return the image width in pixels
+ */
+ public int getImageWidth();
+
+ /**
+ * Gets the height of the image. Note that this is the height of the
+ * underlying image, and does not take into account any size manipulations
+ * that may have occurred when the image was added into Excel
+ *
+ * @return the image height in pixels
+ */
+ public int getImageHeight();
+
+ /**
+ * Gets the horizontal resolution of the image, if that information
+ * is available.
+ *
+ * @return the number of dots per unit specified, if available, 0 otherwise
+ */
+ public double getHorizontalResolution(LengthUnit unit);
+
+ /**
+ * Gets the vertical resolution of the image, if that information
+ * is available.
+ *
+ * @return the number of dots per unit specified, if available, 0 otherwise
+ */
+ public double getVerticalResolution(LengthUnit unit);
+}
Index: 3rdParty_sources/jexcelapi/jxl/JXLException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/JXLException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/JXLException.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,36 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+/**
+ * Base exception class for JExcelAPI exceptions
+ */
+public class JXLException extends Exception
+{
+ /**
+ * Constructor
+ *
+ * @param message the exception message
+ */
+ protected JXLException(String message)
+ {
+ super(message);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/LabelCell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/LabelCell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/LabelCell.java 17 Aug 2012 14:51:24 -0000 1.1
@@ -0,0 +1,34 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+/**
+ * A label cell
+ */
+public interface LabelCell extends Cell
+{
+ /**
+ * Gets the label for this cell. The value returned will be the same
+ * as for the getContents method in the base class
+ *
+ * @return the cell contents
+ */
+ public String getString();
+}
Index: 3rdParty_sources/jexcelapi/jxl/NumberCell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/NumberCell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/NumberCell.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,44 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+import java.text.NumberFormat;
+
+/**
+ * A cell which contains a numerical value
+ */
+public interface NumberCell extends Cell
+{
+ /**
+ * Gets the double contents for this cell.
+ *
+ * @return the cell contents
+ */
+ public double getValue();
+
+ /**
+ * Gets the NumberFormat used to format this cell. This is the java
+ * equivalent of the Excel format
+ *
+ * @return the NumberFormat used to format the cell
+ */
+ public NumberFormat getNumberFormat();
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/NumberFormulaCell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/NumberFormulaCell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/NumberFormulaCell.java 17 Aug 2012 14:51:24 -0000 1.1
@@ -0,0 +1,28 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+/**
+ * A mixin interface for numerical formulas, which combines the interfaces
+ * for formulas and for numbers
+ */
+public interface NumberFormulaCell extends NumberCell, FormulaCell
+{
+}
Index: 3rdParty_sources/jexcelapi/jxl/Range.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/Range.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/Range.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,58 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+/**
+ * Represents a 3-D range of cells in a workbook. This object is
+ * returned by the method findByName in a workbook
+ */
+public interface Range
+{
+ /**
+ * Gets the cell at the top left of this range
+ *
+ * @return the cell at the top left
+ */
+ public Cell getTopLeft();
+
+ /**
+ * Gets the cell at the bottom right of this range
+ *
+ * @return the cell at the bottom right
+ */
+ public Cell getBottomRight();
+
+ /**
+ * Gets the index of the first sheet in the range
+ *
+ * @return the index of the first sheet in the range
+ */
+ public int getFirstSheetIndex();
+
+ /**
+ * Gets the index of the last sheet in the range
+ *
+ * @return the index of the last sheet in the range
+ */
+ public int getLastSheetIndex();
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/Sheet.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/Sheet.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/Sheet.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,279 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+import java.util.regex.Pattern;
+import jxl.format.CellFormat;
+
+/**
+ * Represents a sheet within a workbook. Provides a handle to the individual
+ * cells, or lines of cells (grouped by Row or Column)
+ */
+public interface Sheet
+{
+ /**
+ * Returns the cell specified at this row and at this column.
+ * If a column/row combination forms part of a merged group of cells
+ * then (unless it is the first cell of the group) a blank cell
+ * will be returned
+ *
+ * @param column the column number
+ * @param row the row number
+ * @return the cell at the specified co-ordinates
+ */
+ public Cell getCell(int column, int row);
+
+ /**
+ * Returns the cell for the specified location eg. "A4". Note that this
+ * method is identical to calling getCell(CellReferenceHelper.getColumn(loc),
+ * CellReferenceHelper.getRow(loc)) and its implicit performance
+ * overhead for string parsing. As such,this method should therefore
+ * be used sparingly
+ *
+ * @param loc the cell reference
+ * @return the cell at the specified co-ordinates
+ */
+ public Cell getCell(String loc);
+
+ /**
+ * Returns the number of rows in this sheet
+ *
+ * @return the number of rows in this sheet
+ */
+ public int getRows();
+
+ /**
+ * Returns the number of columns in this sheet
+ *
+ * @return the number of columns in this sheet
+ */
+ public int getColumns();
+
+ /**
+ * Gets all the cells on the specified row
+ *
+ * @param row the rows whose cells are to be returned
+ * @return the cells on the given row
+ */
+ public Cell[] getRow(int row);
+
+ /**
+ * Gets all the cells on the specified column
+ *
+ * @param col the column whose cells are to be returned
+ * @return the cells on the specified column
+ */
+ public Cell[] getColumn(int col);
+
+ /**
+ * Gets the name of this sheet
+ *
+ * @return the name of the sheet
+ */
+ public String getName();
+
+ /**
+ * Determines whether the sheet is hidden
+ *
+ * @return whether or not the sheet is hidden
+ * @deprecated in favour of the getSettings() method
+ */
+ public boolean isHidden();
+
+ /**
+ * Determines whether the sheet is protected
+ *
+ * @return whether or not the sheet is protected
+ * @deprecated in favour of the getSettings() method
+ */
+ public boolean isProtected();
+
+ /**
+ * Gets the cell whose contents match the string passed in.
+ * If no match is found, then null is returned. The search is performed
+ * on a row by row basis, so the lower the row number, the more
+ * efficiently the algorithm will perform
+ *
+ * @param contents the string to match
+ * @return the Cell whose contents match the paramter, null if not found
+ */
+ public Cell findCell(String contents);
+
+ /**
+ * Gets the cell whose contents match the string passed in.
+ * If no match is found, then null is returned. The search is performed
+ * on a row by row basis, so the lower the row number, the more
+ * efficiently the algorithm will perform
+ *
+ * @param contents the string to match
+ * @param firstCol the first column within the range
+ * @param firstRow the first row of the range
+ * @param lastCol the last column within the range
+ * @param lastRow the last row within the range
+ * @param reverse indicates whether to perform a reverse search or not
+ * @return the Cell whose contents match the parameter, null if not found
+ */
+ public Cell findCell(String contents,
+ int firstCol,
+ int firstRow,
+ int lastCol,
+ int lastRow,
+ boolean reverse);
+
+ /**
+ * Gets the cell whose contents match the regular expressionstring passed in.
+ * If no match is found, then null is returned. The search is performed
+ * on a row by row basis, so the lower the row number, the more
+ * efficiently the algorithm will perform
+ *
+ * @param pattern the regular expression string to match
+ * @param firstCol the first column within the range
+ * @param firstRow the first row of the rang
+ * @param lastCol the last column within the range
+ * @param lastRow the last row within the range
+ * @param reverse indicates whether to perform a reverse search or not
+ * @return the Cell whose contents match the parameter, null if not found
+ */
+ public Cell findCell(Pattern pattern,
+ int firstCol,
+ int firstRow,
+ int lastCol,
+ int lastRow,
+ boolean reverse);
+
+ /**
+ * Gets the cell whose contents match the string passed in.
+ * If no match is found, then null is returned. The search is performed
+ * on a row by row basis, so the lower the row number, the more
+ * efficiently the algorithm will perform. This method differs
+ * from the findCell method in that only cells with labels are
+ * queried - all numerical cells are ignored. This should therefore
+ * improve performance.
+ *
+ * @param contents the string to match
+ * @return the Cell whose contents match the paramter, null if not found
+ */
+ public LabelCell findLabelCell(String contents);
+
+ /**
+ * Gets the hyperlinks on this sheet
+ *
+ * @return an array of hyperlinks
+ */
+ public Hyperlink[] getHyperlinks();
+
+ /**
+ * Gets the cells which have been merged on this sheet
+ *
+ * @return an array of range objects
+ */
+ public Range[] getMergedCells();
+
+ /**
+ * Gets the settings used on a particular sheet
+ *
+ * @return the sheet settings
+ */
+ public SheetSettings getSettings();
+
+ /**
+ * Gets the column format for the specified column
+ *
+ * @param col the column number
+ * @return the column format, or NULL if the column has no specific format
+ * @deprecated Use getColumnView and the CellView bean instead
+ */
+ public CellFormat getColumnFormat(int col);
+
+ /**
+ * Gets the column width for the specified column
+ *
+ * @param col the column number
+ * @return the column width, or the default width if the column has no
+ * specified format
+ * @deprecated Use getColumnView instead
+ */
+ public int getColumnWidth(int col);
+
+ /**
+ * Gets the column width for the specified column
+ *
+ * @param col the column number
+ * @return the column format, or the default format if no override is
+ specified
+ */
+ public CellView getColumnView(int col);
+
+ /**
+ * Gets the row height for the specified column
+ *
+ * @param row the row number
+ * @return the row height, or the default height if the column has no
+ * specified format
+ * @deprecated use getRowView instead
+ */
+ public int getRowHeight(int row);
+
+ /**
+ * Gets the row height for the specified column
+ *
+ * @param row the row number
+ * @return the row format, which may be the default format if no format
+ * is specified
+ */
+ public CellView getRowView(int row);
+
+ /**
+ * Accessor for the number of images on the sheet
+ *
+ * @return the number of images on this sheet
+ */
+ public int getNumberOfImages();
+
+ /**
+ * Accessor for the image
+ *
+ * @param i the 0 based image number
+ * @return the image at the specified position
+ */
+ public Image getDrawing(int i);
+
+ /**
+ * Accessor for the page breaks on this sheet
+ *
+ * @return the page breaks on this sheet
+ */
+ public int[] getRowPageBreaks();
+
+ /**
+ * Accessor for the page breaks on this sheet
+ *
+ * @return the page breaks on this sheet
+ */
+ public int[] getColumnPageBreaks();
+
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/SheetSettings.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/SheetSettings.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/SheetSettings.java 17 Aug 2012 14:51:24 -0000 1.1
@@ -0,0 +1,1344 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+import common.Assert;
+
+import jxl.format.PageOrientation;
+import jxl.format.PaperSize;
+import jxl.biff.SheetRangeImpl;
+import jxl.Range;
+import jxl.format.PageOrder;
+
+/**
+ * This is a bean which client applications may use to get/set various
+ * properties which are associated with a particular worksheet, such
+ * as headers and footers, page orientation etc.
+ */
+public final class SheetSettings
+{
+ /**
+ * The page orientation
+ */
+ private PageOrientation orientation;
+
+ /**
+ * The page order
+ */
+ private PageOrder pageOrder;
+
+ /**
+ * The paper size for printing
+ */
+ private PaperSize paperSize;
+
+ /**
+ * Indicates whether or not this sheet is protected
+ */
+ private boolean sheetProtected;
+
+ /**
+ * Indicates whether or not this sheet is hidden
+ */
+ private boolean hidden;
+
+ /**
+ * Indicates whether or not this sheet is selected
+ */
+ private boolean selected;
+
+ /**
+ * The header
+ */
+ private HeaderFooter header;
+
+ /**
+ * The margin allocated for any page headers, in inches
+ */
+ private double headerMargin;
+
+ /**
+ * The footer
+ */
+ private HeaderFooter footer;
+
+ /**
+ * The margin allocated for any page footers, in inches
+ */
+ private double footerMargin;
+
+ /**
+ * The scale factor used when printing
+ */
+ private int scaleFactor;
+
+ /**
+ * The zoom factor used when viewing. Note the difference between
+ * this and the scaleFactor which is used when printing
+ */
+ private int zoomFactor;
+
+ /**
+ * The page number at which to commence printing
+ */
+ private int pageStart;
+
+ /**
+ * The number of pages into which this excel sheet is squeezed widthwise
+ */
+ private int fitWidth;
+
+ /**
+ * The number of pages into which this excel sheet is squeezed heightwise
+ */
+ private int fitHeight;
+
+ /**
+ * The horizontal print resolution
+ */
+ private int horizontalPrintResolution;
+
+ /**
+ * The vertical print resolution
+ */
+ private int verticalPrintResolution;
+
+ /**
+ * The margin from the left hand side of the paper in inches
+ */
+ private double leftMargin;
+
+ /**
+ * The margin from the right hand side of the paper in inches
+ */
+ private double rightMargin;
+
+ /**
+ * The margin from the top of the paper in inches
+ */
+ private double topMargin;
+
+ /**
+ * The margin from the bottom of the paper in inches
+ */
+ private double bottomMargin;
+
+ /**
+ * Indicates whether to fit the print to the pages or scale the output
+ * This field is manipulated indirectly by virtue of the setFitWidth/Height
+ * methods
+ */
+ private boolean fitToPages;
+
+ /**
+ * Indicates whether grid lines should be displayed
+ */
+ private boolean showGridLines;
+
+ /**
+ * Indicates whether grid lines should be printed
+ */
+ private boolean printGridLines;
+
+ /**
+ * Indicates whether sheet headings should be printed
+ */
+ private boolean printHeaders;
+
+ /**
+ * Indicates the view mode
+ */
+ private boolean pageBreakPreviewMode;
+
+ /**
+ * Indicates whether the sheet should display zero values
+ */
+ private boolean displayZeroValues;
+
+ /**
+ * The password for protected sheets
+ */
+ private String password;
+
+ /**
+ * The password hashcode - used when copying sheets
+ */
+ private int passwordHash;
+
+ /**
+ * The default column width, in characters
+ */
+ private int defaultColumnWidth;
+
+ /**
+ * The default row height, in 1/20th of a point
+ */
+ private int defaultRowHeight;
+
+ /**
+ * The horizontal freeze pane
+ */
+ private int horizontalFreeze;
+
+ /**
+ * The vertical freeze position
+ */
+ private int verticalFreeze;
+
+ /**
+ * Vertical centre flag
+ */
+ private boolean verticalCentre;
+
+ /**
+ * Horizontal centre flag
+ */
+ private boolean horizontalCentre;
+
+ /**
+ * The number of copies to print
+ */
+ private int copies;
+
+ /**
+ * Automatic formula calculation
+ */
+ private boolean automaticFormulaCalculation;
+
+ /**
+ * Recalculate the formulas before save
+ */
+ private boolean recalculateFormulasBeforeSave;
+
+ /**
+ * The magnification factor for use during page break preview mode (in
+ * percent)
+ */
+ private int pageBreakPreviewMagnification;
+
+ /**
+ * The magnification factor for use during normal mode (in percent)
+ */
+ private int normalMagnification;
+
+ /**
+ * The print area
+ */
+ private Range printArea;
+
+ /**
+ * The print row titles
+ */
+ private Range printTitlesRow;
+
+ /**
+ * The print column titles
+ */
+ private Range printTitlesCol;
+
+ /**
+ * A handle to the sheet - used internally for ranges
+ */
+ private Sheet sheet;
+
+ // ***
+ // The defaults
+ // **
+ private static final PageOrientation DEFAULT_ORIENTATION =
+ PageOrientation.PORTRAIT;
+ private static final PageOrder DEFAULT_ORDER =
+ PageOrder.RIGHT_THEN_DOWN;
+ private static final PaperSize DEFAULT_PAPER_SIZE = PaperSize.A4;
+ private static final double DEFAULT_HEADER_MARGIN = 0.5;
+ private static final double DEFAULT_FOOTER_MARGIN = 0.5;
+ private static final int DEFAULT_PRINT_RESOLUTION = 0x12c;
+ private static final double DEFAULT_WIDTH_MARGIN = 0.75;
+ private static final double DEFAULT_HEIGHT_MARGIN = 1;
+
+ private static final int DEFAULT_DEFAULT_COLUMN_WIDTH = 8;
+ private static final int DEFAULT_ZOOM_FACTOR = 100;
+ private static final int DEFAULT_NORMAL_MAGNIFICATION = 100;
+ private static final int DEFAULT_PAGE_BREAK_PREVIEW_MAGNIFICATION = 60;
+
+ // The publicly accessible values
+ /**
+ * The default value for the default row height
+ */
+ public static final int DEFAULT_DEFAULT_ROW_HEIGHT = 0xff;
+
+ /**
+ * Default constructor
+ */
+ public SheetSettings(Sheet s)
+ {
+ sheet = s; // for internal use, when accessing ranges
+ orientation = DEFAULT_ORIENTATION;
+ pageOrder = DEFAULT_ORDER;
+ paperSize = DEFAULT_PAPER_SIZE;
+ sheetProtected = false;
+ hidden = false;
+ selected = false;
+ headerMargin = DEFAULT_HEADER_MARGIN;
+ footerMargin = DEFAULT_FOOTER_MARGIN;
+ horizontalPrintResolution = DEFAULT_PRINT_RESOLUTION;
+ verticalPrintResolution = DEFAULT_PRINT_RESOLUTION;
+ leftMargin = DEFAULT_WIDTH_MARGIN;
+ rightMargin = DEFAULT_WIDTH_MARGIN;
+ topMargin = DEFAULT_HEIGHT_MARGIN;
+ bottomMargin = DEFAULT_HEIGHT_MARGIN;
+ fitToPages = false;
+ showGridLines = true;
+ printGridLines = false;
+ printHeaders = false;
+ pageBreakPreviewMode = false;
+ displayZeroValues = true;
+ defaultColumnWidth = DEFAULT_DEFAULT_COLUMN_WIDTH;
+ defaultRowHeight = DEFAULT_DEFAULT_ROW_HEIGHT;
+ zoomFactor = DEFAULT_ZOOM_FACTOR;
+ pageBreakPreviewMagnification = DEFAULT_PAGE_BREAK_PREVIEW_MAGNIFICATION;
+ normalMagnification = DEFAULT_NORMAL_MAGNIFICATION;
+ horizontalFreeze = 0;
+ verticalFreeze = 0;
+ copies = 1;
+ header = new HeaderFooter();
+ footer = new HeaderFooter();
+ automaticFormulaCalculation = true;
+ recalculateFormulasBeforeSave = true;
+ }
+
+ /**
+ * Copy constructor. Called when copying sheets
+ * @param copy the settings to copy
+ */
+ public SheetSettings(SheetSettings copy, Sheet s)
+ {
+ Assert.verify(copy != null);
+
+ sheet = s; // for internal use when accessing ranges
+ orientation = copy.orientation;
+ pageOrder = copy.pageOrder;
+ paperSize = copy.paperSize;
+ sheetProtected = copy.sheetProtected;
+ hidden = copy.hidden;
+ selected = false; // don't copy the selected flag
+ headerMargin = copy.headerMargin;
+ footerMargin = copy.footerMargin;
+ scaleFactor = copy.scaleFactor;
+ pageStart = copy.pageStart;
+ fitWidth = copy.fitWidth;
+ fitHeight = copy.fitHeight;
+ horizontalPrintResolution = copy.horizontalPrintResolution;
+ verticalPrintResolution = copy.verticalPrintResolution;
+ leftMargin = copy.leftMargin;
+ rightMargin = copy.rightMargin;
+ topMargin = copy.topMargin;
+ bottomMargin = copy.bottomMargin;
+ fitToPages = copy.fitToPages;
+ password = copy.password;
+ passwordHash = copy.passwordHash;
+ defaultColumnWidth = copy.defaultColumnWidth;
+ defaultRowHeight = copy.defaultRowHeight;
+ zoomFactor = copy.zoomFactor;
+ pageBreakPreviewMagnification = copy.pageBreakPreviewMagnification;
+ normalMagnification = copy.normalMagnification;
+ showGridLines = copy.showGridLines;
+ displayZeroValues = copy.displayZeroValues;
+ pageBreakPreviewMode = copy.pageBreakPreviewMode;
+ horizontalFreeze = copy.horizontalFreeze;
+ verticalFreeze = copy.verticalFreeze;
+ horizontalCentre = copy.horizontalCentre;
+ verticalCentre = copy.verticalCentre;
+ copies = copy.copies;
+ header = new HeaderFooter(copy.header);
+ footer = new HeaderFooter(copy.footer);
+ automaticFormulaCalculation = copy.automaticFormulaCalculation;
+ recalculateFormulasBeforeSave = copy.recalculateFormulasBeforeSave;
+
+ if (copy.printArea != null)
+ {
+ printArea = new SheetRangeImpl
+ (sheet,
+ copy.getPrintArea().getTopLeft().getColumn(),
+ copy.getPrintArea().getTopLeft().getRow(),
+ copy.getPrintArea().getBottomRight().getColumn(),
+ copy.getPrintArea().getBottomRight().getRow());
+ }
+
+ if (copy.printTitlesRow != null)
+ {
+ printTitlesRow = new SheetRangeImpl
+ (sheet,
+ copy.getPrintTitlesRow().getTopLeft().getColumn(),
+ copy.getPrintTitlesRow().getTopLeft().getRow(),
+ copy.getPrintTitlesRow().getBottomRight().getColumn(),
+ copy.getPrintTitlesRow().getBottomRight().getRow());
+ }
+
+ if (copy.printTitlesCol != null)
+ {
+ printTitlesCol = new SheetRangeImpl
+ (sheet,
+ copy.getPrintTitlesCol().getTopLeft().getColumn(),
+ copy.getPrintTitlesCol().getTopLeft().getRow(),
+ copy.getPrintTitlesCol().getBottomRight().getColumn(),
+ copy.getPrintTitlesCol().getBottomRight().getRow());
+ }
+ }
+
+ /**
+ * Sets the paper orientation for printing this sheet
+ *
+ * @param po the orientation
+ */
+ public void setOrientation(PageOrientation po)
+ {
+ orientation = po;
+ }
+
+ /**
+ * Accessor for the orientation
+ *
+ * @return the orientation
+ */
+ public PageOrientation getOrientation()
+ {
+ return orientation;
+ }
+
+ /**
+ * Accessor for the order
+ *
+ * @return
+ */
+ public PageOrder getPageOrder()
+ {
+ return pageOrder;
+ }
+
+ /**
+ * Sets the page order for printing this sheet
+ *
+ * @param order
+ */
+ public void setPageOrder(PageOrder order)
+ {
+ this.pageOrder = order;
+ }
+
+ /**
+ * Sets the paper size to be used when printing this sheet
+ *
+ * @param ps the paper size
+ */
+ public void setPaperSize(PaperSize ps)
+ {
+ paperSize = ps;
+ }
+
+ /**
+ * Accessor for the paper size
+ *
+ * @return the paper size
+ */
+ public PaperSize getPaperSize()
+ {
+ return paperSize;
+ }
+
+ /**
+ * Queries whether this sheet is protected (ie. read only)
+ *
+ * @return TRUE if this sheet is read only, FALSE otherwise
+ */
+ public boolean isProtected()
+ {
+ return sheetProtected;
+ }
+
+ /**
+ * Sets the protected (ie. read only) status of this sheet
+ *
+ * @param p the protected status
+ */
+ public void setProtected(boolean p)
+ {
+ sheetProtected = p;
+ }
+
+ /**
+ * Sets the margin for any page headers
+ *
+ * @param d the margin in inches
+ */
+ public void setHeaderMargin(double d)
+ {
+ headerMargin = d;
+ }
+
+ /**
+ * Accessor for the header margin
+ *
+ * @return the header margin
+ */
+ public double getHeaderMargin()
+ {
+ return headerMargin;
+ }
+
+ /**
+ * Sets the margin for any page footer
+ *
+ * @param d the footer margin in inches
+ */
+ public void setFooterMargin(double d)
+ {
+ footerMargin = d;
+ }
+
+ /**
+ * Accessor for the footer margin
+ *
+ * @return the footer margin
+ */
+ public double getFooterMargin()
+ {
+ return footerMargin;
+ }
+
+ /**
+ * Sets the hidden status of this worksheet
+ *
+ * @param h the hidden flag
+ */
+ public void setHidden(boolean h)
+ {
+ hidden = h;
+ }
+
+ /**
+ * Accessor for the hidden nature of this sheet
+ *
+ * @return TRUE if this sheet is hidden, FALSE otherwise
+ */
+ public boolean isHidden()
+ {
+ return hidden;
+ }
+
+ /**
+ * Sets this sheet to be when it is opened in excel
+ *
+ * @deprecated use overloaded version which takes a boolean
+ */
+ public void setSelected()
+ {
+ setSelected(true);
+ }
+
+ /**
+ * Sets this sheet to be when it is opened in excel
+ *
+ * @param s sets whether this sheet is selected or not
+ */
+ public void setSelected(boolean s)
+ {
+ selected = s;
+ }
+
+ /**
+ * Accessor for the selected nature of the sheet
+ *
+ * @return TRUE if this sheet is selected, FALSE otherwise
+ */
+ public boolean isSelected()
+ {
+ return selected;
+ }
+
+ /**
+ * Sets the scale factor for this sheet to be used when printing. The
+ * parameter is a percentage, therefore setting a scale factor of 100 will
+ * print at normal size, 50 half size, 200 double size etc
+ *
+ * @param sf the scale factor as a percentage
+ */
+ public void setScaleFactor(int sf)
+ {
+ scaleFactor = sf;
+ fitToPages = false;
+ }
+
+ /**
+ * Accessor for the scale factor
+ *
+ * @return the scale factor
+ */
+ public int getScaleFactor()
+ {
+ return scaleFactor;
+ }
+
+ /**
+ * Sets the page number at which to commence printing
+ *
+ * @param ps the page start number
+ */
+ public void setPageStart(int ps)
+ {
+ pageStart = ps;
+ }
+
+ /**
+ * Accessor for the page start
+ *
+ * @return the page start
+ */
+ public int getPageStart()
+ {
+ return pageStart;
+ }
+
+ /**
+ * Sets the number of pages widthwise which this sheet should be
+ * printed into
+ *
+ * @param fw the number of pages
+ */
+ public void setFitWidth(int fw)
+ {
+ fitWidth = fw;
+ fitToPages = true;
+ }
+
+ /**
+ * Accessor for the fit width
+ *
+ * @return the number of pages this sheet will be printed into widthwise
+ */
+ public int getFitWidth()
+ {
+ return fitWidth;
+ }
+
+ /**
+ * Sets the number of pages vertically that this sheet will be printed into
+ *
+ * @param fh the number of pages this sheet will be printed into heightwise
+ */
+ public void setFitHeight(int fh)
+ {
+ fitHeight = fh;
+ fitToPages = true;
+ }
+
+ /**
+ * Accessor for the fit height
+ *
+ * @return the number of pages this sheet will be printed into heightwise
+ */
+ public int getFitHeight()
+ {
+ return fitHeight;
+ }
+
+ /**
+ * Sets the horizontal print resolution
+ *
+ * @param hpw the print resolution
+ */
+ public void setHorizontalPrintResolution(int hpw)
+ {
+ horizontalPrintResolution = hpw;
+ }
+
+ /**
+ * Accessor for the horizontal print resolution
+ *
+ * @return the horizontal print resolution
+ */
+ public int getHorizontalPrintResolution()
+ {
+ return horizontalPrintResolution;
+ }
+
+ /**
+ * Sets the vertical print reslution
+ *
+ * @param vpw the vertical print resolution
+ */
+ public void setVerticalPrintResolution(int vpw)
+ {
+ verticalPrintResolution = vpw;
+ }
+
+ /**
+ * Accessor for the vertical print resolution
+ *
+ * @return the vertical print resolution
+ */
+ public int getVerticalPrintResolution()
+ {
+ return verticalPrintResolution;
+ }
+
+ /**
+ * Sets the right margin
+ *
+ * @param m the right margin in inches
+ */
+ public void setRightMargin(double m)
+ {
+ rightMargin = m;
+ }
+
+ /**
+ * Accessor for the right margin
+ *
+ * @return the right margin in inches
+ */
+ public double getRightMargin()
+ {
+ return rightMargin;
+ }
+
+ /**
+ * Sets the left margin
+ *
+ * @param m the left margin in inches
+ */
+ public void setLeftMargin(double m)
+ {
+ leftMargin = m;
+ }
+
+ /**
+ * Accessor for the left margin
+ *
+ * @return the left margin in inches
+ */
+ public double getLeftMargin()
+ {
+ return leftMargin;
+ }
+
+ /**
+ * Sets the top margin
+ *
+ * @param m the top margin in inches
+ */
+ public void setTopMargin(double m)
+ {
+ topMargin = m;
+ }
+
+ /**
+ * Accessor for the top margin
+ *
+ * @return the top margin in inches
+ */
+ public double getTopMargin()
+ {
+ return topMargin;
+ }
+
+ /**
+ * Sets the bottom margin
+ *
+ * @param m the bottom margin in inches
+ */
+ public void setBottomMargin(double m)
+ {
+ bottomMargin = m;
+ }
+
+ /**
+ * Accessor for the bottom margin
+ *
+ * @return the bottom margin in inches
+ */
+ public double getBottomMargin()
+ {
+ return bottomMargin;
+ }
+
+ /**
+ * Gets the default margin width
+ *
+ * @return the default margin width
+ */
+ public double getDefaultWidthMargin()
+ {
+ return DEFAULT_WIDTH_MARGIN;
+ }
+
+ /**
+ * Gets the default margin height
+ *
+ * @return the default margin height
+ */
+ public double getDefaultHeightMargin()
+ {
+ return DEFAULT_HEIGHT_MARGIN;
+ }
+
+ /**
+ * Accessor for the fit width print flag
+ * @return TRUE if the print is to fit to pages, false otherwise
+ */
+ public boolean getFitToPages()
+ {
+ return fitToPages;
+ }
+
+ /**
+ * Accessor for the fit to pages flag
+ * @param b TRUE to fit to pages, FALSE to use a scale factor
+ */
+ public void setFitToPages(boolean b)
+ {
+ fitToPages = b;
+ }
+
+ /**
+ * Accessor for the password
+ *
+ * @return the password to unlock this sheet, or NULL if not protected
+ */
+ public String getPassword()
+ {
+ return password;
+ }
+
+ /**
+ * Sets the password for this sheet
+ *
+ * @param s the password
+ */
+ public void setPassword(String s)
+ {
+ password = s;
+ }
+
+ /**
+ * Accessor for the password hash - used only when copying sheets
+ *
+ * @return passwordHash
+ */
+ public int getPasswordHash()
+ {
+ return passwordHash;
+ }
+
+ /**
+ * Accessor for the password hash - used only when copying sheets
+ *
+ * @param ph the password hash
+ */
+ public void setPasswordHash(int ph)
+ {
+ passwordHash = ph;
+ }
+
+ /**
+ * Accessor for the default column width
+ *
+ * @return the default column width, in characters
+ */
+ public int getDefaultColumnWidth()
+ {
+ return defaultColumnWidth;
+ }
+
+ /**
+ * Sets the default column width
+ *
+ * @param w the new default column width
+ */
+ public void setDefaultColumnWidth(int w)
+ {
+ defaultColumnWidth = w;
+ }
+
+ /**
+ * Accessor for the default row height
+ *
+ * @return the default row height, in 1/20ths of a point
+ */
+ public int getDefaultRowHeight()
+ {
+ return defaultRowHeight;
+ }
+
+ /**
+ * Sets the default row height
+ *
+ * @param h the default row height, in 1/20ths of a point
+ */
+ public void setDefaultRowHeight(int h)
+ {
+ defaultRowHeight = h;
+ }
+
+ /**
+ * Accessor for the zoom factor. Do not confuse zoom factor (which relates
+ * to the on screen view) with scale factor (which refers to the scale factor
+ * when printing)
+ *
+ * @return the zoom factor as a percentage
+ */
+ public int getZoomFactor()
+ {
+ return zoomFactor;
+ }
+
+ /**
+ * Sets the zoom factor. Do not confuse zoom factor (which relates
+ * to the on screen view) with scale factor (which refers to the scale factor
+ * when printing)
+ *
+ * @param zf the zoom factor as a percentage
+ */
+ public void setZoomFactor(int zf)
+ {
+ zoomFactor = zf;
+ }
+
+ /**
+ * Accessor for the page break preview mangificaton factor.
+ * Do not confuse zoom factor or scale factor
+ *
+ * @return the page break preview magnification a percentage
+ */
+ public int getPageBreakPreviewMagnification()
+ {
+ return pageBreakPreviewMagnification;
+ }
+
+ /**
+ * Accessor for the page break preview magnificaton factor.
+ * Do not confuse zoom factor or scale factor
+ *
+ * @param f the page break preview magnification as a percentage
+ */
+ public void setPageBreakPreviewMagnification(int f)
+ {
+ pageBreakPreviewMagnification =f ;
+ }
+
+ /**
+ * Accessor for the nomral view magnificaton factor.
+ * Do not confuse zoom factor or scale factor
+ *
+ * @return the page break preview magnification a percentage
+ */
+ public int getNormalMagnification()
+ {
+ return normalMagnification;
+ }
+
+ /**
+ * Accessor for the normal magnificaton factor.
+ * Do not confuse zoom factor or scale factor
+ *
+ * @param f the page break preview magnification as a percentage
+ */
+ public void setNormalMagnification(int f)
+ {
+ normalMagnification = f ;
+ }
+
+
+ /**
+ * Accessor for the displayZeroValues property
+ *
+ * @return TRUE to display zero values, FALSE not to bother
+ */
+ public boolean getDisplayZeroValues()
+ {
+ return displayZeroValues;
+ }
+
+ /**
+ * Sets the displayZeroValues property
+ *
+ * @param b TRUE to show zero values, FALSE not to bother
+ */
+ public void setDisplayZeroValues(boolean b)
+ {
+ displayZeroValues = b;
+ }
+
+ /**
+ * Accessor for the showGridLines property
+ *
+ * @return TRUE if grid lines will be shown, FALSE otherwise
+ */
+ public boolean getShowGridLines()
+ {
+ return showGridLines;
+ }
+
+ /**
+ * Sets the showGridLines property
+ *
+ * @param b TRUE to show grid lines on this sheet, FALSE otherwise
+ */
+ public void setShowGridLines(boolean b)
+ {
+ showGridLines = b;
+ }
+
+ /**
+ * Accessor for the pageBreakPreview mode
+ *
+ * @return TRUE if page break preview is enabled, FALSE otherwise
+ */
+ public boolean getPageBreakPreviewMode()
+ {
+ return pageBreakPreviewMode;
+ }
+
+ /**
+ * Sets the pageBreakPreviewMode property
+ *
+ * @param b TRUE to launch in page break preview mode, FALSE otherwise
+ */
+ public void setPageBreakPreviewMode(boolean b)
+ {
+ pageBreakPreviewMode = b;
+ }
+
+ /**
+ * Accessor for the printGridLines property
+ *
+ * @return TRUE if grid lines will be printed, FALSE otherwise
+ */
+ public boolean getPrintGridLines()
+ {
+ return printGridLines;
+ }
+
+ /**
+ * Sets the printGridLines property
+ *
+ * @param b TRUE to print grid lines on this sheet, FALSE otherwise
+ */
+ public void setPrintGridLines(boolean b)
+ {
+ printGridLines = b;
+ }
+
+ /**
+ * Accessor for the printHeaders property
+ *
+ * @return TRUE if headers will be printed, FALSE otherwise
+ */
+ public boolean getPrintHeaders()
+ {
+ return printHeaders;
+ }
+
+ /**
+ * Sets the printHeaders property
+ *
+ * @param b TRUE to print headers on this sheet, FALSE otherwise
+ */
+ public void setPrintHeaders(boolean b)
+ {
+ printHeaders = b;
+ }
+
+ /**
+ * Gets the row at which the pane is frozen horizontally
+ *
+ * @return the row at which the pane is horizontally frozen, or 0 if there
+ * is no freeze
+ */
+ public int getHorizontalFreeze()
+ {
+ return horizontalFreeze;
+ }
+
+ /**
+ * Sets the row at which the pane is frozen horizontally
+ *
+ * @param row the row number to freeze at
+ */
+ public void setHorizontalFreeze(int row)
+ {
+ horizontalFreeze = Math.max(row, 0);
+ }
+
+ /**
+ * Gets the column at which the pane is frozen vertically
+ *
+ * @return the column at which the pane is vertically frozen, or 0 if there
+ * is no freeze
+ */
+ public int getVerticalFreeze()
+ {
+ return verticalFreeze;
+ }
+
+ /**
+ * Sets the row at which the pane is frozen vertically
+ *
+ * @param col the column number to freeze at
+ */
+ public void setVerticalFreeze(int col)
+ {
+ verticalFreeze = Math.max(col, 0);
+ }
+
+ /**
+ * Sets the number of copies
+ *
+ * @param c the number of copies
+ */
+ public void setCopies(int c)
+ {
+ copies = c;
+ }
+
+ /**
+ * Accessor for the number of copies to print
+ *
+ * @return the number of copies
+ */
+ public int getCopies()
+ {
+ return copies;
+ }
+
+ /**
+ * Accessor for the header
+ *
+ * @return the header
+ */
+ public HeaderFooter getHeader()
+ {
+ return header;
+ }
+
+ /**
+ * Sets the header
+ *
+ * @param h the header
+ */
+ public void setHeader(HeaderFooter h)
+ {
+ header = h;
+ }
+
+ /**
+ * Sets the footer
+ *
+ * @param f the footer
+ */
+ public void setFooter(HeaderFooter f)
+ {
+ footer = f;
+ }
+
+ /**
+ * Accessor for the footer
+ *
+ * @return the footer
+ */
+ public HeaderFooter getFooter()
+ {
+ return footer;
+ }
+
+ /**
+ * Accessor for the horizontal centre
+ *
+ * @return Returns the horizontalCentre.
+ */
+ public boolean isHorizontalCentre()
+ {
+ return horizontalCentre;
+ }
+
+ /**
+ * Sets the horizontal centre
+ *
+ * @param horizCentre The horizontalCentre to set.
+ */
+ public void setHorizontalCentre(boolean horizCentre)
+ {
+ this.horizontalCentre = horizCentre;
+ }
+
+ /**
+ * Accessor for the vertical centre
+ *
+ * @return Returns the verticalCentre.
+ */
+ public boolean isVerticalCentre()
+ {
+ return verticalCentre;
+ }
+
+ /**
+ * Sets the vertical centre
+ *
+ * @param vertCentre The verticalCentre to set.
+ */
+ public void setVerticalCentre(boolean vertCentre)
+ {
+ this.verticalCentre = vertCentre;
+ }
+
+ /**
+ * Sets the automatic formula calculation flag
+ *
+ * @param auto - TRUE to automatically calculate the formulas,
+ * FALSE otherwise
+ */
+ public void setAutomaticFormulaCalculation(boolean auto)
+ {
+ automaticFormulaCalculation = auto;
+ }
+
+ /**
+ * Retrieves the automatic formula calculation flag
+ *
+ * @return TRUE if formulas are calculated automatically, FALSE if they
+ * are calculated manually
+ */
+ public boolean getAutomaticFormulaCalculation()
+ {
+ return automaticFormulaCalculation;
+ }
+
+ /**
+ * Sets the recalculate formulas when the sheet is saved flag
+ *
+ * @param recalc - TRUE to automatically calculate the formulas when the,
+ * spreadsheet is saved, FALSE otherwise
+ */
+ public void setRecalculateFormulasBeforeSave(boolean recalc)
+ {
+ recalculateFormulasBeforeSave = recalc;
+ }
+
+ /**
+ * Retrieves the recalculate formulas before save flag
+ *
+ * @return TRUE if formulas are calculated before the sheet is saved,
+ * FALSE otherwise
+ */
+ public boolean getRecalculateFormulasBeforeSave()
+ {
+ return recalculateFormulasBeforeSave;
+ }
+
+ /**
+ * Sets the print area for this sheet
+ *
+ * @param firstCol the first column of the print area
+ * @param firstRow the first row of the print area
+ * @param lastCol the last column of the print area
+ * @param lastRow the last row of the print area
+ */
+ public void setPrintArea(int firstCol,
+ int firstRow,
+ int lastCol,
+ int lastRow)
+ {
+ printArea = new SheetRangeImpl(sheet, firstCol, firstRow,
+ lastCol, lastRow);
+ }
+
+ /**
+ * Accessor for the print area
+ *
+ * @return the print area, or NULL if one is not defined for this sheet
+ */
+ public Range getPrintArea()
+ {
+ return printArea;
+ }
+
+ /**
+ * Sets both of the print titles for this sheet
+ *
+ * @param firstRow the first row of the print row titles
+ * @param lastRow the last row of the print row titles
+ * @param firstCol the first column of the print column titles
+ * @param lastCol the last column of the print column titles
+ */
+ public void setPrintTitles(int firstRow,
+ int lastRow,
+ int firstCol,
+ int lastCol)
+ {
+ setPrintTitlesRow(firstRow, lastRow);
+ setPrintTitlesCol(firstCol, lastCol);
+ }
+
+ /**
+ * Sets the print row titles for this sheet
+ *
+ * @param firstRow the first row of the print titles
+ * @param lastRow the last row of the print titles
+ */
+ public void setPrintTitlesRow(int firstRow,
+ int lastRow)
+ {
+ printTitlesRow = new SheetRangeImpl(sheet, 0, firstRow,
+ 255, lastRow);
+ }
+
+ /**
+ * Sets the print column titles for this sheet
+ *
+ * @param firstRow the first row of the print titles
+ * @param lastRow the last row of the print titles
+ */
+ public void setPrintTitlesCol(int firstCol,
+ int lastCol)
+ {
+ printTitlesCol = new SheetRangeImpl(sheet, firstCol, 0,
+ lastCol, 65535);
+ }
+
+ /**
+ * Accessor for the print row titles
+ *
+ * @return the print row titles, or NULL if one is not defined for this sheet
+ */
+ public Range getPrintTitlesRow()
+ {
+ return printTitlesRow;
+ }
+
+ /**
+ * Accessor for the print column titles
+ *
+ * @return the print column titles, or NULL if one is not defined for this
+ * sheet
+ */
+ public Range getPrintTitlesCol()
+ {
+ return printTitlesCol;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/StringFormulaCell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/StringFormulaCell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/StringFormulaCell.java 17 Aug 2012 14:51:24 -0000 1.1
@@ -0,0 +1,30 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+/**
+ * A mixin interface for numerical formulas, which combines the interfaces
+ * for formulas and for strings
+ */
+public interface StringFormulaCell extends LabelCell, FormulaCell
+{
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/Workbook.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/Workbook.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/Workbook.java 17 Aug 2012 14:51:25 -0000 1.1
@@ -0,0 +1,419 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import jxl.read.biff.BiffException;
+import jxl.read.biff.File;
+import jxl.read.biff.PasswordException;
+import jxl.read.biff.WorkbookParser;
+import jxl.write.WritableWorkbook;
+import jxl.write.biff.WritableWorkbookImpl;
+
+/**
+ * Represents a Workbook. Contains the various factory methods and provides
+ * a variety of accessors which provide access to the work sheets.
+ */
+public abstract class Workbook
+{
+ /**
+ * The current version of the software
+ */
+ private static final String VERSION = "2.6.9";
+
+ /**
+ * The constructor
+ */
+ protected Workbook()
+ {
+ }
+
+ /**
+ * Gets the sheets within this workbook. Use of this method for
+ * large worksheets can cause performance problems.
+ *
+ * @return an array of the individual sheets
+ */
+ public abstract Sheet[] getSheets();
+
+ /**
+ * Gets the sheet names
+ *
+ * @return an array of strings containing the sheet names
+ */
+ public abstract String[] getSheetNames();
+
+ /**
+ * Gets the specified sheet within this workbook
+ * As described in the accompanying technical notes, each call
+ * to getSheet forces a reread of the sheet (for memory reasons).
+ * Therefore, do not make unnecessary calls to this method. Furthermore,
+ * do not hold unnecessary references to Sheets in client code, as
+ * this will prevent the garbage collector from freeing the memory
+ *
+ * @param index the zero based index of the reQuired sheet
+ * @return The sheet specified by the index
+ * @exception IndexOutOfBoundException when index refers to a non-existent
+ * sheet
+ */
+ public abstract Sheet getSheet(int index)
+ throws IndexOutOfBoundsException;
+
+ /**
+ * Gets the sheet with the specified name from within this workbook.
+ * As described in the accompanying technical notes, each call
+ * to getSheet forces a reread of the sheet (for memory reasons).
+ * Therefore, do not make unnecessary calls to this method. Furthermore,
+ * do not hold unnecessary references to Sheets in client code, as
+ * this will prevent the garbage collector from freeing the memory
+ *
+ * @param name the sheet name
+ * @return The sheet with the specified name, or null if it is not found
+ */
+ public abstract Sheet getSheet(String name);
+
+ /**
+ * Accessor for the software version
+ *
+ * @return the version
+ */
+ public static String getVersion()
+ {
+ return VERSION;
+ }
+
+ /**
+ * Returns the number of sheets in this workbook
+ *
+ * @return the number of sheets in this workbook
+ */
+ public abstract int getNumberOfSheets();
+
+ /**
+ * Gets the named cell from this workbook. If the name refers to a
+ * range of cells, then the cell on the top left is returned. If
+ * the name cannot be found, null is returned.
+ * This is a convenience function to quickly access the contents
+ * of a single cell. If you need further information (such as the
+ * sheet or adjacent cells in the range) use the functionally
+ * richer method, findByName which returns a list of ranges
+ *
+ * @param name the name of the cell/range to search for
+ * @return the cell in the top left of the range if found, NULL
+ * otherwise
+ */
+ public abstract Cell findCellByName(String name);
+
+ /**
+ * Returns the cell for the specified location eg. "Sheet1!A4".
+ * This is identical to using the CellReferenceHelper with its
+ * associated performance overheads, consequently it should
+ * be use sparingly
+ *
+ * @param loc the cell to retrieve
+ * @return the cell at the specified location
+ */
+ public abstract Cell getCell(String loc);
+
+ /**
+ * Gets the named range from this workbook. The Range object returns
+ * contains all the cells from the top left to the bottom right
+ * of the range.
+ * If the named range comprises an adjacent range,
+ * the Range[] will contain one object; for non-adjacent
+ * ranges, it is necessary to return an array of length greater than
+ * one.
+ * If the named range contains a single cell, the top left and
+ * bottom right cell will be the same cell
+ *
+ * @param name the name of the cell/range to search for
+ * @return the range of cells, or NULL if the range does not exist
+ */
+ public abstract Range[] findByName(String name);
+
+ /**
+ * Gets the named ranges
+ *
+ * @return the list of named cells within the workbook
+ */
+ public abstract String[] getRangeNames();
+
+
+ /**
+ * Determines whether the sheet is protected
+ *
+ * @return TRUE if the workbook is protected, FALSE otherwise
+ */
+ public abstract boolean isProtected();
+
+ /**
+ * Parses the excel file.
+ * If the workbook is password protected a PasswordException is thrown
+ * in case consumers of the API wish to handle this in a particular way
+ *
+ * @exception BiffException
+ * @exception PasswordException
+ */
+ protected abstract void parse() throws BiffException, PasswordException;
+
+ /**
+ * Closes this workbook, and frees makes any memory allocated available
+ * for garbage collection
+ */
+ public abstract void close();
+
+ /**
+ * A factory method which takes in an excel file and reads in the contents.
+ *
+ * @exception IOException
+ * @exception BiffException
+ * @param file the excel 97 spreadsheet to parse
+ * @return a workbook instance
+ */
+ public static Workbook getWorkbook(java.io.File file)
+ throws IOException, BiffException
+ {
+ return getWorkbook(file, new WorkbookSettings());
+ }
+
+ /**
+ * A factory method which takes in an excel file and reads in the contents.
+ *
+ * @exception IOException
+ * @exception BiffException
+ * @param file the excel 97 spreadsheet to parse
+ * @param ws the settings for the workbook
+ * @return a workbook instance
+ */
+ public static Workbook getWorkbook(java.io.File file, WorkbookSettings ws)
+ throws IOException, BiffException
+ {
+ FileInputStream fis = new FileInputStream(file);
+
+ // Always close down the input stream, regardless of whether or not the
+ // file can be parsed. Thanks to Steve Hahn for this
+ File dataFile = null;
+
+ try
+ {
+ dataFile = new File(fis, ws);
+ }
+ catch (IOException e)
+ {
+ fis.close();
+ throw e;
+ }
+ catch (BiffException e)
+ {
+ fis.close();
+ throw e;
+ }
+
+ fis.close();
+
+ Workbook workbook = new WorkbookParser(dataFile, ws);
+ workbook.parse();
+
+ return workbook;
+ }
+
+ /**
+ * A factory method which takes in an excel file and reads in the contents.
+ *
+ * @param is an open stream which is the the excel 97 spreadsheet to parse
+ * @return a workbook instance
+ * @exception IOException
+ * @exception BiffException
+ */
+ public static Workbook getWorkbook(InputStream is)
+ throws IOException, BiffException
+ {
+ return getWorkbook(is, new WorkbookSettings());
+ }
+
+ /**
+ * A factory method which takes in an excel file and reads in the contents.
+ *
+ * @param is an open stream which is the the excel 97 spreadsheet to parse
+ * @param ws the settings for the workbook
+ * @return a workbook instance
+ * @exception IOException
+ * @exception BiffException
+ */
+ public static Workbook getWorkbook(InputStream is, WorkbookSettings ws)
+ throws IOException, BiffException
+ {
+ File dataFile = new File(is, ws);
+
+ Workbook workbook = new WorkbookParser(dataFile, ws);
+ workbook.parse();
+
+ return workbook;
+ }
+
+ /**
+ * Creates a writable workbook with the given file name
+ *
+ * @param file the workbook to copy
+ * @return a writable workbook
+ * @exception IOException
+ */
+ public static WritableWorkbook createWorkbook(java.io.File file)
+ throws IOException
+ {
+ return createWorkbook(file, new WorkbookSettings());
+ }
+
+ /**
+ * Creates a writable workbook with the given file name
+ *
+ * @param file the file to copy from
+ * @param ws the global workbook settings
+ * @return a writable workbook
+ * @exception IOException
+ */
+ public static WritableWorkbook createWorkbook(java.io.File file,
+ WorkbookSettings ws)
+ throws IOException
+ {
+ FileOutputStream fos = new FileOutputStream(file);
+ WritableWorkbook w = new WritableWorkbookImpl(fos, true, ws);
+ return w;
+ }
+
+ /**
+ * Creates a writable workbook with the given filename as a copy of
+ * the workbook passed in. Once created, the contents of the writable
+ * workbook may be modified
+ *
+ * @param file the output file for the copy
+ * @param in the workbook to copy
+ * @return a writable workbook
+ * @exception IOException
+ */
+ public static WritableWorkbook createWorkbook(java.io.File file,
+ Workbook in)
+ throws IOException
+ {
+ return createWorkbook(file, in, new WorkbookSettings());
+ }
+
+ /**
+ * Creates a writable workbook with the given filename as a copy of
+ * the workbook passed in. Once created, the contents of the writable
+ * workbook may be modified
+ *
+ * @param file the output file for the copy
+ * @param in the workbook to copy
+ * @param ws the configuration for this workbook
+ * @return a writable workbook
+ */
+ public static WritableWorkbook createWorkbook(java.io.File file,
+ Workbook in,
+ WorkbookSettings ws)
+ throws IOException
+ {
+ FileOutputStream fos = new FileOutputStream(file);
+ WritableWorkbook w = new WritableWorkbookImpl(fos, in, true, ws);
+ return w;
+ }
+
+ /**
+ * Creates a writable workbook as a copy of
+ * the workbook passed in. Once created, the contents of the writable
+ * workbook may be modified
+ *
+ * @param os the stream to write to
+ * @param in the workbook to copy
+ * @return a writable workbook
+ * @exception IOException
+ */
+ public static WritableWorkbook createWorkbook(OutputStream os,
+ Workbook in)
+ throws IOException
+ {
+ return createWorkbook(os, in, ((WorkbookParser) in).getSettings());
+ }
+
+ /**
+ * Creates a writable workbook as a copy of
+ * the workbook passed in. Once created, the contents of the writable
+ * workbook may be modified
+ *
+ * @param os the output stream to write to
+ * @param in the workbook to copy
+ * @param ws the configuration for this workbook
+ * @return a writable workbook
+ * @exception IOException
+ */
+ public static WritableWorkbook createWorkbook(OutputStream os,
+ Workbook in,
+ WorkbookSettings ws)
+ throws IOException
+ {
+ WritableWorkbook w = new WritableWorkbookImpl(os, in, false, ws);
+ return w;
+ }
+
+ /**
+ * Creates a writable workbook. When the workbook is closed,
+ * it will be streamed directly to the output stream. In this
+ * manner, a generated excel spreadsheet can be passed from
+ * a servlet to the browser over HTTP
+ *
+ * @param os the output stream
+ * @return the writable workbook
+ * @exception IOException
+ */
+ public static WritableWorkbook createWorkbook(OutputStream os)
+ throws IOException
+ {
+ return createWorkbook(os, new WorkbookSettings());
+ }
+
+ /**
+ * Creates a writable workbook. When the workbook is closed,
+ * it will be streamed directly to the output stream. In this
+ * manner, a generated excel spreadsheet can be passed from
+ * a servlet to the browser over HTTP
+ *
+ * @param os the output stream
+ * @param ws the configuration for this workbook
+ * @return the writable workbook
+ * @exception IOException
+ */
+ public static WritableWorkbook createWorkbook(OutputStream os,
+ WorkbookSettings ws)
+ throws IOException
+ {
+ WritableWorkbook w = new WritableWorkbookImpl(os, false, ws);
+ return w;
+ }
+}
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/WorkbookSettings.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/WorkbookSettings.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/WorkbookSettings.java 17 Aug 2012 14:51:24 -0000 1.1
@@ -0,0 +1,715 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Locale;
+
+import common.Logger;
+
+import jxl.biff.CountryCode;
+import jxl.biff.formula.FunctionNames;
+
+/**
+ * This is a bean which client applications may use to set various advanced
+ * workbook properties. Use of this bean is not mandatory, and its absence
+ * will merely result in workbooks being read/written using the default
+ * settings
+ */
+public final class WorkbookSettings
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(WorkbookSettings.class);
+
+ /**
+ * The amount of memory allocated to store the workbook data when
+ * reading a worksheet. For processeses reading many small workbooks inside
+ * a WAS it might be necessary to reduce the default size
+ */
+ private int initialFileSize;
+
+ /**
+ * The amount of memory allocated to the array containing the workbook
+ * data when its current amount is exhausted.
+ */
+ private int arrayGrowSize;
+
+ /**
+ * Flag to indicate whether the drawing feature is enabled or not
+ * Drawings deactivated using -Djxl.nodrawings=true on the JVM command line
+ * Activated by default or by using -Djxl.nodrawings=false on the JVM command
+ * line
+ */
+ private boolean drawingsDisabled;
+
+ /**
+ * Flag to indicate whether the name feature is enabled or not
+ * Names deactivated using -Djxl.nonames=true on the JVM command line
+ * Activated by default or by using -Djxl.nonames=false on the JVM command
+ * line
+ */
+ private boolean namesDisabled;
+
+ /**
+ * Flag to indicate whether formula cell references should be adjusted
+ * following row/column insertion/deletion
+ */
+ private boolean formulaReferenceAdjustDisabled;
+
+ /**
+ * Flag to indicate whether the system hint garbage collection
+ * is enabled or not.
+ * As a rule of thumb, it is desirable to enable garbage collection
+ * when reading large spreadsheets from a batch process or from the
+ * command line, but better to deactivate the feature when reading
+ * large spreadsheets within a WAS, as the calls to System.gc() not
+ * only garbage collect the junk in JExcelApi, but also in the
+ * webservers JVM and can cause significant slowdown
+ * GC deactivated using -Djxl.nogc=true on the JVM command line
+ * Activated by default or by using -Djxl.nogc=false on the JVM command line
+ */
+ private boolean gcDisabled;
+
+ /**
+ * Flag to indicate whether the rationalization of cell formats is
+ * disabled or not.
+ * Rationalization is enabled by default, but may be disabled for
+ * performance reasons. It can be deactivated using -Djxl.norat=true on
+ * the JVM command line
+ */
+ private boolean rationalizationDisabled;
+
+ /**
+ * Flag to indicate whether or not the merged cell checking has been
+ * disabled
+ */
+ private boolean mergedCellCheckingDisabled;
+
+ /**
+ * Flag to indicate whether the copying of additional property sets
+ * are disabled
+ */
+ private boolean propertySetsDisabled;
+
+ /**
+ * Flag to indicate that cell validation criteria are ignored
+ */
+ private boolean cellValidationDisabled;
+
+ /**
+ * Flag to indicate whether or not to ignore blank cells when processing
+ * sheets. Cells which are identified as blank can still have associated
+ * cell formats which the processing program may still need to read
+ */
+ private boolean ignoreBlankCells;
+
+ /**
+ * Flag to indicate whether auto filtering should be read/copied
+ */
+ private boolean autoFilterDisabled;
+
+ /**
+ * Flag to indicate whether a temporary file should be used when
+ * writing out the workbook
+ */
+ private boolean useTemporaryFileDuringWrite;
+
+ /**
+ * The directory for used for the temporary file during write. If this
+ * is NULL, the default system directory is used
+ */
+ private File temporaryFileDuringWriteDirectory;
+
+ /**
+ * The locale. Normally this is the same as the system locale, but there
+ * may be cases (eg. where you are uploading many spreadsheets from foreign
+ * sources) where you may want to specify the locale on an individual
+ * worksheet basis
+ * The locale may also be specified on the command line using the lang and
+ * country System properties eg. -Djxl.lang=en -Djxl.country=UK for UK
+ * English
+ */
+ private Locale locale;
+
+ /**
+ * The locale specific function names for this workbook
+ */
+ private FunctionNames functionNames;
+
+ /**
+ * The character encoding used for reading non-unicode strings. This can
+ * be different from the default platform encoding if processing spreadsheets
+ * from abroad. This may also be set using the system property jxl.encoding
+ */
+ private String encoding;
+
+ /**
+ * The character set used by the readable spreadsheeet
+ */
+ private int characterSet;
+
+ /**
+ * The display language used by Excel (ISO 3166 mnemonic)
+ */
+ private String excelDisplayLanguage;
+
+ /**
+ * The regional settings used by Excel (ISO 3166 mnemonic)
+ */
+ private String excelRegionalSettings;
+
+ /**
+ * A hash map of function names keyed on locale
+ */
+ private HashMap localeFunctionNames;
+
+ // **
+ // The default values
+ // **
+ private static final int DEFAULT_INITIAL_FILE_SIZE = 5 * 1024 * 1024;
+ // 5 megabytes
+ private static final int DEFAULT_ARRAY_GROW_SIZE = 1024 * 1024; // 1 megabyte
+
+ /**
+ * Default constructor
+ */
+ public WorkbookSettings()
+ {
+ initialFileSize = DEFAULT_INITIAL_FILE_SIZE;
+ arrayGrowSize = DEFAULT_ARRAY_GROW_SIZE;
+ localeFunctionNames = new HashMap();
+ excelDisplayLanguage = CountryCode.USA.getCode();
+ excelRegionalSettings = CountryCode.UK.getCode();
+
+ // Initialize other properties from the system properties
+ try
+ {
+ boolean suppressWarnings = Boolean.getBoolean("jxl.nowarnings");
+ setSuppressWarnings(suppressWarnings);
+ drawingsDisabled = Boolean.getBoolean("jxl.nodrawings");
+ namesDisabled = Boolean.getBoolean("jxl.nonames");
+ gcDisabled = Boolean.getBoolean("jxl.nogc");
+ rationalizationDisabled = Boolean.getBoolean("jxl.norat");
+ mergedCellCheckingDisabled =
+ Boolean.getBoolean("jxl.nomergedcellchecks");
+ formulaReferenceAdjustDisabled =
+ Boolean.getBoolean("jxl.noformulaadjust");
+ propertySetsDisabled = Boolean.getBoolean("jxl.nopropertysets");
+ ignoreBlankCells = Boolean.getBoolean("jxl.ignoreblanks");
+ cellValidationDisabled = Boolean.getBoolean("jxl.nocellvalidation");
+ autoFilterDisabled = !Boolean.getBoolean("jxl.autofilter");
+ // autofilter currently disabled by default
+ useTemporaryFileDuringWrite =
+ Boolean.getBoolean("jxl.usetemporaryfileduringwrite");
+ String tempdir =
+ System.getProperty("jxl.temporaryfileduringwritedirectory");
+
+ if (tempdir != null)
+ {
+ temporaryFileDuringWriteDirectory = new File(tempdir);
+ }
+
+ encoding = System.getProperty("file.encoding");
+ }
+ catch (SecurityException e)
+ {
+ logger.warn("Error accessing system properties.", e);
+ }
+
+ // Initialize the locale to the system locale
+ try
+ {
+ if (System.getProperty("jxl.lang") == null ||
+ System.getProperty("jxl.country") == null)
+ {
+ locale = Locale.getDefault();
+ }
+ else
+ {
+ locale = new Locale(System.getProperty("jxl.lang"),
+ System.getProperty("jxl.country"));
+ }
+
+ if (System.getProperty("jxl.encoding") != null)
+ {
+ encoding = System.getProperty("jxl.encoding");
+ }
+ }
+ catch (SecurityException e)
+ {
+ logger.warn("Error accessing system properties.", e);
+ locale = Locale.getDefault();
+ }
+ }
+
+ /**
+ * Sets the amount of memory by which to increase the amount of
+ * memory allocated to storing the workbook data.
+ * For processeses reading many small workbooks
+ * inside a WAS it might be necessary to reduce the default size
+ * Default value is 1 megabyte
+ *
+ * @param sz the file size in bytes
+ */
+ public void setArrayGrowSize(int sz)
+ {
+ arrayGrowSize = sz;
+ }
+
+ /**
+ * Accessor for the array grow size property
+ *
+ * @return the array grow size
+ */
+ public int getArrayGrowSize()
+ {
+ return arrayGrowSize;
+ }
+
+ /**
+ * Sets the initial amount of memory allocated to store the workbook data
+ * when reading a worksheet. For processeses reading many small workbooks
+ * inside a WAS it might be necessary to reduce the default size
+ * Default value is 5 megabytes
+ *
+ * @param sz the file size in bytes
+ */
+ public void setInitialFileSize(int sz)
+ {
+ initialFileSize = sz;
+ }
+
+ /**
+ * Accessor for the initial file size property
+ *
+ * @return the initial file size
+ */
+ public int getInitialFileSize()
+ {
+ return initialFileSize;
+ }
+
+ /**
+ * Gets the drawings disabled flag
+ *
+ * @return TRUE if drawings are disabled, FALSE otherwise
+ */
+ public boolean getDrawingsDisabled()
+ {
+ return drawingsDisabled;
+ }
+
+ /**
+ * Accessor for the disabling of garbage collection
+ *
+ * @return FALSE if JExcelApi hints for garbage collection, TRUE otherwise
+ */
+ public boolean getGCDisabled()
+ {
+ return gcDisabled;
+ }
+
+ /**
+ * Accessor for the disabling of interpretation of named ranges
+ *
+ * @return FALSE if named cells are interpreted, TRUE otherwise
+ */
+ public boolean getNamesDisabled()
+ {
+ return namesDisabled;
+ }
+
+ /**
+ * Disables the handling of names
+ *
+ * @param b TRUE to disable the names feature, FALSE otherwise
+ */
+ public void setNamesDisabled(boolean b)
+ {
+ namesDisabled = b;
+ }
+
+ /**
+ * Disables the handling of drawings
+ *
+ * @param b TRUE to disable the names feature, FALSE otherwise
+ */
+ public void setDrawingsDisabled(boolean b)
+ {
+ drawingsDisabled = b;
+ }
+
+ /**
+ * Sets whether or not to rationalize the cell formats before
+ * writing out the sheet. The default value is true
+ *
+ * @param r the rationalization flag
+ */
+ public void setRationalization(boolean r)
+ {
+ rationalizationDisabled = !r;
+ }
+
+ /**
+ * Accessor to retrieve the rationalization flag
+ *
+ * @return TRUE if rationalization is off, FALSE if rationalization is on
+ */
+ public boolean getRationalizationDisabled()
+ {
+ return rationalizationDisabled;
+ }
+
+ /**
+ * Accessor to retrieve the merged cell checking flag
+ *
+ * @return TRUE if merged cell checking is off, FALSE if it is on
+ */
+ public boolean getMergedCellCheckingDisabled()
+ {
+ return mergedCellCheckingDisabled;
+ }
+
+ /**
+ * Accessor to set the merged cell checking
+ *
+ * @param b - TRUE to enable merged cell checking, FALSE otherwise
+ */
+ public void setMergedCellChecking(boolean b)
+ {
+ mergedCellCheckingDisabled = !b;
+ }
+
+ /**
+ * Sets whether or not to enable any property sets (such as macros)
+ * to be copied along with the workbook
+ * Leaving this feature enabled will result in the JXL process using
+ * more memory
+ *
+ * @param r the property sets flag
+ */
+ public void setPropertySets(boolean r)
+ {
+ propertySetsDisabled = !r;
+ }
+
+ /**
+ * Accessor to retrieve the property sets disabled flag
+ *
+ * @return TRUE if property sets are disabled, FALSE otherwise
+ */
+ public boolean getPropertySetsDisabled()
+ {
+ return propertySetsDisabled;
+ }
+
+ /**
+ * Accessor to set the suppress warnings flag. Due to the change
+ * in logging in version 2.4, this will now set the warning
+ * behaviour across the JVM (depending on the type of logger used)
+ *
+ * @param w the flag
+ */
+ public void setSuppressWarnings(boolean w)
+ {
+ logger.setSuppressWarnings(w);
+ }
+
+ /**
+ * Accessor for the formula adjust disabled
+ *
+ * @return TRUE if formulas are adjusted following row/column inserts/deletes
+ * FALSE otherwise
+ */
+ public boolean getFormulaAdjust()
+ {
+ return !formulaReferenceAdjustDisabled;
+ }
+
+ /**
+ * Setter for the formula adjust disabled property
+ *
+ * @param b TRUE to adjust formulas, FALSE otherwise
+ */
+ public void setFormulaAdjust(boolean b)
+ {
+ formulaReferenceAdjustDisabled = !b;
+ }
+
+ /**
+ * Sets the locale used by JExcelApi to generate the spreadsheet.
+ * Setting this value has no effect on the language or region of
+ * the generated excel file
+ *
+ * @param l the locale
+ */
+ public void setLocale(Locale l)
+ {
+ locale = l;
+ }
+
+ /**
+ * Returns the locale used by JExcelAPI to read the spreadsheet
+ *
+ * @return the locale
+ */
+ public Locale getLocale()
+ {
+ return locale;
+ }
+
+ /**
+ * Accessor for the character encoding
+ *
+ * @return the character encoding for this workbook
+ */
+ public String getEncoding()
+ {
+ return encoding;
+ }
+
+ /**
+ * Sets the encoding for this workbook
+ *
+ * @param enc the encoding
+ */
+ public void setEncoding(String enc)
+ {
+ encoding = enc;
+ }
+
+ /**
+ * Gets the function names. This is used by the formula parsing package
+ * in order to get the locale specific function names for this particular
+ * workbook
+ *
+ * @return the list of function names
+ */
+ public FunctionNames getFunctionNames()
+ {
+ if (functionNames == null)
+ {
+ functionNames = (FunctionNames) localeFunctionNames.get(locale);
+
+ // have not previously accessed function names for this locale,
+ // so create a brand new one and add it to the list
+ if (functionNames == null)
+ {
+ functionNames = new FunctionNames(locale);
+ localeFunctionNames.put(locale, functionNames);
+ }
+ }
+
+ return functionNames;
+ }
+
+ /**
+ * Accessor for the character set. This value is only used for reading
+ * and has no effect when writing out the spreadsheet
+ *
+ * @return the character set used by this spreadsheet
+ */
+ public int getCharacterSet()
+ {
+ return characterSet;
+ }
+
+ /**
+ * Sets the character set. This is only used when the spreadsheet is
+ * read, and has no effect when the spreadsheet is written
+ *
+ * @param cs the character set encoding value
+ */
+ public void setCharacterSet(int cs)
+ {
+ characterSet = cs;
+ }
+
+ /**
+ * Sets the garbage collection disabled
+ *
+ * @param disabled TRUE to disable garbage collection, FALSE to enable it
+ */
+ public void setGCDisabled(boolean disabled)
+ {
+ gcDisabled = disabled;
+ }
+
+ /**
+ * Sets the ignore blanks flag
+ *
+ * @param ignoreBlanks TRUE to ignore blanks, FALSE to take them into account
+ */
+ public void setIgnoreBlanks(boolean ignoreBlanks)
+ {
+ ignoreBlankCells = ignoreBlanks;
+ }
+
+ /**
+ * Accessor for the ignore blanks flag
+ *
+ * @return TRUE if blank cells are being ignored, FALSE otherwise
+ */
+ public boolean getIgnoreBlanks()
+ {
+ return ignoreBlankCells;
+ }
+
+ /**
+ * Sets the ignore cell validation flag
+ *
+ * @param cv TRUE to disable cell validation, FALSE to enable it
+ */
+ public void setCellValidationDisabled(boolean cv)
+ {
+ cellValidationDisabled = cv;
+ }
+
+ /**
+ * Accessor for the ignore cell validation
+ *
+ * @return TRUE if cell validation is disabled
+ */
+ public boolean getCellValidationDisabled()
+ {
+ return cellValidationDisabled;
+ }
+
+ /**
+ * Returns the two character ISO 3166 mnemonic used by excel for user
+ * language displayto display
+ * @return the display language
+ */
+ public String getExcelDisplayLanguage()
+ {
+ return excelDisplayLanguage;
+ }
+
+ /**
+ * Returns the two character ISO 3166 mnemonic used by excel for
+ * its regional settings
+ * @return the regional settings
+ */
+ public String getExcelRegionalSettings()
+ {
+ return excelRegionalSettings;
+ }
+
+ /**
+ * Sets the language in which the generated file will display
+ *
+ * @param code the two character ISO 3166 country code
+ */
+ public void setExcelDisplayLanguage(String code)
+ {
+ excelDisplayLanguage = code;
+ }
+
+ /**
+ * Sets the regional settings for the generated excel file
+ *
+ * @param code the two character ISO 3166 country code
+ */
+ public void setExcelRegionalSettings(String code)
+ {
+ excelRegionalSettings = code;
+ }
+
+ /**
+ * Accessor for the autofilter disabled feature
+ *
+ * @return TRUE if autofilter is disabled, FALSE otherwise
+ */
+ public boolean getAutoFilterDisabled()
+ {
+ return autoFilterDisabled;
+ }
+
+ /**
+ * Sets the autofilter disabled
+ *
+ * @param disabled
+ */
+ public void setAutoFilterDisabled(boolean disabled)
+ {
+ autoFilterDisabled = disabled;
+ }
+
+ /**
+ * Accessor for the temporary file during write. If this is set, then
+ * when the workbook is written a temporary file will be used to store
+ * the interim binary data, otherwise it will take place in memory. Setting
+ * this flag involves an assessment of the trade-offs between memory usage
+ * and performance
+ *
+ * @return TRUE if a temporary is file is used during writing,
+ * FALSE otherwise
+ */
+ public boolean getUseTemporaryFileDuringWrite()
+ {
+ return useTemporaryFileDuringWrite;
+ }
+
+ /**
+ * Sets whether a temporary file is used during the generation of
+ * the workbook. If not set, the workbook will take place entirely in
+ * memory. Setting
+ * this flag involves an assessment of the trade-offs between memory usage
+ * and performance
+ *
+ * @return TRUE if a temporary is file is used during writing,
+ * FALSE otherwise
+ */
+ public void setUseTemporaryFileDuringWrite(boolean temp)
+ {
+ useTemporaryFileDuringWrite = temp;
+ }
+
+ /**
+ * Used in conjunction with the UseTemporaryFileDuringWrite setting to
+ * set the target directory for the temporary files. If this is not set,
+ * the system default temporary directory is used.
+ * This has no effect unless the useTemporaryFileDuringWrite setting
+ * is TRUE
+ *
+ * @param dir the directory to which temporary files should be written
+ */
+ public void setTemporaryFileDuringWriteDirectory(File dir)
+ {
+ temporaryFileDuringWriteDirectory = dir;
+ }
+
+ /**
+ * Used in conjunction with the UseTemporaryFileDuringWrite setting to
+ * set the target directory for the temporary files. This value can
+ * be NULL, in which case the normal system default temporary directory
+ * is used instead
+ *
+ * @return the temporary directory used during write, or NULL if it is
+ * not set
+ */
+ public File getTemporaryFileDuringWriteDirectory()
+ {
+ return temporaryFileDuringWriteDirectory;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/AutoFilter.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/AutoFilter.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/AutoFilter.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,73 @@
+/*********************************************************************
+*
+* Copyright (C) 2007 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import java.io.IOException;
+
+import jxl.write.biff.File;
+
+/**
+ * Information for autofiltering
+ */
+public class AutoFilter
+{
+ private FilterModeRecord filterMode;
+ private AutoFilterInfoRecord autoFilterInfo;
+ private AutoFilterRecord autoFilter;
+
+ /**
+ * Constructor
+ */
+ public AutoFilter(FilterModeRecord fmr,
+ AutoFilterInfoRecord afir)
+ {
+ filterMode = fmr;
+ autoFilterInfo = afir;
+ }
+
+ public void add(AutoFilterRecord af)
+ {
+ autoFilter = af; // make this into a list sometime
+ }
+
+ /**
+ * Writes out the data validation
+ *
+ * @exception IOException
+ * @param outputFile the output file
+ */
+ public void write(File outputFile) throws IOException
+ {
+ if (filterMode != null)
+ {
+ outputFile.write(filterMode);
+ }
+
+ if (autoFilterInfo != null)
+ {
+ outputFile.write(autoFilterInfo);
+ }
+
+ if (autoFilter != null)
+ {
+ outputFile.write(autoFilter);
+ }
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/AutoFilterInfoRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/AutoFilterInfoRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/AutoFilterInfoRecord.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,60 @@
+/*********************************************************************
+*
+* Copyright (C) 2007 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Logger;
+
+import jxl.read.biff.Record;
+
+/**
+ * Range information for conditional formatting
+ */
+public class AutoFilterInfoRecord extends WritableRecordData
+{
+ // The logger
+ private static Logger logger = Logger.getLogger(AutoFilterInfoRecord.class);
+
+ /**
+ * The data
+ */
+ private byte[] data;
+
+
+ /**
+ * Constructor
+ */
+ public AutoFilterInfoRecord(Record t)
+ {
+ super(t);
+
+ data = getRecord().getData();
+ }
+
+ /**
+ * Retrieves the data for output to binary file
+ *
+ * @return the data to be written
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/AutoFilterRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/AutoFilterRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/AutoFilterRecord.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,60 @@
+/*********************************************************************
+*
+* Copyright (C) 2007 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Logger;
+
+import jxl.read.biff.Record;
+
+/**
+ * Range information for conditional formatting
+ */
+public class AutoFilterRecord extends WritableRecordData
+{
+ // The logger
+ private static Logger logger = Logger.getLogger(AutoFilterRecord.class);
+
+ /**
+ * The data
+ */
+ private byte[] data;
+
+
+ /**
+ * Constructor
+ */
+ public AutoFilterRecord(Record t)
+ {
+ super(t);
+
+ data = getRecord().getData();
+ }
+
+ /**
+ * Retrieves the data for output to binary file
+ *
+ * @return the data to be written
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/BaseCellFeatures.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/BaseCellFeatures.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/BaseCellFeatures.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,434 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import java.util.Collection;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.biff.drawing.ComboBox;
+import jxl.biff.drawing.Comment;
+import jxl.write.biff.CellValue;
+
+/**
+ * Container for any additional cell features
+ */
+public class BaseCellFeatures
+{
+ /**
+ * The logger
+ */
+ public static Logger logger = Logger.getLogger(BaseCellFeatures.class);
+
+ /**
+ * The comment
+ */
+ private String comment;
+
+ /**
+ * The comment width in cells
+ */
+ private double commentWidth;
+
+ /**
+ * The comment height in cells
+ */
+ private double commentHeight;
+
+ /**
+ * A handle to the drawing object
+ */
+ private Comment commentDrawing;
+
+ /**
+ * A handle to the combo box object
+ */
+ private ComboBox comboBox;
+
+ /**
+ * The data validation settings
+ */
+ private DataValiditySettingsRecord validationSettings;
+
+ /**
+ * The DV Parser used to contain the validation details
+ */
+ private DVParser dvParser;
+
+ /**
+ * Indicates whether a drop down is required
+ */
+ private boolean dropDown;
+
+ /**
+ * Indicates whether this cell features has data validation
+ */
+ private boolean dataValidation;
+
+ /**
+ * The cell to which this is attached, and which may need to be notified
+ */
+ private CellValue writableCell;
+
+ // Constants
+ private final static double defaultCommentWidth = 3;
+ private final static double defaultCommentHeight = 4;
+
+ // Validation conditions
+ protected static class ValidationCondition
+ {
+ private DVParser.Condition condition;
+
+ private static ValidationCondition[] types = new ValidationCondition[0];
+
+ ValidationCondition(DVParser.Condition c)
+ {
+ condition = c;
+ ValidationCondition[] oldtypes = types;
+ types = new ValidationCondition[oldtypes.length+1];
+ System.arraycopy(oldtypes, 0, types, 0, oldtypes.length);
+ types[oldtypes.length] = this;
+ }
+
+ public DVParser.Condition getCondition()
+ {
+ return condition;
+ }
+ }
+
+ public static final ValidationCondition BETWEEN =
+ new ValidationCondition(DVParser.BETWEEN);
+ public static final ValidationCondition NOT_BETWEEN =
+ new ValidationCondition(DVParser.NOT_BETWEEN);
+ public static final ValidationCondition EQUAL =
+ new ValidationCondition(DVParser.EQUAL);
+ public static final ValidationCondition NOT_EQUAL =
+ new ValidationCondition(DVParser.NOT_EQUAL);
+ public static final ValidationCondition GREATER_THAN =
+ new ValidationCondition(DVParser.GREATER_THAN);
+ public static final ValidationCondition LESS_THAN =
+ new ValidationCondition(DVParser.LESS_THAN);
+ public static final ValidationCondition GREATER_EQUAL =
+ new ValidationCondition(DVParser.GREATER_EQUAL);
+ public static final ValidationCondition LESS_EQUAL =
+ new ValidationCondition(DVParser.LESS_EQUAL);
+
+ /**
+ * Constructor
+ */
+ protected BaseCellFeatures()
+ {
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param the cell to copy
+ */
+ public BaseCellFeatures(BaseCellFeatures cf)
+ {
+ // The comment stuff
+ comment = cf.comment;
+ commentWidth = cf.commentWidth;
+ commentHeight = cf.commentHeight;
+
+ // The data validation stuff.
+ dropDown = cf.dropDown;
+ dataValidation = cf.dataValidation;
+
+ validationSettings = cf.validationSettings; // ?
+
+ if (cf.dvParser != null)
+ {
+ dvParser = new DVParser(cf.dvParser);
+ }
+ }
+
+ /**
+ * Accessor for the cell comment
+ */
+ protected String getComment()
+ {
+ return comment;
+ }
+
+ /**
+ * Accessor for the comment width
+ */
+ public double getCommentWidth()
+ {
+ return commentWidth;
+ }
+
+ /**
+ * Accessor for the comment height
+ */
+ public double getCommentHeight()
+ {
+ return commentHeight;
+ }
+
+ /**
+ * Called by the cell when the features are added
+ *
+ * @param wc the writable cell
+ */
+ public final void setWritableCell(CellValue wc)
+ {
+ writableCell = wc;
+ }
+
+ /**
+ * Internal method to set the cell comment. Used when reading
+ */
+ public void setReadComment(String s, double w, double h)
+ {
+ comment = s;
+ commentWidth = w;
+ commentHeight = h;
+ }
+
+ /**
+ * Internal method to set the data validation. Used when reading
+ */
+ public void setValidationSettings(DataValiditySettingsRecord dvsr)
+ {
+ Assert.verify(dvsr != null);
+
+ validationSettings = dvsr;
+ dataValidation = true;
+ }
+
+ /**
+ * Sets the cell comment
+ *
+ * @param s the comment
+ */
+ public void setComment(String s)
+ {
+ setComment(s, defaultCommentWidth, defaultCommentHeight);
+ }
+
+ /**
+ * Sets the cell comment
+ *
+ * @param s the comment
+ * @param height the height of the comment box in cells
+ * @param width the width of the comment box in cells
+ */
+ public void setComment(String s, double width, double height)
+ {
+ comment = s;
+ commentWidth = width;
+ commentHeight = height;
+
+ if (commentDrawing != null)
+ {
+ commentDrawing.setCommentText(s);
+ commentDrawing.setWidth(width);
+ commentDrawing.setWidth(height);
+ // commentDrawing is set up when trying to modify a copied cell
+ }
+ }
+
+ /**
+ * Removes the cell comment, if present
+ */
+ public void removeComment()
+ {
+ // Set the comment string to be empty
+ comment = null;
+
+ // Remove the drawing from the drawing group
+ if (commentDrawing != null)
+ {
+ // do not call DrawingGroup.remove() because comments are not present
+ // on the Workbook DrawingGroup record
+ writableCell.removeComment(commentDrawing);
+ commentDrawing = null;
+ }
+ }
+
+ /**
+ * Removes any data validation, if present
+ */
+ public void removeDataValidation()
+ {
+ // Remove the validation from the WritableSheet object if present
+ if (dataValidation)
+ {
+ writableCell.removeDataValidation();
+ }
+
+ clearValidationSettings();
+ }
+
+ /**
+ * Sets the comment drawing object
+ */
+ public final void setCommentDrawing(Comment c)
+ {
+ commentDrawing = c;
+ }
+
+ /**
+ * Accessor for the comment drawing
+ */
+ public final Comment getCommentDrawing()
+ {
+ return commentDrawing;
+ }
+
+ /**
+ * Gets the data validation list as a formula. Used only when reading
+ *
+ * @return the validation formula as a list
+ */
+ public String getDataValidationList()
+ {
+ if (validationSettings == null)
+ {
+ return null;
+ }
+
+ return validationSettings.getValidationFormula();
+ }
+
+ /**
+ * The list of items to validate for this cell. For each object in the
+ * collection, the toString() method will be called and the data entered
+ * will be validated against that string
+ *
+ * @param c the list of valid values
+ */
+ public void setDataValidationList(Collection c)
+ {
+ clearValidationSettings();
+ dvParser = new DVParser(c);
+ dropDown = true;
+ dataValidation = true;
+ }
+
+ /**
+ * The list of items to validate for this cell in the form of a cell range.
+ *
+ * @param c the list of valid values
+ */
+ public void setDataValidationRange(int col1, int r1, int col2, int r2)
+ {
+ clearValidationSettings();
+ dvParser = new DVParser(col1, r1, col2, r2);
+ dropDown = true;
+ dataValidation = true;
+ }
+
+ /**
+ * Sets the data validation based upon a named range
+ */
+ public void setDataValidationRange(String namedRange)
+ {
+ clearValidationSettings();
+ dvParser = new DVParser(namedRange);
+ dropDown = true;
+ dataValidation = true;
+ }
+
+ public void setNumberValidation(double val, ValidationCondition c)
+ {
+ clearValidationSettings();
+ dvParser = new DVParser(val, Double.NaN, c.getCondition());
+ dropDown = false;
+ dataValidation = true;
+ }
+
+ public void setNumberValidation(double val1, double val2,
+ ValidationCondition c)
+ {
+ clearValidationSettings();
+ dvParser = new DVParser(val1, val2, c.getCondition());
+ dropDown = false;
+ dataValidation = true;
+ }
+
+ /**
+ * Accessor for the data validation
+ *
+ * @return TRUE if this has a data validation associated with it,
+ FALSE otherwise
+ */
+ public boolean hasDataValidation()
+ {
+ return dataValidation;
+ }
+
+ /**
+ * Clears out any existing validation settings
+ */
+ private void clearValidationSettings()
+ {
+ validationSettings = null;
+ dvParser = null;
+ dropDown = false;
+ comboBox = null;
+ dataValidation = false;
+ }
+
+ /**
+ * Accessor for whether a drop down is required
+ *
+ * @return TRUE if this requires a drop down, FALSE otherwise
+ */
+ public boolean hasDropDown()
+ {
+ return dropDown;
+ }
+
+ /**
+ * Sets the combo box drawing object for list validations
+ *
+ * @param cb the combo box
+ */
+ public void setComboBox(ComboBox cb)
+ {
+ comboBox = cb;
+ }
+
+ /**
+ * Gets the dv parser
+ */
+ public DVParser getDVParser()
+ {
+ // straightforward - this was created as a writable cell
+ if (dvParser != null)
+ {
+ return dvParser;
+ }
+
+ // this was copied from a readable cell, and then copied again
+ if (validationSettings != null)
+ {
+ dvParser = new DVParser(validationSettings.getDVParser());
+ return dvParser;
+ }
+
+ return null; // keep the compiler happy
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/BaseCompoundFile.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/BaseCompoundFile.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/BaseCompoundFile.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,349 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Assert;
+import common.Logger;
+
+/**
+ * Contains the common data for a compound file
+ */
+public abstract class BaseCompoundFile
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(BaseCompoundFile.class);
+
+ /**
+ * The identifier at the beginning of every OLE file
+ */
+ protected static final byte[] IDENTIFIER = new byte[]
+ {(byte) 0xd0,
+ (byte) 0xcf,
+ (byte) 0x11,
+ (byte) 0xe0,
+ (byte) 0xa1,
+ (byte) 0xb1,
+ (byte) 0x1a,
+ (byte) 0xe1};
+ /**
+ */
+ protected static final int NUM_BIG_BLOCK_DEPOT_BLOCKS_POS = 0x2c;
+ /**
+ */
+ protected static final int SMALL_BLOCK_DEPOT_BLOCK_POS = 0x3c;
+ /**
+ */
+ protected static final int NUM_SMALL_BLOCK_DEPOT_BLOCKS_POS = 0x40;
+ /**
+ */
+ protected static final int ROOT_START_BLOCK_POS = 0x30;
+ /**
+ */
+ protected static final int BIG_BLOCK_SIZE = 0x200;
+ /**
+ */
+ protected static final int SMALL_BLOCK_SIZE = 0x40;
+ /**
+ */
+ protected static final int EXTENSION_BLOCK_POS = 0x44;
+ /**
+ */
+ protected static final int NUM_EXTENSION_BLOCK_POS = 0x48;
+ /**
+ */
+ protected static final int PROPERTY_STORAGE_BLOCK_SIZE = 0x80;
+ /**
+ */
+ protected static final int BIG_BLOCK_DEPOT_BLOCKS_POS = 0x4c;
+ /**
+ */
+ protected static final int SMALL_BLOCK_THRESHOLD = 0x1000;
+
+ // property storage offsets
+ /**
+ */
+ private static final int SIZE_OF_NAME_POS = 0x40;
+ /**
+ */
+ private static final int TYPE_POS = 0x42;
+ /**
+ */
+ private static final int COLOUR_POS = 0x43;
+ /**
+ */
+ private static final int PREVIOUS_POS = 0x44;
+ /**
+ */
+ private static final int NEXT_POS = 0x48;
+ /**
+ */
+ private static final int CHILD_POS = 0x4c;
+ /**
+ */
+ private static final int START_BLOCK_POS = 0x74;
+ /**
+ */
+ private static final int SIZE_POS = 0x78;
+
+ /**
+ * The standard property sets
+ */
+ public final static String ROOT_ENTRY_NAME = "Root Entry";
+ public final static String WORKBOOK_NAME = "Workbook";
+ public final static String SUMMARY_INFORMATION_NAME =
+ "\u0005SummaryInformation";
+ public final static String DOCUMENT_SUMMARY_INFORMATION_NAME =
+ "\u0005DocumentSummaryInformation";
+ public final static String COMP_OBJ_NAME =
+ "\u0001CompObj";
+ public final static String[] STANDARD_PROPERTY_SETS =
+ new String[] {ROOT_ENTRY_NAME, WORKBOOK_NAME,
+ SUMMARY_INFORMATION_NAME,
+ DOCUMENT_SUMMARY_INFORMATION_NAME};
+
+ /**
+ * Property storage types
+ */
+ public final static int NONE_PS_TYPE = 0;
+ public final static int DIRECTORY_PS_TYPE = 1;
+ public final static int FILE_PS_TYPE = 2;
+ public final static int ROOT_ENTRY_PS_TYPE = 5;
+
+
+ /**
+ * Inner class to represent the property storage sets. Access is public
+ * to allow access from the PropertySetsReader demo utility
+ */
+ public class PropertyStorage
+ {
+ /**
+ * The name of this property set
+ */
+ public String name;
+ /**
+ * The type of the property set
+ */
+ public int type;
+ /**
+ * The colour of the property set
+ */
+ public int colour;
+ /**
+ * The block number in the stream which this property sets starts at
+ */
+ public int startBlock;
+ /**
+ * The size, in bytes, of this property set
+ */
+ public int size;
+ /**
+ * The previous property set
+ */
+ public int previous;
+ /**
+ * The next property set
+ */
+ public int next;
+ /**
+ * The child for this property set
+ */
+ public int child;
+
+ /**
+ * The data that created this set
+ */
+ public byte[] data;
+
+ /**
+ * Constructs a property set
+ *
+ * @param d the bytes
+ */
+ public PropertyStorage(byte[] d)
+ {
+ data = d;
+ int nameSize = IntegerHelper.getInt(data[SIZE_OF_NAME_POS],
+ data[SIZE_OF_NAME_POS + 1]);
+
+ if (nameSize > SIZE_OF_NAME_POS)
+ {
+ logger.warn("property set name exceeds max length - truncating");
+ nameSize = SIZE_OF_NAME_POS;
+
+ }
+ type = data[TYPE_POS];
+ colour = data[COLOUR_POS];
+
+ startBlock = IntegerHelper.getInt
+ (data[START_BLOCK_POS],
+ data[START_BLOCK_POS + 1],
+ data[START_BLOCK_POS + 2],
+ data[START_BLOCK_POS + 3]);
+ size = IntegerHelper.getInt
+ (data[SIZE_POS],
+ data[SIZE_POS + 1],
+ data[SIZE_POS + 2],
+ data[SIZE_POS + 3]);
+ previous = IntegerHelper.getInt
+ (data[PREVIOUS_POS],
+ data[PREVIOUS_POS+1],
+ data[PREVIOUS_POS+2],
+ data[PREVIOUS_POS+3]);
+ next = IntegerHelper.getInt
+ (data[NEXT_POS],
+ data[NEXT_POS+1],
+ data[NEXT_POS+2],
+ data[NEXT_POS+3]);
+ child = IntegerHelper.getInt
+ (data[CHILD_POS],
+ data[CHILD_POS+1],
+ data[CHILD_POS+2],
+ data[CHILD_POS+3]);
+
+ int chars = 0;
+ if (nameSize > 2)
+ {
+ chars = (nameSize - 1) / 2;
+ }
+
+ StringBuffer n = new StringBuffer("");
+ for (int i = 0; i < chars ; i++)
+ {
+ n.append( (char) data[i * 2]);
+ }
+
+ name = n.toString();
+ }
+
+ /**
+ * Constructs an empty property set. Used when writing the file
+ *
+ * @param name the property storage name
+ */
+ public PropertyStorage(String name)
+ {
+ data = new byte[PROPERTY_STORAGE_BLOCK_SIZE];
+
+ Assert.verify(name.length() < 32);
+
+ IntegerHelper.getTwoBytes((name.length() + 1) * 2,
+ data,
+ SIZE_OF_NAME_POS);
+ // add one to the name length to allow for the null character at
+ // the end
+ for (int i = 0; i < name.length(); i++)
+ {
+ data[i * 2] = (byte) name.charAt(i);
+ }
+ }
+
+ /**
+ * Sets the type
+ *
+ * @param t the type
+ */
+ public void setType(int t)
+ {
+ type = t;
+ data[TYPE_POS] = (byte) t;
+ }
+
+ /**
+ * Sets the number of the start block
+ *
+ * @param sb the number of the start block
+ */
+ public void setStartBlock(int sb)
+ {
+ startBlock = sb;
+ IntegerHelper.getFourBytes(sb, data, START_BLOCK_POS);
+ }
+
+ /**
+ * Sets the size of the file
+ *
+ * @param s the size
+ */
+ public void setSize(int s)
+ {
+ size = s;
+ IntegerHelper.getFourBytes(s, data, SIZE_POS);
+ }
+
+ /**
+ * Sets the previous block
+ *
+ * @param prev the previous block
+ */
+ public void setPrevious(int prev)
+ {
+ previous = prev;
+ IntegerHelper.getFourBytes(prev, data, PREVIOUS_POS);
+ }
+
+ /**
+ * Sets the next block
+ *
+ * @param nxt the next block
+ */
+ public void setNext(int nxt)
+ {
+ next = nxt;
+ IntegerHelper.getFourBytes(next, data, NEXT_POS);
+ }
+
+ /**
+ * Sets the child
+ *
+ * @param dir the child
+ */
+ public void setChild(int dir)
+ {
+ child = dir;
+ IntegerHelper.getFourBytes(child, data, CHILD_POS);
+ }
+
+ /**
+ * Sets the colour
+ *
+ * @param col colour
+ */
+ public void setColour(int col)
+ {
+ colour = col == 0 ? 0 : 1;
+ data[COLOUR_POS] = (byte) colour;
+ }
+
+ }
+
+ /**
+ * Constructor
+ */
+ protected BaseCompoundFile()
+ {
+ }
+
+}
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/BuiltInFormat.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/BuiltInFormat.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/BuiltInFormat.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,176 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import jxl.format.Format;
+
+/**
+ * The excel string for the various built in formats. Used to present
+ * the cell format information back to the user
+ *
+ * The difference between this class and the various format object contained
+ * in the jxl.write package is that this object contains the Excel strings,
+ * not their java equivalents
+ */
+final class BuiltInFormat implements Format, DisplayFormat
+{
+ /**
+ * The excel format string
+ */
+ private String formatString;
+
+ /**
+ * The index
+ */
+ private int formatIndex;
+
+ /**
+ * Constructor
+ *
+ * @param s the format string
+ * @param i the format index
+ */
+ private BuiltInFormat(String s, int i)
+ {
+ formatIndex = i;
+ formatString = s;
+ }
+
+ /**
+ * Accesses the excel format string which is applied to the cell
+ * Note that this is the string that excel uses, and not the java
+ * equivalent
+ *
+ * @return the cell format string
+ */
+ public String getFormatString()
+ {
+ return formatString;
+ }
+
+ /**
+ * Accessor for the index style of this format
+ *
+ * @return the index for this format
+ */
+ public int getFormatIndex()
+ {
+ return formatIndex;
+ }
+ /**
+ * Accessor to see whether this format has been initialized
+ *
+ * @return TRUE if initialized, FALSE otherwise
+ */
+ public boolean isInitialized()
+ {
+ return true;
+ }
+ /**
+ * Initializes this format with the specified index number
+ *
+ * @param pos the position of this format record in the workbook
+ */
+ public void initialize(int pos)
+ {
+ }
+
+ /**
+ * Accessor to determine whether or not this format is built in
+ *
+ * @return TRUE if this format is a built in format, FALSE otherwise
+ */
+ public boolean isBuiltIn()
+ {
+ return true;
+ }
+
+ /**
+ * Equals method
+ *
+ * @return TRUE if the two built in formats are equal, FALSE otherwise
+ */
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+
+ if (!(o instanceof BuiltInFormat))
+ {
+ return false;
+ }
+
+ BuiltInFormat bif = (BuiltInFormat) o;
+ return (formatIndex == bif.formatIndex);
+ }
+
+ /**
+ * The list of built in formats
+ */
+ public static BuiltInFormat[] builtIns = new BuiltInFormat[0x32];
+
+ // Populate the built ins
+ static
+ {
+ builtIns[0x0] = new BuiltInFormat("", 0);
+ builtIns[0x1] = new BuiltInFormat("0", 1);
+ builtIns[0x2] = new BuiltInFormat("0.00", 2);
+ builtIns[0x3] = new BuiltInFormat("#,##0", 3);
+ builtIns[0x4] = new BuiltInFormat("#,##0.00", 4);
+ builtIns[0x5] = new BuiltInFormat("($#,##0_);($#,##0)", 5);
+ builtIns[0x6] = new BuiltInFormat("($#,##0_);[Red]($#,##0)", 6);
+ builtIns[0x7] = new BuiltInFormat("($#,##0_);[Red]($#,##0)", 7);
+ builtIns[0x8] = new BuiltInFormat("($#,##0.00_);[Red]($#,##0.00)", 8);
+ builtIns[0x9] = new BuiltInFormat("0%", 9);
+ builtIns[0xa] = new BuiltInFormat("0.00%", 10);
+ builtIns[0xb] = new BuiltInFormat("0.00E+00", 11);
+ builtIns[0xc] = new BuiltInFormat("# ?/?", 12);
+ builtIns[0xd] = new BuiltInFormat("# ??/??", 13);
+ builtIns[0xe] = new BuiltInFormat("dd/mm/yyyy", 14);
+ builtIns[0xf] = new BuiltInFormat("d-mmm-yy", 15);
+ builtIns[0x10] = new BuiltInFormat("d-mmm", 16);
+ builtIns[0x11] = new BuiltInFormat("mmm-yy", 17);
+ builtIns[0x12] = new BuiltInFormat("h:mm AM/PM", 18);
+ builtIns[0x13] = new BuiltInFormat("h:mm:ss AM/PM", 19);
+ builtIns[0x14] = new BuiltInFormat("h:mm", 20);
+ builtIns[0x15] = new BuiltInFormat("h:mm:ss", 21);
+ builtIns[0x16] = new BuiltInFormat("m/d/yy h:mm", 22);
+ builtIns[0x25] = new BuiltInFormat("(#,##0_);(#,##0)", 0x25);
+ builtIns[0x26] = new BuiltInFormat("(#,##0_);[Red](#,##0)", 0x26);
+ builtIns[0x27] = new BuiltInFormat("(#,##0.00_);(#,##0.00)", 0x27);
+ builtIns[0x28] = new BuiltInFormat("(#,##0.00_);[Red](#,##0.00)", 0x28);
+ builtIns[0x29] = new BuiltInFormat
+ ("_(*#,##0_);_(*(#,##0);_(*\"-\"_);(@_)", 0x29);
+ builtIns[0x2a] = new BuiltInFormat
+ ("_($*#,##0_);_($*(#,##0);_($*\"-\"_);(@_)", 0x2a);
+ builtIns[0x2b] = new BuiltInFormat
+ ("_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);(@_)", 0x2b);
+ builtIns[0x2c] = new BuiltInFormat
+ ("_($* #,##0.00_);_($* (#,##0.00);_($* \"-\"??_);(@_)", 0x2c);
+ builtIns[0x2d] = new BuiltInFormat("mm:ss", 0x2d);
+ builtIns[0x2e] = new BuiltInFormat("[h]mm:ss", 0x2e);
+ builtIns[0x2f] = new BuiltInFormat("mm:ss.0", 0x2f);
+ builtIns[0x30] = new BuiltInFormat("##0.0E+0", 0x30);
+ builtIns[0x31] = new BuiltInFormat("@", 0x31);
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/BuiltInName.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/BuiltInName.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/BuiltInName.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,120 @@
+/*********************************************************************
+*
+* Copyright (C) 2006 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+/**
+ * Enumeration of built in names
+ */
+public class BuiltInName
+{
+ /**
+ * The name
+ */
+ private String name;
+
+ /**
+ * The value
+ */
+ private int value;
+
+ /**
+ * The list of name
+ */
+ private static BuiltInName[] builtInNames = new BuiltInName[0];
+ /**
+ * Constructor
+ */
+ private BuiltInName(String n, int v)
+ {
+ name = n;
+ value = v;
+
+ BuiltInName[] oldnames = builtInNames;
+ builtInNames = new BuiltInName[oldnames.length + 1];
+ System.arraycopy(oldnames, 0, builtInNames, 0, oldnames.length);
+ builtInNames[oldnames.length] = this;
+ }
+
+ /**
+ * Accessor for the name
+ *
+ * @return the name
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Accessor for the value
+ *
+ * @return the value
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Gets the built in name for the value
+ */
+ public static BuiltInName getBuiltInName(int val)
+ {
+ BuiltInName ret = FILTER_DATABASE;
+ for (int i = 0 ; i < builtInNames.length; i++)
+ {
+ if (builtInNames[i].getValue() == val)
+ {
+ ret = builtInNames[i];
+ }
+ }
+ return ret;
+ }
+
+ // The list of built in names
+ public static final BuiltInName CONSOLIDATE_AREA =
+ new BuiltInName("Consolidate_Area", 0x0);
+ public static final BuiltInName AUTO_OPEN =
+ new BuiltInName("Auto_Open", 0x1);
+ public static final BuiltInName AUTO_CLOSE =
+ new BuiltInName("Auto_Open", 0x2);
+ public static final BuiltInName EXTRACT =
+ new BuiltInName("Extract", 0x3);
+ public static final BuiltInName DATABASE =
+ new BuiltInName("Database", 0x4);
+ public static final BuiltInName CRITERIA =
+ new BuiltInName("Criteria", 0x5);
+ public static final BuiltInName PRINT_AREA =
+ new BuiltInName("Print_Area", 0x6);
+ public static final BuiltInName PRINT_TITLES =
+ new BuiltInName("Print_Titles", 0x7);
+ public static final BuiltInName RECORDER =
+ new BuiltInName("Recorder", 0x8);
+ public static final BuiltInName DATA_FORM =
+ new BuiltInName("Data_Form", 0x9);
+ public static final BuiltInName AUTO_ACTIVATE =
+ new BuiltInName("Auto_Activate", 0xa);
+ public static final BuiltInName AUTO_DEACTIVATE =
+ new BuiltInName("Auto_Deactivate", 0xb);
+ public static final BuiltInName SHEET_TITLE =
+ new BuiltInName("Sheet_Title", 0xb);
+ public static final BuiltInName FILTER_DATABASE =
+ new BuiltInName("_FilterDatabase", 0xd);
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/BuiltInStyle.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/BuiltInStyle.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/BuiltInStyle.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,73 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+/**
+ * Represents a built in, rather than a user defined, style.
+ * This class is used by the FormattingRecords class when writing out the hard*
+ * coded styles
+ */
+class BuiltInStyle extends WritableRecordData
+{
+ /**
+ * The XF index of this style
+ */
+ private int xfIndex;
+ /**
+ * The reference number of this style
+ */
+ private int styleNumber;
+
+ /**
+ * Constructor
+ *
+ * @param xfind the xf index of this style
+ * @param sn the style number of this style
+ */
+ public BuiltInStyle(int xfind, int sn)
+ {
+ super(Type.STYLE);
+
+ xfIndex = xfind;
+ styleNumber = sn;
+ }
+
+ /**
+ * Abstract method implementation to get the raw byte data ready to write out
+ *
+ * @return The byte data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[4];
+
+ IntegerHelper.getTwoBytes(xfIndex, data, 0);
+
+ // Set the built in bit
+ data[1] |= 0x80;
+
+ data[2] = (byte) styleNumber;
+
+ // Set the outline level
+ data[3] = (byte) 0xff;
+
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/ByteArray.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/ByteArray.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/ByteArray.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,117 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+/**
+ * A growable array of bytes
+ */
+public class ByteArray
+{
+ /**
+ * The array grow size
+ */
+ private int growSize;
+
+ /**
+ * The current array
+ */
+ private byte[] bytes;
+
+ /**
+ * The current position
+ */
+ private int pos;
+
+ // The default grow size
+ private final static int defaultGrowSize = 1024;
+
+ /**
+ * Constructor
+ */
+ public ByteArray()
+ {
+ this(defaultGrowSize);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param gs
+ */
+ public ByteArray(int gs)
+ {
+ growSize = gs;
+ bytes = new byte[defaultGrowSize];
+ pos = 0;
+ }
+
+ /**
+ * Adds a byte onto the array
+ *
+ * @param b the byte
+ */
+ public void add(byte b)
+ {
+ checkSize(1);
+ bytes[pos] = b;
+ pos++;
+ }
+
+ /**
+ * Adds an array of bytes onto the array
+ *
+ * @param b the array of bytes
+ */
+ public void add(byte[] b)
+ {
+ checkSize(b.length);
+ System.arraycopy(b, 0, bytes, pos, b.length);
+ pos += b.length;
+ }
+
+ /**
+ * Gets the complete array
+ *
+ * @return the array
+ */
+ public byte[] getBytes()
+ {
+ byte[] returnArray = new byte[pos];
+ System.arraycopy(bytes, 0, returnArray, 0, pos);
+ return returnArray;
+ }
+
+ /**
+ * Checks to see if there is sufficient space left on the array. If not,
+ * then it grows the array
+ *
+ * @param sz the amount of bytes to add
+ */
+ private void checkSize(int sz)
+ {
+ while (pos + sz >= bytes.length)
+ {
+ // Grow the array
+ byte[] newArray = new byte[bytes.length + growSize];
+ System.arraycopy(bytes, 0, newArray, 0, pos);
+ bytes = newArray;
+ }
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/ByteData.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/ByteData.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/ByteData.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,34 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+/**
+ * Interface which provides a method for transferring chunks of binary
+ * data from one Excel file (read in) to another (written out)
+ */
+public interface ByteData
+{
+ /**
+ * Used when writing out records
+ *
+ * @return the full data to be included in the final compound file
+ */
+ public byte[] getBytes();
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/CellFinder.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/CellFinder.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/CellFinder.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,219 @@
+/**********************************************************************
+*
+* Copyright (C) 2008 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+import jxl.Sheet;
+import jxl.Cell;
+import jxl.CellType;
+import jxl.LabelCell;
+
+/**
+ * Refactorisation to provide more sophisticated find cell by contents
+ * functionality
+ */
+public class CellFinder
+{
+ private Sheet sheet;
+
+ public CellFinder(Sheet s)
+ {
+ sheet = s;
+ }
+
+ /**
+ * Gets the cell whose contents match the string passed in.
+ * If no match is found, then null is returned. The search is performed
+ * on a row by row basis, so the lower the row number, the more
+ * efficiently the algorithm will perform
+ *
+ * @param contents the string to match
+ * @param firstCol the first column within the range
+ * @param firstRow the first row of the range
+ * @param lastCol the last column within the range
+ * @param lastRow the last row within the range
+ * @param reverse indicates whether to perform a reverse search or not
+ * @return the Cell whose contents match the parameter, null if not found
+ */
+ public Cell findCell(String contents,
+ int firstCol,
+ int firstRow,
+ int lastCol,
+ int lastRow,
+ boolean reverse)
+ {
+ Cell cell = null;
+ boolean found = false;
+
+ int numCols = lastCol - firstCol;
+ int numRows = lastRow - firstRow;
+
+ int row1 = reverse ? lastRow : firstRow;
+ int row2 = reverse ? firstRow : lastRow;
+ int col1 = reverse ? lastCol : firstCol;
+ int col2 = reverse ? firstCol : lastCol;
+ int inc = reverse ? -1 : 1;
+
+ for (int i = 0; i <= numCols && found == false; i++)
+ {
+ for (int j = 0; j <= numRows && found == false; j++)
+ {
+ int curCol = col1 + i * inc;
+ int curRow = row1 + j * inc;
+ if (curCol < sheet.getColumns() && curRow < sheet.getRows())
+ {
+ Cell c = sheet.getCell(curCol, curRow);
+ if (c.getType() != CellType.EMPTY)
+ {
+ if (c.getContents().equals(contents))
+ {
+ cell = c;
+ found = true;
+ }
+ }
+ }
+ }
+ }
+
+ return cell;
+ }
+
+ /**
+ * Finds a cell within a given range of cells
+ *
+ * @param contents the string to match
+ * @return the Cell whose contents match the parameter, null if not found
+ */
+ public Cell findCell(String contents)
+ {
+ Cell cell = null;
+ boolean found = false;
+
+ for (int i = 0 ; i < sheet.getRows() && found == false; i++)
+ {
+ Cell[] row = sheet.getRow(i);
+ for (int j = 0 ; j < row.length && found == false; j++)
+ {
+ if (row[j].getContents().equals(contents))
+ {
+ cell = row[j];
+ found = true;
+ }
+ }
+ }
+
+ return cell;
+ }
+
+ /**
+ * Gets the cell whose contents match the regular expressionstring passed in.
+ * If no match is found, then null is returned. The search is performed
+ * on a row by row basis, so the lower the row number, the more
+ * efficiently the algorithm will perform
+ *
+ * @param pattern the regular expression string to match
+ * @param firstCol the first column within the range
+ * @param firstRow the first row of the range
+ * @param lastCol the last column within the range
+ * @param lastRow the last row within the range
+ * @param reverse indicates whether to perform a reverse search or not
+ * @return the Cell whose contents match the parameter, null if not found
+ */
+ public Cell findCell(Pattern pattern,
+ int firstCol,
+ int firstRow,
+ int lastCol,
+ int lastRow,
+ boolean reverse)
+ {
+ Cell cell = null;
+ boolean found = false;
+
+ int numCols = lastCol - firstCol;
+ int numRows = lastRow - firstRow;
+
+ int row1 = reverse ? lastRow : firstRow;
+ int row2 = reverse ? firstRow : lastRow;
+ int col1 = reverse ? lastCol : firstCol;
+ int col2 = reverse ? firstCol : lastCol;
+ int inc = reverse ? -1 : 1;
+
+ for (int i = 0; i <= numCols && found == false; i++)
+ {
+ for (int j = 0; j <= numRows && found == false; j++)
+ {
+ int curCol = col1 + i * inc;
+ int curRow = row1 + j * inc;
+ if (curCol < sheet.getColumns() && curRow < sheet.getRows())
+ {
+ Cell c = sheet.getCell(curCol, curRow);
+ if (c.getType() != CellType.EMPTY)
+ {
+ Matcher m = pattern.matcher(c.getContents());
+ if (m.matches())
+ {
+ cell = c;
+ found = true;
+ }
+ }
+ }
+ }
+ }
+
+ return cell;
+ }
+
+ /**
+ * Gets the cell whose contents match the string passed in.
+ * If no match is found, then null is returned. The search is performed
+ * on a row by row basis, so the lower the row number, the more
+ * efficiently the algorithm will perform. This method differs
+ * from the findCell methods in that only cells with labels are
+ * queried - all numerical cells are ignored. This should therefore
+ * improve performance.
+ *
+ * @param contents the string to match
+ * @return the Cell whose contents match the paramter, null if not found
+ */
+ public LabelCell findLabelCell(String contents)
+ {
+ LabelCell cell = null;
+ boolean found = false;
+
+ for (int i = 0; i < sheet.getRows() && !found; i++)
+ {
+ Cell[] row = sheet.getRow(i);
+ for (int j = 0; j < row.length && !found; j++)
+ {
+ if ((row[j].getType() == CellType.LABEL ||
+ row[j].getType() == CellType.STRING_FORMULA) &&
+ row[j].getContents().equals(contents))
+ {
+ cell = (LabelCell) row[j];
+ found = true;
+ }
+ }
+ }
+
+ return cell;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/CellReferenceHelper.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/CellReferenceHelper.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/CellReferenceHelper.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,349 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Logger;
+
+import jxl.biff.formula.ExternalSheet;
+
+/**
+ * A helper to transform between excel cell references and
+ * sheet:column:row notation
+ * Because this function will be called when generating a string
+ * representation of a formula, the cell reference will merely
+ * be appened to the string buffer instead of returning a full
+ * blooded string, for performance reasons
+ */
+public final class CellReferenceHelper
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(CellReferenceHelper.class);
+
+ /**
+ * The character which indicates whether a reference is fixed
+ */
+ private static final char fixedInd='$';
+
+ /**
+ * The character which indicates the sheet name terminator
+ */
+ private static final char sheetInd = '!';
+
+ /**
+ * Constructor to prevent instantiation
+ */
+ private CellReferenceHelper()
+ {
+ }
+
+ /**
+ * Gets the cell reference
+ *
+ * @param column
+ * @param row
+ * @param buf
+ */
+ public static void getCellReference(int column, int row, StringBuffer buf)
+ {
+ // Put the column letter into the buffer
+ getColumnReference(column, buf);
+
+ // Add the row into the buffer
+ buf.append(Integer.toString(row+1));
+ }
+
+ /**
+ * Overloaded method which prepends $ for absolute reference
+ *
+ * @param column
+ * @param colabs TRUE if the column reference is absolute
+ * @param row
+ * @param rowabs TRUE if the row reference is absolute
+ * @param buf
+ */
+ public static void getCellReference(int column, boolean colabs,
+ int row, boolean rowabs,
+ StringBuffer buf)
+ {
+ if (colabs)
+ {
+ buf.append(fixedInd);
+ }
+
+ // Put the column letter into the buffer
+ getColumnReference(column, buf);
+
+ if (rowabs)
+ {
+ buf.append(fixedInd);
+ }
+
+ // Add the row into the buffer
+ buf.append(Integer.toString(row+1));
+ }
+
+ /**
+ * Gets the column letter corresponding to the 0-based column number
+ *
+ * @param column the column number
+ * @return the letter for that column number
+ */
+ public static String getColumnReference(int column)
+ {
+ StringBuffer buf = new StringBuffer();
+ getColumnReference(column, buf);
+ return buf.toString();
+ }
+
+ /**
+ * Gets the column letter corresponding to the 0-based column number
+ *
+ * @param column the column number
+ * @param buf the string buffer in which to write the column letter
+ */
+ public static void getColumnReference(int column, StringBuffer buf)
+ {
+ int v = column/26;
+ int r = column%26;
+
+ StringBuffer tmp = new StringBuffer();
+ while (v != 0)
+ {
+ char col = (char) ('A' + r) ;
+
+ tmp.append(col);
+
+ r = v%26 - 1; // subtract one because only rows >26 preceded by A
+ v = v/26;
+ }
+
+ char col = (char) ('A' + r) ;
+ tmp.append(col);
+
+ // Insert into the proper string buffer in reverse order
+ for (int i = tmp.length() - 1; i >= 0; i--)
+ {
+ buf.append(tmp.charAt(i));
+ }
+ }
+
+ /**
+ * Gets the fully qualified cell reference given the column, row
+ * external sheet reference etc
+ *
+ * @param sheet
+ * @param column
+ * @param row
+ * @param workbook
+ * @param buf
+ */
+ public static void getCellReference
+ (int sheet, int column, int row,
+ ExternalSheet workbook, StringBuffer buf)
+ {
+ // buf.append('\''); - quotes now added by WorkbookParser
+ String name = workbook.getExternalSheetName(sheet);
+ buf.append(StringHelper.replace(name, "\'", "\'\'"));
+ // buf.append('\'');
+ buf.append(sheetInd);
+ getCellReference(column, row, buf);
+ }
+
+ /**
+ * Gets the fully qualified cell reference given the column, row
+ * external sheet reference etc
+ *
+ * @param sheet
+ * @param column
+ * @param colabs TRUE if the column is an absolute reference
+ * @param row
+ * @param rowabs TRUE if the row is an absolute reference
+ * @param workbook
+ * @param buf
+ */
+ public static void getCellReference
+ (int sheet, int column, boolean colabs,
+ int row, boolean rowabs,
+ ExternalSheet workbook, StringBuffer buf)
+ {
+ // WorkbookParser now appends quotes and escapes apostrophes
+ String name = workbook.getExternalSheetName(sheet);
+ buf.append(name);
+ buf.append(sheetInd);
+ getCellReference(column, colabs, row, rowabs, buf);
+ }
+
+ /**
+ * Gets the fully qualified cell reference given the column, row
+ * external sheet reference etc
+ *
+ * @param sheet
+ * @param column
+ * @param row
+ * @param workbook
+ * @return the cell reference in the form 'Sheet 1'!A1
+ */
+ public static String getCellReference
+ (int sheet, int column, int row,
+ ExternalSheet workbook)
+ {
+ StringBuffer sb = new StringBuffer();
+ getCellReference(sheet, column, row, workbook, sb);
+ return sb.toString();
+ }
+
+
+ /**
+ * Gets the cell reference for the specified column and row
+ *
+ * @param column
+ * @param row
+ * @return
+ */
+ public static String getCellReference(int column, int row)
+ {
+ StringBuffer buf = new StringBuffer();
+ getCellReference(column, row, buf);
+ return buf.toString();
+ }
+
+ /**
+ * Gets the columnn number of the string cell reference
+ *
+ * @param s the string to parse
+ * @return the column portion of the cell reference
+ */
+ public static int getColumn(String s)
+ {
+ int colnum = 0;
+ int numindex = getNumberIndex(s);
+
+ String s2 = s.toUpperCase();
+
+ int startPos = s.lastIndexOf(sheetInd) + 1;
+ if (s.charAt(startPos) == fixedInd)
+ {
+ startPos++;
+ }
+
+ int endPos = numindex;
+ if (s.charAt(numindex - 1) == fixedInd)
+ {
+ endPos--;
+ }
+
+ for (int i = startPos; i < endPos ; i++)
+ {
+
+ if (i != startPos)
+ {
+ colnum = (colnum+1) * 26;
+ }
+ colnum += (int) s2.charAt(i) - (int) 'A';
+ }
+
+ return colnum;
+ }
+
+ /**
+ * Gets the row number of the cell reference
+ */
+ public static int getRow(String s)
+ {
+ try
+ {
+ return (Integer.parseInt(s.substring(getNumberIndex(s))) - 1);
+ }
+ catch (NumberFormatException e)
+ {
+ logger.warn(e, e);
+ return 0xffff;
+ }
+ }
+
+ /**
+ * Finds the position where the first number occurs in the string
+ */
+ private static int getNumberIndex(String s)
+ {
+ // Find the position of the first number
+ boolean numberFound = false;
+ int pos = s.lastIndexOf(sheetInd) + 1;
+ char c = '\0';
+
+ while (!numberFound && pos < s.length() )
+ {
+ c = s.charAt(pos);
+
+ if (c >= '0' && c <= '9')
+ {
+ numberFound = true;
+ }
+ else
+ {
+ pos++;
+ }
+ }
+
+ return pos;
+ }
+
+ /**
+ * Sees if the column component is relative or not
+ *
+ * @param s
+ * @return TRUE if the column is relative, FALSE otherwise
+ */
+ public static boolean isColumnRelative(String s)
+ {
+ return s.charAt(0) != fixedInd;
+ }
+
+ /**
+ * Sees if the row component is relative or not
+ *
+ * @param s
+ * @return TRUE if the row is relative, FALSE otherwise
+ */
+ public static boolean isRowRelative(String s)
+ {
+ return s.charAt(getNumberIndex(s) - 1) != fixedInd;
+ }
+
+ /**
+ * Gets the sheet name from the cell reference string
+ *
+ * @param ref
+ * @return the sheet reference
+ */
+ public static String getSheet(String ref)
+ {
+ int sheetPos = ref.lastIndexOf(sheetInd);
+ if (sheetPos == -1)
+ {
+ return "";
+ }
+
+ return ref.substring(0, sheetPos);
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/CellReferenceHelper.java2
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/CellReferenceHelper.java2,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/CellReferenceHelper.java2 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,209 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import jxl.biff.formula.ExternalSheet;
+
+/**
+ * A helper to transform between excel cell references and
+ * sheet:column:row notation
+ * Because this function will be called when generating a string
+ * representation of a formula, the cell reference will merely
+ * be appened to the string buffer instead of returning a full
+ * blooded string, for performance reasons
+ */
+public final class CellReferenceHelper
+{
+ /**
+ * The character which indicates whether a reference is fixed
+ */
+ private static final char fixedInd='$';
+
+ /**
+ * Constructor to prevent instantiation
+ */
+ private CellReferenceHelper()
+ {
+ }
+
+ public static void getCellReference(int column, int row, StringBuffer buf)
+ {
+ int v = column/26;
+ int r = column%26;
+
+ StringBuffer tmp = new StringBuffer();
+ while (v != 0)
+ {
+ char col = (char) ((int) 'A' + r) ;
+
+ tmp.append(col);
+
+ r = v%26 - 1; // subtract one because only rows >26 preceded by A
+ v = v/26;
+ }
+
+ char col = (char) ((int) 'A' + r) ;
+ tmp.append(col);
+
+ // Insert into the proper string buffer in reverse order
+ for (int i = tmp.length() - 1; i >= 0; i--)
+ {
+ buf.append(tmp.charAt(i));
+ }
+
+ buf.append(Integer.toString(row+1));
+ }
+
+ /**
+ * Gets the fully qualified cell reference given the column, row
+ * external sheet reference etc
+ *
+ * @param sheet
+ * @param column
+ * @param row
+ * @param workbook
+ * @param buf
+ */
+ public static void getCellReference
+ (int sheet, int column, int row,
+ ExternalSheet workbook, StringBuffer buf)
+ {
+ buf.append(workbook.getExternalSheetName(sheet));
+ buf.append('!');
+ getCellReference(column, row, buf);
+ }
+
+ /**
+ * Gets the cell reference for the specified column and row
+ *
+ * @param column
+ * @param row
+ * @return
+ */
+ public static String getCellReference(int column, int row)
+ {
+ StringBuffer buf = new StringBuffer();
+ getCellReference(column, row, buf);
+ return buf.toString();
+ }
+
+ /**
+ * Gets the columnn number of the string cell reference
+ *
+ * @param s the string to parse
+ * @return the column portion of the cell reference
+ */
+ public static int getColumn(String s)
+ {
+ int colnum = 0;
+ int numindex = getNumberIndex(s);
+
+ String s2 = s.toUpperCase();
+
+ int startPos = 0;
+ if (s.charAt(0) == fixedInd)
+ {
+ startPos = 1;
+ }
+
+ int endPos = numindex;
+ if (s.charAt(numindex - 1) == fixedInd)
+ {
+ endPos--;
+ }
+
+ for (int i = startPos; i < endPos ; i++)
+ {
+
+ if (i != startPos)
+ {
+ colnum = (colnum+1) * 26;
+ }
+ colnum += (int) s2.charAt(i) - (int) 'A';
+ }
+
+ return colnum;
+ }
+
+ /**
+ * Gets the row number of the cell reference
+ */
+ public static int getRow(String s)
+ {
+ try
+ {
+ return (Integer.parseInt(s.substring(getNumberIndex(s))) - 1);
+ }
+ catch (NumberFormatException e)
+ {
+ System.err.println("Warning: " + e.toString());
+ return 0xffff;
+ }
+ }
+
+ /**
+ * Finds the position where the first number occurs in the string
+ */
+ private static int getNumberIndex(String s)
+ {
+ // Find the position of the first number
+ boolean numberFound = false;
+ int pos = 0;
+ char c = '\0';
+
+ while (!numberFound && pos < s.length() )
+ {
+ c = s.charAt(pos);
+
+ if (c >= '0' && c <= '9')
+ {
+ numberFound = true;
+ }
+ else
+ {
+ pos++;
+ }
+ }
+
+ return pos;
+ }
+
+ /**
+ * Sees if the column component is relative or not
+ *
+ * @param s
+ * @return TRUE if the column is relative, FALSE otherwise
+ */
+ public static boolean isColumnRelative(String s)
+ {
+ return s.charAt(0) != fixedInd;
+ }
+
+ /**
+ * Sees if the row component is relative or not
+ *
+ * @param s
+ * @return TRUE if the row is relative, FALSE otherwise
+ */
+ public static boolean isRowRelative(String s)
+ {
+ return s.charAt(getNumberIndex(s) - 1) != fixedInd;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/ConditionalFormat.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/ConditionalFormat.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/ConditionalFormat.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,125 @@
+/*********************************************************************
+*
+* Copyright (C) 2007 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import jxl.WorkbookSettings;
+import jxl.biff.formula.ExternalSheet;
+import jxl.write.biff.File;
+
+/**
+ * Class containing the CONDFMT and CF records for conditionally formatting
+ * a cell
+ */
+public class ConditionalFormat
+{
+ /**
+ * The range of the format
+ */
+ private ConditionalFormatRangeRecord range;
+
+ /**
+ * The format conditions
+ */
+ private ArrayList conditions;
+
+ /**
+ * Constructor
+ */
+ public ConditionalFormat(ConditionalFormatRangeRecord cfrr)
+ {
+ range = cfrr;
+ conditions = new ArrayList();
+ }
+
+ /**
+ * Adds a condition
+ *
+ * @param cond the condition
+ */
+ public void addCondition(ConditionalFormatRecord cond)
+ {
+ conditions.add(cond);
+ }
+
+ /**
+ * Inserts a blank column into this spreadsheet. If the column is out of
+ * range of the columns in the sheet, then no action is taken
+ *
+ * @param col the column to insert
+ */
+ public void insertColumn(int col)
+ {
+ range.insertColumn(col);
+ }
+
+ /**
+ * Removes a column from this spreadsheet. If the column is out of range
+ * of the columns in the sheet, then no action is taken
+ *
+ * @param col the column to remove
+ */
+ public void removeColumn(int col)
+ {
+ range.removeColumn(col);
+ }
+
+ /**
+ * Removes a row from this spreadsheet. If the row is out of
+ * range of the columns in the sheet, then no action is taken
+ *
+ * @param row the row to remove
+ */
+ public void removeRow(int row)
+ {
+ range.removeRow(row);
+ }
+
+ /**
+ * Inserts a blank row into this spreadsheet. If the row is out of range
+ * of the rows in the sheet, then no action is taken
+ *
+ * @param row the row to insert
+ */
+ public void insertRow(int row)
+ {
+ range.insertRow(row);
+ }
+
+ /**
+ * Writes out the data validation
+ *
+ * @exception IOException
+ * @param outputFile the output file
+ */
+ public void write(File outputFile) throws IOException
+ {
+ outputFile.write(range);
+
+ for (Iterator i = conditions.iterator(); i.hasNext();)
+ {
+ ConditionalFormatRecord cfr = (ConditionalFormatRecord) i.next();
+ outputFile.write(cfr);
+ }
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/ConditionalFormatRangeRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/ConditionalFormatRangeRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/ConditionalFormatRangeRecord.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,391 @@
+/*********************************************************************
+*
+* Copyright (C) 2007 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Logger;
+
+import jxl.read.biff.Record;
+
+/**
+ * Range information for conditional formatting
+ */
+public class ConditionalFormatRangeRecord extends WritableRecordData
+{
+ // The logger
+ private static Logger logger =
+ Logger.getLogger(ConditionalFormatRangeRecord.class);
+
+ /**
+ * The enclosing range
+ */
+ private Range enclosingRange;
+
+ /**
+ * The discrete ranges
+ */
+ private Range[] ranges;
+
+ /**
+ * The number of ranges
+ */
+ private int numRanges;
+
+ /**
+ * Initialized flag
+ */
+ private boolean initialized;
+
+ /**
+ * Modified flag
+ */
+ private boolean modified;
+
+ /**
+ * The data
+ */
+ private byte[] data;
+
+ private static class Range
+ {
+ public int firstRow;
+ public int firstColumn;
+ public int lastRow;
+ public int lastColumn;
+ public boolean modified;
+
+ public Range()
+ {
+ modified = false;
+ }
+
+ /**
+ * Inserts a blank column into this spreadsheet. If the column is out of
+ * range of the columns in the sheet, then no action is taken
+ *
+ * @param col the column to insert
+ */
+ public void insertColumn(int col)
+ {
+ if (col > lastColumn)
+ {
+ return;
+ }
+
+ if (col <= firstColumn)
+ {
+ firstColumn++;
+ modified = true;
+ }
+
+ if (col <= lastColumn)
+ {
+ lastColumn++;
+ modified = true;
+ }
+ }
+
+ /**
+ * Removes a column from this spreadsheet. If the column is out of range
+ * of the columns in the sheet, then no action is taken
+ *
+ * @param col the column to remove
+ */
+ public void removeColumn(int col)
+ {
+ if (col > lastColumn)
+ {
+ return;
+ }
+
+ if (col < firstColumn)
+ {
+ firstColumn--;
+ modified = true;
+ }
+
+ if (col <= lastColumn)
+ {
+ lastColumn--;
+ modified = true;
+ }
+ }
+
+ /**
+ * Removes a row from this spreadsheet. If the row is out of
+ * range of the columns in the sheet, then no action is taken
+ *
+ * @param row the row to remove
+ */
+ public void removeRow(int row)
+ {
+ if (row > lastRow)
+ {
+ return;
+ }
+
+ if (row < firstRow)
+ {
+ firstRow--;
+ modified = true;
+ }
+
+ if (row <= lastRow)
+ {
+ lastRow--;
+ modified = true;
+ }
+ }
+
+ /**
+ * Inserts a blank row into this spreadsheet. If the row is out of range
+ * of the rows in the sheet, then no action is taken
+ *
+ * @param row the row to insert
+ */
+ public void insertRow(int row)
+ {
+ if (row > lastRow)
+ {
+ return;
+ }
+
+ if (row <= firstRow)
+ {
+ firstRow++;
+ modified = true;
+ }
+
+ if (row <= lastRow)
+ {
+ lastRow++;
+ modified = true;
+ }
+ }
+
+ }
+
+ /**
+ * Constructor
+ */
+ public ConditionalFormatRangeRecord(Record t)
+ {
+ super(t);
+
+ initialized = false;
+ modified = false;
+ data = getRecord().getData();
+ }
+
+ /**
+ * Initialization function
+ */
+ private void initialize()
+ {
+ enclosingRange = new Range();
+ enclosingRange.firstRow = IntegerHelper.getInt(data[4], data[5]);
+ enclosingRange.lastRow = IntegerHelper.getInt(data[6], data[7]);
+ enclosingRange.firstColumn = IntegerHelper.getInt(data[8], data[9]);
+ enclosingRange.lastColumn = IntegerHelper.getInt(data[10], data[11]);
+ numRanges = IntegerHelper.getInt(data[12], data[13]);
+ ranges = new Range[numRanges];
+
+ int pos = 14;
+
+ for (int i = 0; i < numRanges; i++)
+ {
+ ranges[i] = new Range();
+ ranges[i].firstRow = IntegerHelper.getInt(data[pos], data[pos+1]);
+ ranges[i].lastRow = IntegerHelper.getInt(data[pos+2], data[pos+3]);
+ ranges[i].firstColumn = IntegerHelper.getInt(data[pos+4], data[pos+5]);
+ ranges[i].lastColumn = IntegerHelper.getInt(data[pos+6], data[pos+7]);
+ pos += 8;
+ }
+
+ initialized = true;
+ }
+
+ /**
+ * Inserts a blank column into this spreadsheet. If the column is out of
+ * range of the columns in the sheet, then no action is taken
+ *
+ * @param col the column to insert
+ */
+ public void insertColumn(int col)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ enclosingRange.insertColumn(col);
+ if (enclosingRange.modified)
+ {
+ modified = true;
+ }
+
+ for (int i = 0 ; i < ranges.length ; i++)
+ {
+ ranges[i].insertColumn(col);
+
+ if (ranges[i].modified)
+ {
+ modified = true;
+ }
+ }
+
+ return;
+ }
+
+ /**
+ * Inserts a blank column into this spreadsheet. If the column is out of
+ * range of the columns in the sheet, then no action is taken
+ *
+ * @param col the column to insert
+ */
+ public void removeColumn(int col)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ enclosingRange.removeColumn(col);
+ if (enclosingRange.modified)
+ {
+ modified = true;
+ }
+
+ for (int i = 0 ; i < ranges.length ; i++)
+ {
+ ranges[i].removeColumn(col);
+
+ if (ranges[i].modified)
+ {
+ modified = true;
+ }
+ }
+
+ return;
+ }
+
+ /**
+ * Removes a row from this spreadsheet. If the row is out of
+ * range of the columns in the sheet, then no action is taken
+ *
+ * @param row the row to remove
+ */
+ public void removeRow(int row)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ enclosingRange.removeRow(row);
+ if (enclosingRange.modified)
+ {
+ modified = true;
+ }
+
+ for (int i = 0 ; i < ranges.length ; i++)
+ {
+ ranges[i].removeRow(row);
+
+ if (ranges[i].modified)
+ {
+ modified = true;
+ }
+ }
+
+ return;
+ }
+
+ /**
+ * Inserts a blank row into this spreadsheet. If the row is out of range
+ * of the rows in the sheet, then no action is taken
+ *
+ * @param row the row to insert
+ */
+ public void insertRow(int row)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ enclosingRange.insertRow(row);
+ if (enclosingRange.modified)
+ {
+ modified = true;
+ }
+
+ for (int i = 0 ; i < ranges.length ; i++)
+ {
+ ranges[i].insertRow(row);
+
+ if (ranges[i].modified)
+ {
+ modified = true;
+ }
+ }
+
+ return;
+ }
+
+
+ /**
+ * Retrieves the data for output to binary file
+ *
+ * @return the data to be written
+ */
+ public byte[] getData()
+ {
+ if (!modified)
+ {
+ return data;
+ }
+
+ byte[] d = new byte[14 + ranges.length * 8];
+
+ // Copy in the original information
+ System.arraycopy(data, 0, d, 0, 4);
+
+ // Create the new range
+ IntegerHelper.getTwoBytes(enclosingRange.firstRow, d, 4);
+ IntegerHelper.getTwoBytes(enclosingRange.lastRow, d, 6);
+ IntegerHelper.getTwoBytes(enclosingRange.firstColumn, d, 8);
+ IntegerHelper.getTwoBytes(enclosingRange.lastColumn, d, 10);
+
+ IntegerHelper.getTwoBytes(numRanges, d, 12);
+
+ int pos = 14;
+ for (int i = 0 ; i < ranges.length ; i++)
+ {
+ IntegerHelper.getTwoBytes(ranges[i].firstRow, d, pos);
+ IntegerHelper.getTwoBytes(ranges[i].lastRow, d, pos+2);
+ IntegerHelper.getTwoBytes(ranges[i].firstColumn, d, pos+4);
+ IntegerHelper.getTwoBytes(ranges[i].lastColumn, d, pos+6);
+ pos += 8;
+ }
+
+ return d;
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/ConditionalFormatRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/ConditionalFormatRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/ConditionalFormatRecord.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,60 @@
+/*********************************************************************
+*
+* Copyright (C) 2007 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Logger;
+
+import jxl.read.biff.Record;
+
+/**
+ * The conditional format conditions
+ */
+public class ConditionalFormatRecord extends WritableRecordData
+{
+ // the logger
+ private static Logger logger =
+ Logger.getLogger(ConditionalFormatRecord.class);
+
+ /**
+ * The data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ */
+ public ConditionalFormatRecord(Record t)
+ {
+ super(t);
+
+ data = getRecord().getData();
+ }
+
+ /**
+ * Retrieves the data for output to binary file
+ *
+ * @return the data to be written
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/ContinueRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/ContinueRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/ContinueRecord.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,79 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import jxl.read.biff.Record;
+
+/**
+ * A continue record - only used explicitly in special circumstances, as
+ * the general continuation record is handled directly by the records
+ */
+public class ContinueRecord extends WritableRecordData
+{
+ /**
+ * The data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param t the raw bytes
+ */
+ public ContinueRecord(Record t)
+ {
+ super(t);
+ data = t.getData();
+ }
+
+ /**
+ * Constructor invoked when creating continue records
+ *
+ * @param d the data
+ */
+ public ContinueRecord(byte[] d)
+ {
+ super(Type.CONTINUE);
+ data = d;
+ }
+
+ /**
+ * Accessor for the binary data - used when copying
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+
+ /**
+ * Accessor for the record. Used when forcibly changing this record
+ * into another type, notably a drawing record, as sometimes Excel appears
+ * to switch to writing Continue records instead of MsoDrawing records
+ *
+ * @return the record
+ */
+ public Record getRecord()
+ {
+ return super.getRecord();
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/CountryCode.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/CountryCode.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/CountryCode.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,167 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Logger;
+
+/**
+ * Enumeration type for the excel country codes
+ */
+public class CountryCode
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(CountryCode.class);
+
+ /**
+ * The country code
+ */
+ private int value;
+
+ /**
+ * The ISO 3166 two letter country mnemonic (as used by the Locale class)
+ */
+ private String code;
+
+ /**
+ * The long description
+ */
+ private String description;
+
+ /**
+ * The array of country codes
+ */
+ private static CountryCode[] codes = new CountryCode[0];
+
+ /**
+ * Constructor
+ */
+ private CountryCode(int v, String c, String d)
+ {
+ value = v;
+ code = c;
+ description = d;
+
+ CountryCode[] newcodes = new CountryCode[codes.length+1];
+ System.arraycopy(codes, 0, newcodes, 0, codes.length);
+ newcodes[codes.length] = this;
+ codes = newcodes;
+ }
+
+ /**
+ * Constructor used to create an arbitrary code with a specified value.
+ * Doesn't add the latest value to the static array
+ */
+ private CountryCode(int v)
+ {
+ value = v;
+ description = "Arbitrary";
+ code = "??";
+ }
+
+ /**
+ * Accessor for the excel value
+ *
+ * @return the excel value
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Accessor for the string
+ *
+ * @return the two character iso 3166 string
+ */
+ public String getCode()
+ {
+ return code;
+ }
+
+ /**
+ * Gets the country code for the given two character mnemonic string
+ */
+ public static CountryCode getCountryCode(String s)
+ {
+ if (s == null || s.length() != 2)
+ {
+ logger.warn("Please specify two character ISO 3166 country code");
+ return USA;
+ }
+
+ CountryCode code = UNKNOWN;
+ for (int i = 0 ; i < codes.length && code == UNKNOWN ; i++)
+ {
+ if (codes[i].code.equals(s))
+ {
+ code = codes[i];
+ }
+ }
+
+ return code;
+ }
+
+ /**
+ * Creates an arbitrary country code with the specified value. Used
+ * when copying sheets, and the country code isn't initialized as part
+ * of the static data below
+ */
+ public static CountryCode createArbitraryCode(int i)
+ {
+ return new CountryCode(i);
+ }
+
+ // The country codes
+ public final static CountryCode USA = new CountryCode(0x1, "US", "USA");
+ public final static CountryCode CANADA =
+ new CountryCode(0x2, "CA", "Canada");
+ public final static CountryCode GREECE =
+ new CountryCode(0x1e, "GR", "Greece");
+ public final static CountryCode NETHERLANDS =
+ new CountryCode(0x1f, "NE", "Netherlands");
+ public final static CountryCode BELGIUM =
+ new CountryCode(0x20, "BE", "Belgium");
+ public final static CountryCode FRANCE =
+ new CountryCode(0x21, "FR", "France");
+ public final static CountryCode SPAIN = new CountryCode(0x22, "ES", "Spain");
+ public final static CountryCode ITALY = new CountryCode(0x27, "IT", "Italy");
+ public final static CountryCode SWITZERLAND =
+ new CountryCode(0x29, "CH", "Switzerland");
+ public final static CountryCode UK =
+ new CountryCode(0x2c, "UK", "United Kingdowm");
+ public final static CountryCode DENMARK =
+ new CountryCode(0x2d, "DK", "Denmark");
+ public final static CountryCode SWEDEN =
+ new CountryCode(0x2e, "SE", "Sweden");
+ public final static CountryCode NORWAY =
+ new CountryCode(0x2f, "NO", "Norway");
+ public final static CountryCode GERMANY =
+ new CountryCode(0x31, "DE", "Germany");
+ public final static CountryCode PHILIPPINES =
+ new CountryCode(0x3f, "PH", "Philippines");
+ public final static CountryCode CHINA =
+ new CountryCode(0x56, "CN", "China");
+ public final static CountryCode INDIA =
+ new CountryCode(0x5b, "IN", "India");
+ public final static CountryCode UNKNOWN =
+ new CountryCode(0xffff, "??", "Unknown");
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/DVParser.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/DVParser.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/DVParser.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,924 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Assert;
+import common.Logger;
+
+import java.text.MessageFormat;
+import java.text.DecimalFormat;
+import java.util.Collection;
+import java.util.Iterator;
+
+import jxl.WorkbookSettings;
+import jxl.biff.formula.ExternalSheet;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+
+/**
+ * Class which parses the binary data associated with Data Validity (DV)
+ * setting
+ */
+public class DVParser
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(DVParser.class);
+
+ // DV Type
+ public static class DVType
+ {
+ private int value;
+ private String desc;
+
+ private static DVType[] types = new DVType[0];
+
+ DVType(int v, String d)
+ {
+ value = v;
+ desc = d;
+ DVType[] oldtypes = types;
+ types = new DVType[oldtypes.length+1];
+ System.arraycopy(oldtypes, 0, types, 0, oldtypes.length);
+ types[oldtypes.length] = this;
+ }
+
+ static DVType getType(int v)
+ {
+ DVType found = null;
+ for (int i = 0 ; i < types.length && found == null ; i++)
+ {
+ if (types[i].value == v)
+ {
+ found = types[i];
+ }
+ }
+ return found;
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+
+ public String getDescription()
+ {
+ return desc;
+ }
+ }
+
+ // Error Style
+ public static class ErrorStyle
+ {
+ private int value;
+
+ private static ErrorStyle[] types = new ErrorStyle[0];
+
+ ErrorStyle(int v)
+ {
+ value = v;
+ ErrorStyle[] oldtypes = types;
+ types = new ErrorStyle[oldtypes.length+1];
+ System.arraycopy(oldtypes, 0, types, 0, oldtypes.length);
+ types[oldtypes.length] = this;
+ }
+
+ static ErrorStyle getErrorStyle(int v)
+ {
+ ErrorStyle found = null;
+ for (int i = 0 ; i < types.length && found == null ; i++)
+ {
+ if (types[i].value == v)
+ {
+ found = types[i];
+ }
+ }
+ return found;
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+ }
+
+ // Conditions
+ public static class Condition
+ {
+ private int value;
+ private MessageFormat format;
+
+ private static Condition[] types = new Condition[0];
+
+ Condition(int v, String pattern)
+ {
+ value = v;
+ format = new MessageFormat(pattern);
+ Condition[] oldtypes = types;
+ types = new Condition[oldtypes.length+1];
+ System.arraycopy(oldtypes, 0, types, 0, oldtypes.length);
+ types[oldtypes.length] = this;
+ }
+
+ static Condition getCondition(int v)
+ {
+ Condition found = null;
+ for (int i = 0 ; i < types.length && found == null ; i++)
+ {
+ if (types[i].value == v)
+ {
+ found = types[i];
+ }
+ }
+ return found;
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+
+ public String getConditionString(String s1, String s2)
+ {
+ return format.format(new String[] {s1, s2});
+ }
+ }
+
+ // The values
+ public static final DVType ANY = new DVType(0, "any");
+ public static final DVType INTEGER = new DVType(1, "int");
+ public static final DVType DECIMAL = new DVType(2, "dec");
+ public static final DVType LIST = new DVType(3, "list");
+ public static final DVType DATE = new DVType(4, "date");
+ public static final DVType TIME = new DVType(5, "time");
+ public static final DVType TEXT_LENGTH = new DVType(6, "strlen");
+ public static final DVType FORMULA = new DVType(7, "form");
+
+ // The error styles
+ public static final ErrorStyle STOP = new ErrorStyle(0);
+ public static final ErrorStyle WARNING = new ErrorStyle(1);
+ public static final ErrorStyle INFO = new ErrorStyle(2);
+
+ // The conditions
+ public static final Condition BETWEEN = new Condition(0, "{0} <= x <= {1}");
+ public static final Condition NOT_BETWEEN =
+ new Condition(1, "!({0} <= x <= {1}");
+ public static final Condition EQUAL = new Condition(2, "x == {0}");
+ public static final Condition NOT_EQUAL = new Condition(3, "x != {0}");
+ public static final Condition GREATER_THAN = new Condition(4, "x > {0}");
+ public static final Condition LESS_THAN = new Condition(5, "x < {0}");
+ public static final Condition GREATER_EQUAL = new Condition(6, "x >= {0}");
+ public static final Condition LESS_EQUAL = new Condition(7, "x <= {0}");
+
+ // The masks
+ private static final int STRING_LIST_GIVEN_MASK = 0x80;
+ private static final int EMPTY_CELLS_ALLOWED_MASK = 0x100;
+ private static final int SUPPRESS_ARROW_MASK = 0x200;
+ private static final int SHOW_PROMPT_MASK = 0x40000;
+ private static final int SHOW_ERROR_MASK = 0x80000;
+
+ // The decimal format
+ private static DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.#");
+
+ // The maximum string length for a data validation list
+ private static final int MAX_VALIDATION_LIST_LENGTH = 254;
+
+ /**
+ * The type
+ */
+ private DVType type;
+
+ /**
+ * The error style
+ */
+ private ErrorStyle errorStyle;
+
+ /**
+ * The condition
+ */
+ private Condition condition;
+
+ /**
+ * String list option
+ */
+ private boolean stringListGiven;
+
+ /**
+ * Empty cells allowed
+ */
+ private boolean emptyCellsAllowed;
+
+ /**
+ * Suppress arrow
+ */
+ private boolean suppressArrow;
+
+ /**
+ * Show prompt
+ */
+ private boolean showPrompt;
+
+ /**
+ * Show error
+ */
+ private boolean showError;
+
+ /**
+ * The title of the prompt box
+ */
+ private String promptTitle;
+
+ /**
+ * The title of the error box
+ */
+ private String errorTitle;
+
+ /**
+ * The text of the prompt box
+ */
+ private String promptText;
+
+ /**
+ * The text of the error box
+ */
+ private String errorText;
+
+ /**
+ * The first formula
+ */
+ private FormulaParser formula1;
+
+ /**
+ * The first formula string
+ */
+ private String formula1String;
+
+ /**
+ * The second formula
+ */
+ private FormulaParser formula2;
+
+ /**
+ * The second formula string
+ */
+ private String formula2String;
+
+ /**
+ * The column number of the cell at the top left of the range
+ */
+ private int column1;
+
+ /**
+ * The row number of the cell at the top left of the range
+ */
+ private int row1;
+
+ /**
+ * The column index of the cell at the bottom right
+ */
+ private int column2;
+
+ /**
+ * The row index of the cell at the bottom right
+ */
+ private int row2;
+
+ /**
+ * Constructor
+ */
+ public DVParser(byte[] data,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ WorkbookSettings ws) throws FormulaException
+ {
+ Assert.verify(nt != null);
+
+ int options = IntegerHelper.getInt(data[0], data[1], data[2], data[3]);
+
+ int typeVal = options & 0xf;
+ type = DVType.getType(typeVal);
+
+ int errorStyleVal = (options & 0x70) >> 4;
+ errorStyle = ErrorStyle.getErrorStyle(errorStyleVal);
+
+ int conditionVal = (options & 0xf00000) >> 20;
+ condition = Condition.getCondition(conditionVal);
+
+ stringListGiven = (options & STRING_LIST_GIVEN_MASK) != 0;
+ emptyCellsAllowed = (options & EMPTY_CELLS_ALLOWED_MASK) != 0;
+ suppressArrow = (options & SUPPRESS_ARROW_MASK) != 0;
+ showPrompt = (options & SHOW_PROMPT_MASK) != 0;
+ showError = (options & SHOW_ERROR_MASK) != 0;
+
+ int pos = 4;
+ int length = IntegerHelper.getInt(data[pos], data[pos+1]);
+ if (length > 0 && data[pos + 2] == 0)
+ {
+ promptTitle = StringHelper.getString(data, length, pos + 3, ws);
+ pos += length + 3;
+ }
+ else if (length > 0)
+ {
+ promptTitle = StringHelper.getUnicodeString(data, length, pos + 3);
+ pos += length * 2 + 3;
+ }
+ else
+ {
+ pos += 3;
+ }
+
+ length = IntegerHelper.getInt(data[pos], data[pos+1]);
+ if (length > 0 && data[pos + 2] == 0)
+ {
+ errorTitle = StringHelper.getString(data, length, pos + 3, ws);
+ pos += length + 3;
+ }
+ else if (length > 0)
+ {
+ errorTitle = StringHelper.getUnicodeString(data, length, pos + 3);
+ pos += length * 2 + 3;
+ }
+ else
+ {
+ pos += 3;
+ }
+
+ length = IntegerHelper.getInt(data[pos], data[pos+1]);
+ if (length > 0 && data[pos + 2] == 0)
+ {
+ promptText = StringHelper.getString(data, length, pos + 3, ws);
+ pos += length + 3;
+ }
+ else if (length > 0)
+ {
+ promptText = StringHelper.getUnicodeString(data, length, pos + 3);
+ pos += length * 2 + 3;
+ }
+ else
+ {
+ pos += 3;
+ }
+
+ length = IntegerHelper.getInt(data[pos], data[pos+1]);
+ if (length > 0 && data[pos + 2] == 0)
+ {
+ errorText = StringHelper.getString(data, length, pos + 3, ws);
+ pos += length + 3;
+ }
+ else if (length > 0)
+ {
+ errorText = StringHelper.getUnicodeString(data, length, pos + 3);
+ pos += length * 2 + 3;
+ }
+ else
+ {
+ pos += 3;
+ }
+
+ int formula1Length = IntegerHelper.getInt(data[pos], data[pos+1]);
+ pos += 4;
+ int formula1Pos = pos;
+ pos += formula1Length;
+
+ int formula2Length = IntegerHelper.getInt(data[pos], data[pos+1]);
+ pos += 4;
+ int formula2Pos = pos;
+ pos += formula2Length;
+
+ pos += 2;
+
+ row1 = IntegerHelper.getInt(data[pos], data[pos+1]);
+ pos += 2;
+
+ row2 = IntegerHelper.getInt(data[pos], data[pos+1]);
+ pos += 2;
+
+ column1 = IntegerHelper.getInt(data[pos], data[pos+1]);
+ pos += 2;
+
+ column2 = IntegerHelper.getInt(data[pos], data[pos+1]);
+ pos += 2;
+
+ // Do the formulas
+
+ // First, create a temporary blank cell for any formula relative
+ // references
+ EmptyCell tmprt = new EmptyCell(column1, row1);
+
+ if (formula1Length != 0)
+ {
+ byte[] tokens = new byte[formula1Length];
+ System.arraycopy(data, formula1Pos, tokens, 0, formula1Length);
+ formula1 = new FormulaParser(tokens, tmprt, es, nt,ws);
+ formula1.parse();
+ }
+
+ if (formula2Length != 0)
+ {
+ byte[] tokens = new byte[formula2Length];
+ System.arraycopy(data, formula2Pos, tokens, 0, formula2Length);
+ formula2 = new FormulaParser(tokens, tmprt, es, nt, ws);
+ formula2.parse();
+ }
+ }
+
+ /**
+ * Constructor called when creating a data validation from the API
+ */
+ public DVParser(Collection strings)
+ {
+ type = LIST;
+ errorStyle = STOP;
+ condition = BETWEEN;
+
+ // the options
+ stringListGiven = true;
+ emptyCellsAllowed = true;
+ suppressArrow = false;
+ showPrompt = true;
+ showError = true;
+
+ promptTitle = "\0";
+ errorTitle = "\0";
+ promptText = "\0";
+ errorText = "\0";
+ if (strings.size() == 0)
+ {
+ logger.warn("no validation strings - ignoring");
+ }
+
+ Iterator i = strings.iterator();
+ StringBuffer formulaString = new StringBuffer();
+
+ formulaString.append(i.next().toString());
+ while (i.hasNext())
+ {
+ formulaString.append('\0');
+ formulaString.append(' ');
+ formulaString.append(i.next().toString());
+ }
+
+ // If the formula string exceeds
+ // the maximum validation list length, then truncate and stop there
+ if (formulaString.length() > MAX_VALIDATION_LIST_LENGTH)
+ {
+ logger.warn("Validation list exceeds maximum number of characters - " +
+ "truncating");
+ formulaString.delete(MAX_VALIDATION_LIST_LENGTH,
+ formulaString.length());
+ }
+
+ // Put the string in quotes
+ formulaString.insert(0, '\"');
+ formulaString.append('\"');
+ formula1String = formulaString.toString();
+ }
+
+ /**
+ * Constructor called when creating a data validation from the API
+ */
+ public DVParser(String namedRange)
+ {
+ type = LIST;
+ errorStyle = STOP;
+ condition = BETWEEN;
+
+ // the options
+ stringListGiven = false;
+ emptyCellsAllowed = true;
+ suppressArrow = false;
+ showPrompt = true;
+ showError = true;
+
+ promptTitle = "\0";
+ errorTitle = "\0";
+ promptText = "\0";
+ errorText = "\0";
+ formula1String = namedRange;
+ }
+
+ /**
+ * Constructor called when creating a data validation from the API
+ */
+ public DVParser(int c1, int r1, int c2, int r2)
+ {
+ type = LIST;
+ errorStyle = STOP;
+ condition = BETWEEN;
+
+ // the options
+ stringListGiven = false;
+ emptyCellsAllowed = true;
+ suppressArrow = false;
+ showPrompt = true;
+ showError = true;
+
+ promptTitle = "\0";
+ errorTitle = "\0";
+ promptText = "\0";
+ errorText = "\0";
+ StringBuffer formulaString = new StringBuffer();
+ CellReferenceHelper.getCellReference(c1,r1,formulaString);
+ formulaString.append(':');
+ CellReferenceHelper.getCellReference(c2,r2,formulaString);
+ formula1String = formulaString.toString();
+ }
+
+ /**
+ * Constructor called when creating a data validation from the API
+ */
+ public DVParser(double val1, double val2, Condition c)
+ {
+ type = DECIMAL;
+ errorStyle = STOP;
+ condition = c;
+
+ // the options
+ stringListGiven = false;
+ emptyCellsAllowed = true;
+ suppressArrow = false;
+ showPrompt = true;
+ showError = true;
+
+ promptTitle = "\0";
+ errorTitle = "\0";
+ promptText = "\0";
+ errorText = "\0";
+ formula1String = DECIMAL_FORMAT.format(val1);
+
+ if (!Double.isNaN(val2))
+ {
+ formula2String = DECIMAL_FORMAT.format(val2);
+ }
+ }
+
+ /**
+ * Constructor called when doing a cell deep copy
+ */
+ public DVParser(DVParser copy)
+ {
+ type = copy.type;
+ errorStyle = copy.errorStyle;
+ condition = copy.condition;
+ stringListGiven = copy.stringListGiven;
+ emptyCellsAllowed = copy.emptyCellsAllowed;
+ suppressArrow = copy.suppressArrow;
+ showPrompt = copy.showPrompt;
+ showError = copy.showError;
+ promptTitle = copy.promptTitle;
+ promptText = copy.promptText;
+ errorTitle = copy.errorTitle;
+ errorText = copy.errorText;
+
+ // Don't copy the formula parsers - just take their string equivalents
+ if (copy.formula1String != null)
+ {
+ formula1String = copy.formula1String;
+ formula2String = copy.formula2String;
+ }
+ else
+ {
+ try
+ {
+ formula1String = copy.formula1.getFormula();
+ formula2String = (copy.formula2 != null) ?
+ copy.formula2.getFormula() : null;
+ }
+ catch (FormulaException e)
+ {
+ logger.warn("Cannot parse validation formula: " + e.getMessage());
+ }
+ }
+ // Don't copy the cell references - these will be added later
+ }
+
+ /**
+ * Gets the data
+ */
+ public byte[] getData()
+ {
+ // Compute the length of the data
+ byte[] f1Bytes = formula1 != null ? formula1.getBytes() : new byte[0];
+ byte[] f2Bytes = formula2 != null ? formula2.getBytes() : new byte[0];
+ int dataLength =
+ 4 + // the options
+ promptTitle.length() * 2 + 2 + // the prompt title
+ errorTitle.length() * 2 + 2 + // the error title
+ promptText.length() * 2 + 2 + // the prompt text
+ errorText.length() * 2 + 2 + // the error text
+ f1Bytes.length + 2 + // first formula
+ f2Bytes.length + 2 + // second formula
+ + 4 + // unused bytes
+ 10; // cell range
+
+ byte[] data = new byte[dataLength];
+
+ // The position
+ int pos = 0;
+
+ // The options
+ int options = 0;
+ options |= type.getValue();
+ options |= errorStyle.getValue() << 4;
+ options |= condition.getValue() << 20;
+
+ if (stringListGiven)
+ {
+ options |= STRING_LIST_GIVEN_MASK;
+ }
+
+ if (emptyCellsAllowed)
+ {
+ options |= EMPTY_CELLS_ALLOWED_MASK;
+ }
+
+ if (suppressArrow)
+ {
+ options |= SUPPRESS_ARROW_MASK;
+ }
+
+ if (showPrompt)
+ {
+ options |= SHOW_PROMPT_MASK;
+ }
+
+ if (showError)
+ {
+ options |= SHOW_ERROR_MASK;
+ }
+
+ // The text
+ IntegerHelper.getFourBytes(options, data, pos);
+ pos += 4;
+
+ IntegerHelper.getTwoBytes(promptTitle.length(), data, pos);
+ pos += 2;
+
+ StringHelper.getUnicodeBytes(promptTitle, data, pos);
+ pos += promptTitle.length() * 2;
+
+ IntegerHelper.getTwoBytes(errorTitle.length(), data, pos);
+ pos += 2;
+
+ StringHelper.getUnicodeBytes(errorTitle, data, pos);
+ pos += errorTitle.length() * 2;
+
+ IntegerHelper.getTwoBytes(promptText.length(), data, pos);
+ pos += 2;
+
+ StringHelper.getUnicodeBytes(promptText, data, pos);
+ pos += promptText.length() * 2;
+
+ IntegerHelper.getTwoBytes(errorText.length(), data, pos);
+ pos += 2;
+
+ StringHelper.getUnicodeBytes(errorText, data, pos);
+ pos += errorText.length() * 2;
+
+ // Formula 1
+ IntegerHelper.getTwoBytes(f1Bytes.length, data, pos);
+ pos += 4;
+
+ System.arraycopy(f1Bytes, 0, data, pos, f1Bytes.length);
+ pos += f1Bytes.length;
+
+ // Formula 2
+ IntegerHelper.getTwoBytes(f2Bytes.length, data, pos);
+ pos += 4;
+
+ System.arraycopy(f2Bytes, 0, data, pos, f2Bytes.length);
+ pos += f2Bytes.length;
+
+ // The cell ranges
+ IntegerHelper.getTwoBytes(1, data, pos);
+ pos += 2;
+
+ IntegerHelper.getTwoBytes(row1, data, pos);
+ pos += 2;
+
+ IntegerHelper.getTwoBytes(row2, data, pos);
+ pos += 2;
+
+ IntegerHelper.getTwoBytes(column1, data, pos);
+ pos += 2;
+
+ IntegerHelper.getTwoBytes(column2, data, pos);
+ pos += 2;
+
+ return data;
+ }
+
+ /**
+ * Inserts a row
+ *
+ * @param row the row to insert
+ */
+ public void insertRow(int row)
+ {
+ if (formula1 != null)
+ {
+ formula1.rowInserted(0, row, true);
+ }
+
+ if (formula2 != null)
+ {
+ formula2.rowInserted(0, row, true);
+ }
+
+ if (row1 >= row)
+ {
+ row1++;
+ }
+
+ if (row2 >= row)
+ {
+ row2++;
+ }
+ }
+
+ /**
+ * Inserts a column
+ *
+ * @param col the column to insert
+ */
+ public void insertColumn(int col)
+ {
+ if (formula1 != null)
+ {
+ formula1.columnInserted(0, col, true);
+ }
+
+ if (formula2 != null)
+ {
+ formula2.columnInserted(0, col, true);
+ }
+
+ if (column1 >= col)
+ {
+ column1++;
+ }
+
+ if (column2 >= col)
+ {
+ column2++;
+ }
+ }
+
+ /**
+ * Removes a row
+ *
+ * @param row the row to insert
+ */
+ public void removeRow(int row)
+ {
+ if (formula1 != null)
+ {
+ formula1.rowRemoved(0, row, true);
+ }
+
+ if (formula2 != null)
+ {
+ formula2.rowRemoved(0, row, true);
+ }
+
+ if (row1 > row)
+ {
+ row1--;
+ }
+
+ if (row2 >= row)
+ {
+ row2--;
+ }
+ }
+
+ /**
+ * Removes a column
+ *
+ * @param col the row to remove
+ */
+ public void removeColumn(int col)
+ {
+ if (formula1 != null)
+ {
+ formula1.columnRemoved(0, col, true);
+ }
+
+ if (formula2 != null)
+ {
+ formula2.columnRemoved(0, col, true);
+ }
+
+ if (column1 > col)
+ {
+ column1--;
+ }
+
+ if (column2 >= col)
+ {
+ column2--;
+ }
+ }
+
+ /**
+ * Accessor for first column
+ *
+ * @return the first column
+ */
+ public int getFirstColumn()
+ {
+ return column1;
+ }
+
+ /**
+ * Accessor for the last column
+ *
+ * @return the last column
+ */
+ public int getLastColumn()
+ {
+ return column2;
+ }
+
+ /**
+ * Accessor for first row
+ *
+ * @return the first row
+ */
+ public int getFirstRow()
+ {
+ return row1;
+ }
+
+ /**
+ * Accessor for the last row
+ *
+ * @return the last row
+ */
+ public int getLastRow()
+ {
+ return row2;
+ }
+
+ /**
+ * Gets the formula present in the validation
+ *
+ * @return the validation formula as a string
+ * @exception FormulaException
+ */
+ String getValidationFormula() throws FormulaException
+ {
+ if (type == LIST)
+ {
+ return formula1.getFormula();
+ }
+
+ String s1 = formula1.getFormula();
+ String s2 = formula2 != null ? formula2.getFormula() : null;
+ return condition.getConditionString(s1, s2) +
+ "; x " + type.getDescription();
+ }
+
+ /**
+ * Called by the cell value when the cell features are added to the sheet
+ */
+ public void setCell(int col, int row,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ WorkbookSettings ws) throws FormulaException
+ {
+ row1 = row;
+ row2 = row;
+ column1 = col;
+ column2 = col;
+
+ formula1 = new FormulaParser(formula1String,
+ es, nt, ws);
+ formula1.parse();
+
+ if (formula2String != null)
+ {
+ formula2 = new FormulaParser(formula2String,
+ es, nt, ws);
+ formula2.parse();
+ }
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/DValParser.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/DValParser.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/DValParser.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,162 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+
+/**
+ * Class which parses the binary data associated with Data Validity (DVal)
+ * setting
+ */
+public class DValParser
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(DValParser.class);
+
+ // The option masks
+ private static int PROMPT_BOX_VISIBLE_MASK = 0x1;
+ private static int PROMPT_BOX_AT_CELL_MASK = 0x2;
+ private static int VALIDITY_DATA_CACHED_MASK = 0x4;
+
+ /**
+ * Prompt box visible
+ */
+ private boolean promptBoxVisible;
+
+ /**
+ * Empty cells allowed
+ */
+ private boolean promptBoxAtCell;
+
+ /**
+ * Cell validity data cached in following DV records
+ */
+ private boolean validityDataCached;
+
+ /**
+ * The number of following DV records
+ */
+ private int numDVRecords;
+
+ /**
+ * The object id of the associated down arrow
+ */
+ private int objectId;
+
+ /**
+ * Constructor
+ */
+ public DValParser(byte[] data)
+ {
+ int options = IntegerHelper.getInt(data[0], data[1]);
+
+ promptBoxVisible = (options & PROMPT_BOX_VISIBLE_MASK) != 0;
+ promptBoxAtCell = (options & PROMPT_BOX_AT_CELL_MASK) != 0;
+ validityDataCached = (options & VALIDITY_DATA_CACHED_MASK) != 0;
+
+ objectId = IntegerHelper.getInt(data[10], data[11], data[12], data[13]);
+ numDVRecords = IntegerHelper.getInt(data[14], data[15],
+ data[16], data[17]);
+ }
+
+ /**
+ * Constructor
+ */
+ public DValParser(int objid, int num)
+ {
+ objectId = objid;
+ numDVRecords = num;
+ validityDataCached = true;
+ }
+
+ /**
+ * Gets the data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[18];
+
+ int options = 0;
+
+ if (promptBoxVisible)
+ {
+ options |= PROMPT_BOX_VISIBLE_MASK;
+ }
+
+ if (promptBoxAtCell)
+ {
+ options |= PROMPT_BOX_AT_CELL_MASK;
+ }
+
+ if (validityDataCached)
+ {
+ options |= VALIDITY_DATA_CACHED_MASK;
+ }
+
+ IntegerHelper.getTwoBytes(options, data, 0);
+
+ IntegerHelper.getFourBytes(objectId, data, 10);
+
+ IntegerHelper.getFourBytes(numDVRecords, data, 14);
+
+ return data;
+ }
+
+ /**
+ * Called when a remove row or column results in one of DV records being
+ * removed
+ */
+ public void dvRemoved()
+ {
+ numDVRecords--;
+ }
+
+ /**
+ * Accessor for the number of DV records
+ *
+ * @return the number of DV records for this list
+ */
+ public int getNumberOfDVRecords()
+ {
+ return numDVRecords;
+ }
+
+ /**
+ * Accessor for the object id
+ *
+ * @return the object id
+ */
+ public int getObjectId()
+ {
+ return objectId;
+ }
+
+ /**
+ * Called when adding a DV record on a copied DVal
+ */
+ public void dvAdded()
+ {
+ numDVRecords++;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/DataValidation.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/DataValidation.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/DataValidation.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,320 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.formula.ExternalSheet;
+import jxl.write.biff.File;
+
+
+/**
+ * Class which encapsulates a data validation (typically in the form of a
+ * dropdown list box)
+ */
+public class DataValidation
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(DataValidation.class);
+
+ /**
+ * The data validity list
+ */
+ private DataValidityListRecord validityList;
+
+ /**
+ * The data validity record
+ */
+ private ArrayList validitySettings;
+
+ /**
+ * Handle to the workbook
+ */
+ private WorkbookMethods workbook;
+
+ /**
+ * Handle to the external sheet
+ */
+ private ExternalSheet externalSheet;
+
+ /**
+ * Handle to the workbook settings
+ */
+ private WorkbookSettings workbookSettings;
+
+ /**
+ * The object id of the combo box used for drop downs
+ */
+ private int comboBoxObjectId;
+
+ /**
+ * Indicates whether this was copied
+ */
+ private boolean copied;
+
+ public static final int DEFAULT_OBJECT_ID = 0xffffffff;
+
+ /**
+ * Constructor
+ */
+ public DataValidation(DataValidityListRecord dvlr)
+ {
+ validityList = dvlr;
+ validitySettings = new ArrayList(validityList.getNumberOfSettings());
+ copied = false;
+ }
+
+ /**
+ * Constructor used to create writable data validations
+ */
+ public DataValidation(int objId,
+ ExternalSheet es,
+ WorkbookMethods wm,
+ WorkbookSettings ws )
+ {
+ workbook = wm;
+ externalSheet = es;
+ workbookSettings = ws;
+ validitySettings = new ArrayList();
+ comboBoxObjectId = objId;
+ copied = false;
+ }
+
+ /**
+ * Copy constructor used to copy from read to write
+ */
+ public DataValidation(DataValidation dv,
+ ExternalSheet es,
+ WorkbookMethods wm,
+ WorkbookSettings ws )
+ {
+ workbook = wm;
+ externalSheet = es;
+ workbookSettings = ws;
+ copied = true;
+ validityList = new DataValidityListRecord(dv.getDataValidityList());
+
+ validitySettings = new ArrayList();
+ DataValiditySettingsRecord[] settings = dv.getDataValiditySettings();
+
+ for (int i = 0; i < settings.length ; i++)
+ {
+ validitySettings.add(new DataValiditySettingsRecord(settings[i],
+ externalSheet,
+ workbook,
+ workbookSettings));
+ }
+ }
+
+ /**
+ * Adds a new settings object to this data validation
+ */
+ public void add(DataValiditySettingsRecord dvsr)
+ {
+ validitySettings.add(dvsr);
+ dvsr.setDataValidation(this);
+
+ if (copied)
+ {
+ // adding a writable dv record to a copied validity list
+ Assert.verify(validityList != null);
+ validityList.dvAdded();
+ }
+ }
+
+ /**
+ * Accessor for the validity list. Used when copying sheets
+ */
+ public DataValidityListRecord getDataValidityList()
+ {
+ return validityList;
+ }
+
+ /**
+ * Accessor for the validity settings. Used when copying sheets
+ */
+ public DataValiditySettingsRecord[] getDataValiditySettings()
+ {
+ DataValiditySettingsRecord[] dvlr = new DataValiditySettingsRecord[0];
+ return (DataValiditySettingsRecord[]) validitySettings.toArray(dvlr);
+ }
+
+ /**
+ * Writes out the data validation
+ *
+ * @exception IOException
+ * @param outputFile the output file
+ */
+ public void write(File outputFile) throws IOException
+ {
+ if (validityList == null)
+ {
+ DValParser dvp = new DValParser(comboBoxObjectId,
+ validitySettings.size());
+ validityList = new DataValidityListRecord(dvp);
+ }
+
+ if (!validityList.hasDVRecords())
+ {
+ return;
+ }
+
+ outputFile.write(validityList);
+
+ for (Iterator i = validitySettings.iterator(); i.hasNext() ; )
+ {
+ DataValiditySettingsRecord dvsr = (DataValiditySettingsRecord) i.next();
+ outputFile.write(dvsr);
+ }
+ }
+
+ /**
+ * Inserts a row
+ *
+ * @param row the inserted row
+ */
+ public void insertRow(int row)
+ {
+ for (Iterator i = validitySettings.iterator(); i.hasNext() ; )
+ {
+ DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next();
+ dv.insertRow(row);
+ }
+ }
+
+ /**
+ * Inserts a row
+ *
+ * @param row the inserted row
+ */
+ public void removeRow(int row)
+ {
+ for (Iterator i = validitySettings.iterator(); i.hasNext() ; )
+ {
+ DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next();
+
+ if (dv.getFirstRow() == row && dv.getLastRow() == row)
+ {
+ i.remove();
+ validityList.dvRemoved();
+ }
+ else
+ {
+ dv.removeRow(row);
+ }
+ }
+ }
+
+ /**
+ * Inserts a column
+ *
+ * @param col the inserted column
+ */
+ public void insertColumn(int col)
+ {
+ for (Iterator i = validitySettings.iterator(); i.hasNext() ; )
+ {
+ DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next();
+ dv.insertColumn(col);
+ }
+ }
+
+ /**
+ * Removes a column
+ *
+ * @param col the inserted column
+ */
+ public void removeColumn(int col)
+ {
+ for (Iterator i = validitySettings.iterator(); i.hasNext() ; )
+ {
+ DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next();
+
+ if (dv.getFirstColumn() == col && dv.getLastColumn() == col)
+ {
+ i.remove();
+ validityList.dvRemoved();
+ }
+ else
+ {
+ dv.removeColumn(col);
+ }
+ }
+ }
+
+ /**
+ * Removes the data validation for a specific cell
+ *
+ * @param col the column
+ * @param row the row
+ */
+ public void removeDataValidation (int col, int row)
+ {
+ for (Iterator i = validitySettings.iterator(); i.hasNext() ; )
+ {
+ DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next();
+
+ if (dv.getFirstColumn() == col && dv.getLastColumn() == col &&
+ dv.getFirstRow() == row && dv.getLastRow() == row)
+ {
+ i.remove();
+ validityList.dvRemoved();
+ break;
+ }
+ }
+ }
+
+ /**
+ * Used during the copy process to retrieve the validity settings for
+ * a particular cell
+ */
+ public DataValiditySettingsRecord getDataValiditySettings(int col, int row)
+ {
+ boolean found = false;
+ DataValiditySettingsRecord foundRecord = null;
+ for (Iterator i = validitySettings.iterator(); i.hasNext() && !found;)
+ {
+ DataValiditySettingsRecord dvsr = (DataValiditySettingsRecord) i.next();
+ if (dvsr.getFirstColumn() == col && dvsr.getFirstRow() == row)
+ {
+ found = true;
+ foundRecord = dvsr;
+ }
+ }
+
+ return foundRecord;
+ }
+
+ /**
+ * Accessor for the combo box, used when copying sheets
+ */
+ public int getComboBoxObjectId()
+ {
+ return comboBoxObjectId;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/DataValidityListRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/DataValidityListRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/DataValidityListRecord.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,163 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import jxl.read.biff.Record;
+
+/**
+ * Record containing the list of data validation settings for a given sheet
+ */
+public class DataValidityListRecord extends WritableRecordData
+{
+
+ /**
+ * The number of settings records associated with this list
+ */
+ private int numSettings;
+
+ /**
+ * The object id of the associated down arrow
+ */
+ private int objectId;
+
+ /**
+ * The dval parser
+ */
+ private DValParser dvalParser;
+
+ /**
+ * The data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ */
+ public DataValidityListRecord(Record t)
+ {
+ super(t);
+
+ data = getRecord().getData();
+ objectId = IntegerHelper.getInt(data[10], data[11], data[12], data[13]);
+ numSettings = IntegerHelper.getInt(data[14], data[15], data[16], data[17]);
+ }
+
+ /**
+ * Constructor called when generating a data validity list from the API
+ */
+ public DataValidityListRecord(DValParser dval)
+ {
+ super(Type.DVAL);
+
+ dvalParser = dval;
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param dvlr the record copied from a read only sheet
+ */
+ DataValidityListRecord(DataValidityListRecord dvlr)
+ {
+ super(Type.DVAL);
+
+ data = dvlr.getData();
+ }
+
+ /**
+ * Accessor for the number of settings records associated with this list
+ */
+ int getNumberOfSettings()
+ {
+ return numSettings;
+ }
+
+ /**
+ * Retrieves the data for output to binary file
+ *
+ * @return the data to be written
+ */
+ public byte[] getData()
+ {
+ if (dvalParser == null)
+ {
+ return data;
+ }
+
+ return dvalParser.getData();
+ }
+
+ /**
+ * Called when a remove row or column results in one of DV records being
+ * removed
+ */
+ void dvRemoved()
+ {
+ if (dvalParser == null)
+ {
+ dvalParser = new DValParser(data);
+ }
+
+ dvalParser.dvRemoved();
+ }
+
+ /**
+ * Called when a writable DV record is added to a copied validity list
+ */
+ void dvAdded()
+ {
+ if (dvalParser == null)
+ {
+ dvalParser = new DValParser(data);
+ }
+
+ dvalParser.dvAdded();
+ }
+
+ /**
+ * Accessor for the number of DV records
+ *
+ * @return the number of DV records for this list
+ */
+ public boolean hasDVRecords()
+ {
+ if (dvalParser == null)
+ {
+ return true;
+ }
+
+ return dvalParser.getNumberOfDVRecords() > 0;
+ }
+
+ /**
+ * Accessor for the object id
+ *
+ * @return the object id
+ */
+ public int getObjectId()
+ {
+ if (dvalParser == null)
+ {
+ return objectId;
+ }
+
+ return dvalParser.getObjectId();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/DataValiditySettingsRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/DataValiditySettingsRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/DataValiditySettingsRecord.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,322 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.formula.ExternalSheet;
+import jxl.biff.formula.FormulaException;
+import jxl.read.biff.Record;
+
+/**
+ * Data validity settings
+ */
+public class DataValiditySettingsRecord extends WritableRecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger =
+ Logger.getLogger(DataValiditySettingsRecord.class);
+
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * The reader
+ */
+ private DVParser dvParser;
+
+ /**
+ * Handle to the workbook
+ */
+ private WorkbookMethods workbook;
+
+ /**
+ * Handle to the externalSheet
+ */
+ private ExternalSheet externalSheet;
+
+ /**
+ * Handle to the workbook settings
+ */
+ private WorkbookSettings workbookSettings;
+
+ /**
+ * Handle to the data validation record
+ */
+ private DataValidation dataValidation;
+
+ /**
+ * Constructor
+ */
+ public DataValiditySettingsRecord(Record t,
+ ExternalSheet es,
+ WorkbookMethods wm,
+ WorkbookSettings ws)
+ {
+ super(t);
+
+ data = t.getData();
+ externalSheet = es;
+ workbook = wm;
+ workbookSettings = ws;
+ }
+
+ /**
+ * Copy constructor
+ */
+ DataValiditySettingsRecord(DataValiditySettingsRecord dvsr)
+ {
+ super(Type.DV);
+
+ data = dvsr.getData();
+ }
+
+ /**
+ * Constructor
+ *
+ * @param dvsr the record copied from a writable sheet
+ */
+ DataValiditySettingsRecord(DataValiditySettingsRecord dvsr,
+ ExternalSheet es,
+ WorkbookMethods w,
+ WorkbookSettings ws)
+ {
+ super(Type.DV);
+
+ workbook = w;
+ externalSheet = es;
+ workbookSettings = ws;
+
+ Assert.verify(w != null);
+ Assert.verify(es != null);
+
+ data = new byte[dvsr.data.length];
+ System.arraycopy(dvsr.data, 0, data, 0, data.length);
+ }
+
+ /**
+ * Constructor called when the API creates a writable data validation
+ *
+ * @param dvsr the record copied from a writable sheet
+ */
+ public DataValiditySettingsRecord(DVParser dvp)
+ {
+ super(Type.DV);
+ dvParser = dvp;
+ }
+
+ /**
+ * Initializes the dvParser
+ */
+ private void initialize()
+ {
+ try
+ {
+ if (dvParser == null)
+ {
+ dvParser = new DVParser(data, externalSheet,
+ workbook, workbookSettings);
+ }
+ }
+ catch (FormulaException e)
+ {
+ logger.warn("Cannot read drop down range " + e.getMessage());
+ }
+ }
+
+ /**
+ * Retrieves the data for output to binary file
+ *
+ * @return the data to be written
+ */
+ public byte[] getData()
+ {
+ if (dvParser == null)
+ {
+ return data;
+ }
+
+ return dvParser.getData();
+ }
+
+ /**
+ * Inserts a row
+ *
+ * @param row the row to insert
+ */
+ public void insertRow(int row)
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ dvParser.insertRow(row);
+ }
+
+ /**
+ * Removes a row
+ *
+ * @param row the row to insert
+ */
+ public void removeRow(int row)
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ dvParser.removeRow(row);
+ }
+
+ /**
+ * Inserts a row
+ *
+ * @param col the row to insert
+ */
+ public void insertColumn(int col)
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ dvParser.insertColumn(col);
+ }
+
+ /**
+ * Removes a column
+ *
+ * @param col the row to insert
+ */
+ public void removeColumn(int col)
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ dvParser.removeColumn(col);
+ }
+
+ /**
+ * Accessor for first column
+ *
+ * @return the first column
+ */
+ public int getFirstColumn()
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ return dvParser.getFirstColumn();
+ }
+
+ /**
+ * Accessor for the last column
+ *
+ * @return the last column
+ */
+ public int getLastColumn()
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ return dvParser.getLastColumn();
+ }
+
+ /**
+ * Accessor for first row
+ *
+ * @return the first row
+ */
+ public int getFirstRow()
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ return dvParser.getFirstRow();
+ }
+
+ /**
+ * Accessor for the last row
+ *
+ * @return the last row
+ */
+ public int getLastRow()
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ return dvParser.getLastRow();
+ }
+
+ /**
+ * Sets the handle to the data validation record
+ *
+ * @param dv the data validation
+ */
+ void setDataValidation(DataValidation dv)
+ {
+ dataValidation = dv;
+ }
+
+ /**
+ * Gets the DVParser. This is used when doing a deep copy of cells
+ * on the writable side of things
+ */
+ DVParser getDVParser()
+ {
+ return dvParser;
+ }
+
+ public String getValidationFormula()
+ {
+ try
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ return dvParser.getValidationFormula();
+ }
+ catch (FormulaException e)
+ {
+ logger.warn("Cannot read drop down range " + e.getMessage());
+ return "";
+ }
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/DisplayFormat.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/DisplayFormat.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/DisplayFormat.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,55 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+/**
+ * The interface implemented by the various number and date format styles.
+ * The methods on this interface are called internally when generating a
+ * spreadsheet
+ */
+public interface DisplayFormat
+{
+ /**
+ * Accessor for the index style of this format
+ *
+ * @return the index for this format
+ */
+ public int getFormatIndex();
+ /**
+ * Accessor to see whether this format has been initialized
+ *
+ * @return TRUE if initialized, FALSE otherwise
+ */
+ public boolean isInitialized();
+
+ /**
+ * Initializes this format with the specified index number
+ *
+ * @param pos the position of this format record in the workbook
+ */
+ public void initialize(int pos);
+
+ /**
+ * Accessor to determine whether or not this format is built in
+ *
+ * @return TRUE if this format is a built in format, FALSE otherwise
+ */
+ public boolean isBuiltIn();
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/DoubleHelper.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/DoubleHelper.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/DoubleHelper.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,89 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+/**
+ * Class to help handle doubles
+ */
+public class DoubleHelper
+{
+ /**
+ * Private constructor to prevent instantiation
+ */
+ private DoubleHelper()
+ {
+ }
+
+ /**
+ * Gets the IEEE value from the byte array passed in
+ *
+ * @param pos the position in the data block which contains the double value
+ * @param data the data block containing the raw bytes
+ * @return the double value converted from the raw data
+ */
+ public static double getIEEEDouble(byte[] data, int pos)
+ {
+ int num1 = IntegerHelper.getInt(data[pos], data[pos + 1],
+ data[pos + 2], data[pos + 3]);
+ int num2 = IntegerHelper.getInt(data[pos + 4], data[pos + 5],
+ data[pos + 6], data[pos + 7]);
+
+ // Long.parseLong doesn't like the sign bit, so have to extract this
+ // information and put it in at the end. (Acknowledgment: thanks
+ // to Ruben for pointing this out)
+ boolean negative = ((num2 & 0x80000000) != 0);
+
+ // Thanks to Lyle for the following improved IEEE double processing
+ long val = ((num2 & 0x7fffffff) * 0x100000000L) +
+ (num1 < 0 ? 0x100000000L + num1 : num1);
+ double value = Double.longBitsToDouble(val);
+
+ if (negative)
+ {
+ value = -value;
+ }
+ return value;
+ }
+
+ /**
+ * Puts the IEEE representation of the double provided into the array
+ * at the designated position
+ *
+ * @param target the data block into which the binary representation is to
+ * be placed
+ * @param pos the position in target in which to place the bytes
+ * @param d the double value to convert to raw bytes
+ */
+ public static void getIEEEBytes(double d, byte[] target, int pos)
+ {
+ long val = Double.doubleToLongBits(d);
+ target[pos] = (byte) (val & 0xff);
+ target[pos + 1] = (byte) ((val & 0xff00) >> 8);
+ target[pos + 2] = (byte) ((val & 0xff0000) >> 16);
+ target[pos + 3] = (byte) ((val & 0xff000000) >> 24);
+ target[pos + 4] = (byte) ((val & 0xff00000000L) >> 32);
+ target[pos + 5] = (byte) ((val & 0xff0000000000L) >> 40);
+ target[pos + 6] = (byte) ((val & 0xff000000000000L) >> 48);
+ target[pos + 7] = (byte) ((val & 0xff00000000000000L) >> 56) ;
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/EmptyCell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/EmptyCell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/EmptyCell.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,219 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import jxl.CellFeatures;
+import jxl.CellType;
+import jxl.format.Alignment;
+import jxl.format.CellFormat;
+import jxl.format.Border;
+import jxl.format.BorderLineStyle;
+import jxl.format.VerticalAlignment;
+import jxl.write.WritableCell;
+import jxl.write.WritableCellFeatures;
+
+/**
+ * An empty cell. Represents an empty, as opposed to a blank cell
+ * in the workbook
+ */
+public class EmptyCell implements WritableCell
+{
+ /**
+ * The row of this empty cell
+ */
+ private int row;
+ /**
+ * The column number of this empty cell
+ */
+ private int col;
+
+ /**
+ * Constructs an empty cell at the specified position
+ *
+ * @param c the zero based column
+ * @param r the zero based row
+ */
+ public EmptyCell(int c, int r)
+ {
+ row = r;
+ col = c;
+ }
+
+ /**
+ * Returns the row number of this cell
+ *
+ * @return the row number of this cell
+ */
+ public int getRow()
+ {
+ return row;
+ }
+
+ /**
+ * Returns the column number of this cell
+ *
+ * @return the column number of this cell
+ */
+ public int getColumn()
+ {
+ return col;
+ }
+
+ /**
+ * Returns the content type of this cell
+ *
+ * @return the content type for this cell
+ */
+ public CellType getType()
+ {
+ return CellType.EMPTY;
+ }
+
+ /**
+ * Quick and dirty function to return the contents of this cell as a string.
+ *
+ * @return an empty string
+ */
+ public String getContents()
+ {
+ return "";
+ }
+
+ /**
+ * Accessor for the format which is applied to this cell
+ *
+ * @return the format applied to this cell
+ */
+ public CellFormat getCellFormat()
+ {
+ return null;
+ }
+
+ /**
+ * Dummy override
+ * @param flag the hidden flag
+ */
+ public void setHidden(boolean flag)
+ {
+ }
+
+ /**
+ * Dummy override
+ * @param flag dummy
+ */
+ public void setLocked(boolean flag)
+ {
+ }
+
+ /**
+ * Dummy override
+ * @param align dummy
+ */
+ public void setAlignment(Alignment align)
+ {
+ }
+
+ /**
+ * Dummy override
+ * @param valign dummy
+ */
+ public void setVerticalAlignment(VerticalAlignment valign)
+ {
+ }
+
+ /**
+ * Dummy override
+ * @param line dummy
+ * @param border dummy
+ */
+ public void setBorder(Border border, BorderLineStyle line)
+ {
+ }
+
+ /**
+ * Dummy override
+ * @param cf dummy
+ */
+ public void setCellFormat(CellFormat cf)
+ {
+ }
+
+ /**
+ * Dummy override
+ * @param cf dummy
+ * @deprecated
+ */
+ public void setCellFormat(jxl.CellFormat cf)
+ {
+ }
+
+ /**
+ * Indicates whether or not this cell is hidden, by virtue of either
+ * the entire row or column being collapsed
+ *
+ * @return TRUE if this cell is hidden, FALSE otherwise
+ */
+ public boolean isHidden()
+ {
+ return false;
+ }
+
+ /**
+ * Implementation of the deep copy function
+ *
+ * @param c the column which the new cell will occupy
+ * @param r the row which the new cell will occupy
+ * @return a copy of this cell, which can then be added to the sheet
+ */
+ public WritableCell copyTo(int c, int r)
+ {
+ return new EmptyCell(c, r);
+ }
+
+ /**
+ * Accessor for the cell features
+ *
+ * @return the cell features or NULL if this cell doesn't have any
+ */
+ public CellFeatures getCellFeatures()
+ {
+ return null;
+ }
+
+ /**
+ * Accessor for the cell features
+ *
+ * @return the cell features or NULL if this cell doesn't have any
+ */
+ public WritableCellFeatures getWritableCellFeatures()
+ {
+ return null;
+ }
+
+ /**
+ * Accessor for the cell features
+ */
+ public void setCellFeatures(WritableCellFeatures wcf)
+ {
+ }
+
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/EncodedURLHelper.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/EncodedURLHelper.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/EncodedURLHelper.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,142 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+
+/**
+ * Helper to get the Microsoft encoded URL from the given string
+ */
+public class EncodedURLHelper
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(EncodedURLHelper.class);
+
+ // The control codes
+ private static byte msDosDriveLetter = 0x01;
+ private static byte sameDrive = 0x02;
+ private static byte endOfSubdirectory = 0x03;
+ private static byte parentDirectory = 0x04;
+ private static byte unencodedUrl = 0x05;
+
+ public static byte[] getEncodedURL(String s, WorkbookSettings ws)
+ {
+ if (s.startsWith("http:"))
+ {
+ return getURL(s, ws);
+ }
+ else
+ {
+ return getFile(s, ws);
+ }
+ }
+
+ private static byte[] getFile(String s, WorkbookSettings ws)
+ {
+ ByteArray byteArray = new ByteArray();
+
+ int pos = 0;
+ if (s.charAt(1) == ':')
+ {
+ // we have a drive letter
+ byteArray.add(msDosDriveLetter);
+ byteArray.add((byte) s.charAt(0));
+ pos = 2;
+ }
+ else if (s.charAt(pos) == '\\' ||
+ s.charAt(pos) == '/')
+ {
+ byteArray.add(sameDrive);
+ }
+
+ while (s.charAt(pos) == '\\' ||
+ s.charAt(pos) == '/')
+ {
+ pos++;
+ }
+
+ while (pos < s.length())
+ {
+ int nextSepIndex1 = s.indexOf('/', pos);
+ int nextSepIndex2 = s.indexOf('\\', pos);
+ int nextSepIndex = 0;
+ String nextFileNameComponent = null;
+
+ if (nextSepIndex1 != -1 && nextSepIndex2 != -1)
+ {
+ // choose the smallest (ie. nearest) separator
+ nextSepIndex = Math.min(nextSepIndex1, nextSepIndex2);
+ }
+ else if (nextSepIndex1 == -1 || nextSepIndex2 == -1)
+ {
+ // chose the maximum separator
+ nextSepIndex = Math.max(nextSepIndex1, nextSepIndex2);
+ }
+
+ if (nextSepIndex == -1)
+ {
+ // no more separators
+ nextFileNameComponent = s.substring(pos);
+ pos = s.length();
+ }
+ else
+ {
+ nextFileNameComponent = s.substring(pos, nextSepIndex);
+ pos = nextSepIndex + 1;
+ }
+
+ if (nextFileNameComponent.equals("."))
+ {
+ // current directory - do nothing
+ }
+ else if (nextFileNameComponent.equals(".."))
+ {
+ // parent directory
+ byteArray.add(parentDirectory);
+ }
+ else
+ {
+ // add the filename component
+ byteArray.add(StringHelper.getBytes(nextFileNameComponent,
+ ws));
+ }
+
+ if (pos < s.length())
+ {
+ byteArray.add(endOfSubdirectory);
+ }
+ }
+
+ return byteArray.getBytes();
+ }
+
+ private static byte[] getURL(String s, WorkbookSettings ws)
+ {
+ ByteArray byteArray = new ByteArray();
+ byteArray.add(unencodedUrl);
+ byteArray.add((byte) s.length());
+ byteArray.add(StringHelper.getBytes(s, ws));
+ return byteArray.getBytes();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/FilterModeRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/FilterModeRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/FilterModeRecord.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,60 @@
+/*********************************************************************
+*
+* Copyright (C) 2007 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Logger;
+
+import jxl.read.biff.Record;
+
+/**
+ * Range information for conditional formatting
+ */
+public class FilterModeRecord extends WritableRecordData
+{
+ // The logger
+ private static Logger logger = Logger.getLogger(FilterModeRecord.class);
+
+ /**
+ * The data
+ */
+ private byte[] data;
+
+
+ /**
+ * Constructor
+ */
+ public FilterModeRecord(Record t)
+ {
+ super(t);
+
+ data = getRecord().getData();
+ }
+
+ /**
+ * Retrieves the data for output to binary file
+ *
+ * @return the data to be written
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/FontRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/FontRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/FontRecord.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,547 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.format.Colour;
+import jxl.format.Font;
+import jxl.format.ScriptStyle;
+import jxl.format.UnderlineStyle;
+import jxl.read.biff.Record;
+
+/**
+ * A record containing the necessary data for the font information
+ */
+public class FontRecord extends WritableRecordData implements Font
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(FontRecord.class);
+
+ /**
+ * The point height of this font
+ */
+ private int pointHeight;
+ /**
+ * The index into the colour palette
+ */
+ private int colourIndex;
+ /**
+ * The bold weight for this font (normal or bold)
+ */
+ private int boldWeight;
+ /**
+ * The style of the script (italic or normal)
+ */
+ private int scriptStyle;
+ /**
+ * The underline style for this font (none, single, double etc)
+ */
+ private int underlineStyle;
+ /**
+ * The font family
+ */
+ private byte fontFamily;
+ /**
+ * The character set
+ */
+ private byte characterSet;
+
+ /**
+ * Indicates whether or not this font is italic
+ */
+ private boolean italic;
+ /**
+ * Indicates whether or not this font is struck out
+ */
+ private boolean struckout;
+ /**
+ * The name of this font
+ */
+ private String name;
+ /**
+ * Flag to indicate whether the derived data (such as the font index) has
+ * been initialized or not
+ */
+ private boolean initialized;
+
+ /**
+ * The index of this font in the font list
+ */
+ private int fontIndex;
+
+ /**
+ * Dummy indicators for overloading the constructor
+ */
+ private static class Biff7 {};
+ public static final Biff7 biff7 = new Biff7();
+
+ /**
+ * The conversion factor between microsoft internal units and point size
+ */
+ private static final int EXCEL_UNITS_PER_POINT = 20;
+
+ /**
+ * Constructor, used when creating a new font for writing out.
+ *
+ * @param bold the bold indicator
+ * @param ps the point size
+ * @param us the underline style
+ * @param fn the name
+ * @param it italicised indicator
+ * @param ss the script style
+ * @param ci the colour index
+ */
+ protected FontRecord(String fn, int ps, int bold, boolean it,
+ int us, int ci, int ss)
+ {
+ super(Type.FONT);
+ boldWeight = bold;
+ underlineStyle = us;
+ name = fn;
+ pointHeight = ps;
+ italic = it;
+ scriptStyle = ss;
+ colourIndex = ci;
+ initialized = false;
+ struckout = false;
+ }
+
+ /**
+ * Constructs this object from the raw data. Used when reading in a
+ * format record
+ *
+ * @param t the raw data
+ * @param ws the workbook settings
+ */
+ public FontRecord(Record t, WorkbookSettings ws)
+ {
+ super(t);
+
+ byte[] data = getRecord().getData();
+
+ pointHeight = IntegerHelper.getInt(data[0], data[1]) /
+ EXCEL_UNITS_PER_POINT;
+ colourIndex = IntegerHelper.getInt(data[4], data[5]);
+ boldWeight = IntegerHelper.getInt(data[6], data[7]);
+ scriptStyle = IntegerHelper.getInt(data[8], data[9]);
+ underlineStyle = data[10];
+ fontFamily = data[11];
+ characterSet = data[12];
+ initialized = false;
+
+ if ((data[2] & 0x02) != 0)
+ {
+ italic = true;
+ }
+
+ if ((data[2] & 0x08) != 0)
+ {
+ struckout = true;
+ }
+
+ int numChars = data[14];
+ if (data[15] == 0)
+ {
+ name = StringHelper.getString(data, numChars, 16, ws);
+ }
+ else if (data[15] == 1)
+ {
+ name = StringHelper.getUnicodeString(data, numChars, 16);
+ }
+ else
+ {
+ // Some font names don't have the unicode indicator
+ name = StringHelper.getString(data, numChars, 15, ws);
+ }
+ }
+
+ /**
+ * Constructs this object from the raw data. Used when reading in a
+ * format record
+ *
+ * @param t the raw data
+ * @param ws the workbook settings
+ * @param dummy dummy overload
+ */
+ public FontRecord(Record t, WorkbookSettings ws, Biff7 dummy)
+ {
+ super(t);
+
+ byte[] data = getRecord().getData();
+
+ pointHeight = IntegerHelper.getInt(data[0], data[1]) /
+ EXCEL_UNITS_PER_POINT;
+ colourIndex = IntegerHelper.getInt(data[4], data[5]);
+ boldWeight = IntegerHelper.getInt(data[6], data[7]);
+ scriptStyle = IntegerHelper.getInt(data[8], data[9]);
+ underlineStyle = data[10];
+ fontFamily = data[11];
+ initialized = false;
+
+ if ((data[2] & 0x02) != 0)
+ {
+ italic = true;
+ }
+
+ if ((data[2] & 0x08) != 0)
+ {
+ struckout = true;
+ }
+
+ int numChars = data[14];
+ name = StringHelper.getString(data, numChars, 15, ws);
+ }
+
+ /**
+ * Publicly available copy constructor
+ *
+ * @param f the font to copy
+ */
+ protected FontRecord(Font f)
+ {
+ super(Type.FONT);
+
+ Assert.verify(f != null);
+
+ pointHeight = f.getPointSize();
+ colourIndex = f.getColour().getValue();
+ boldWeight = f.getBoldWeight();
+ scriptStyle = f.getScriptStyle().getValue();
+ underlineStyle = f.getUnderlineStyle().getValue();
+ italic = f.isItalic();
+ name = f.getName();
+ struckout = f.isStruckout();
+ initialized = false;
+ }
+
+ /**
+ * Gets the byte data for writing out
+ *
+ * @return the raw data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[16 + name.length() * 2];
+
+ // Excel expects font heights in 1/20ths of a point
+ IntegerHelper.getTwoBytes(pointHeight * EXCEL_UNITS_PER_POINT, data, 0);
+
+ // Set the font attributes to be zero for now
+ if (italic)
+ {
+ data[2] |= 0x2;
+ }
+
+ if (struckout)
+ {
+ data[2] |= 0x08;
+ }
+
+ // Set the index to the colour palette
+ IntegerHelper.getTwoBytes(colourIndex, data, 4);
+
+ // Bold style
+ IntegerHelper.getTwoBytes(boldWeight, data, 6);
+
+ // Script style
+ IntegerHelper.getTwoBytes(scriptStyle, data, 8);
+
+ // Underline style
+ data[10] = (byte) underlineStyle;
+
+ // Set the font family to be 0
+ data[11] = fontFamily;
+
+ // Set the character set to be zero
+ data[12] = characterSet;
+
+ // Set the reserved bit to be zero
+ data[13] = 0;
+
+ // Set the length of the font name
+ data[14] = (byte) name.length();
+
+ data[15] = (byte) 1;
+
+ // Copy in the string
+ StringHelper.getUnicodeBytes(name, data, 16);
+
+ return data;
+ }
+
+ /**
+ * Accessor to see whether this object is initialized or not.
+ *
+ * @return TRUE if this font record has been initialized, FALSE otherwise
+ */
+ public final boolean isInitialized()
+ {
+ return initialized;
+ }
+
+ /**
+ * Sets the font index of this record. Called from the FormattingRecords
+ * object
+ *
+ * @param pos the position of this font in the workbooks font list
+ */
+ public final void initialize(int pos)
+ {
+ fontIndex = pos;
+ initialized = true;
+ }
+
+ /**
+ * Resets the initialize flag. This is called by the constructor of
+ * WritableWorkbookImpl to reset the statically declared fonts
+ */
+ public final void uninitialize()
+ {
+ initialized = false;
+ }
+
+ /**
+ * Accessor for the font index
+ *
+ * @return the font index
+ */
+ public final int getFontIndex()
+ {
+ return fontIndex;
+ }
+
+ /**
+ * Sets the point size for this font, if the font hasn't been initialized
+ *
+ * @param ps the point size
+ */
+ protected void setFontPointSize(int ps)
+ {
+ Assert.verify(!initialized);
+
+ pointHeight = ps;
+ }
+
+ /**
+ * Gets the point size for this font, if the font hasn't been initialized
+ *
+ * @return the point size
+ */
+ public int getPointSize()
+ {
+ return pointHeight;
+ }
+
+ /**
+ * Sets the bold style for this font, if the font hasn't been initialized
+ *
+ * @param bs the bold style
+ */
+ protected void setFontBoldStyle(int bs)
+ {
+ Assert.verify(!initialized);
+
+ boldWeight = bs;
+ }
+
+ /**
+ * Gets the bold weight for this font
+ *
+ * @return the bold weight for this font
+ */
+ public int getBoldWeight()
+ {
+ return boldWeight;
+ }
+
+ /**
+ * Sets the italic indicator for this font, if the font hasn't been
+ * initialized
+ *
+ * @param i the italic flag
+ */
+ protected void setFontItalic(boolean i)
+ {
+ Assert.verify(!initialized);
+
+ italic = i;
+ }
+
+ /**
+ * Returns the italic flag
+ *
+ * @return TRUE if this font is italic, FALSE otherwise
+ */
+ public boolean isItalic()
+ {
+ return italic;
+ }
+
+ /**
+ * Sets the underline style for this font, if the font hasn't been
+ * initialized
+ *
+ * @param us the underline style
+ */
+ protected void setFontUnderlineStyle(int us)
+ {
+ Assert.verify(!initialized);
+
+ underlineStyle = us;
+ }
+
+ /**
+ * Gets the underline style for this font
+ *
+ * @return the underline style
+ */
+ public UnderlineStyle getUnderlineStyle()
+ {
+ return UnderlineStyle.getStyle(underlineStyle);
+ }
+
+ /**
+ * Sets the colour for this font, if the font hasn't been
+ * initialized
+ *
+ * @param c the colour
+ */
+ protected void setFontColour(int c)
+ {
+ Assert.verify(!initialized);
+
+ colourIndex = c;
+ }
+
+ /**
+ * Gets the colour for this font
+ *
+ * @return the colour
+ */
+ public Colour getColour()
+ {
+ return Colour.getInternalColour(colourIndex);
+ }
+
+ /**
+ * Sets the script style (eg. superscript, subscript) for this font,
+ * if the font hasn't been initialized
+ *
+ * @param ss the colour
+ */
+ protected void setFontScriptStyle(int ss)
+ {
+ Assert.verify(!initialized);
+
+ scriptStyle = ss;
+ }
+
+ /**
+ * Gets the script style
+ *
+ * @return the script style
+ */
+ public ScriptStyle getScriptStyle()
+ {
+ return ScriptStyle.getStyle(scriptStyle);
+ }
+
+ /**
+ * Gets the name of this font
+ *
+ * @return the name of this font
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Standard hash code method
+ * @return the hash code for this object
+ */
+ public int hashCode()
+ {
+ return name.hashCode();
+ }
+
+ /**
+ * Standard equals method
+ * @param o the object to compare
+ * @return TRUE if the objects are equal, FALSE otherwise
+ */
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+
+ if (!(o instanceof FontRecord))
+ {
+ return false;
+ }
+
+ FontRecord font = (FontRecord) o;
+
+ if (pointHeight == font.pointHeight &&
+ colourIndex == font.colourIndex &&
+ boldWeight == font.boldWeight &&
+ scriptStyle == font.scriptStyle &&
+ underlineStyle == font.underlineStyle &&
+ italic == font.italic &&
+ struckout == font.struckout &&
+ fontFamily == font.fontFamily &&
+ characterSet == font.characterSet &&
+ name.equals(font.name))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Accessor for the strike out flag
+ *
+ * @return TRUE if this font is struck out, FALSE otherwise
+ */
+ public boolean isStruckout()
+ {
+ return struckout;
+ }
+
+ /**
+ * Sets the struck out flag
+ *
+ * @param os TRUE if the font is struck out, false otherwise
+ */
+ protected void setFontStruckout(boolean os)
+ {
+ struckout = os;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/Fonts.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/Fonts.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/Fonts.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,181 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import common.Assert;
+
+import jxl.write.biff.File;
+
+/**
+ * A container for the list of fonts used in this workbook
+ */
+public class Fonts
+{
+ /**
+ * The list of fonts
+ */
+ private ArrayList fonts;
+
+ /**
+ * The default number of fonts
+ */
+ private static final int numDefaultFonts = 4;
+
+ /**
+ * Constructor
+ */
+ public Fonts()
+ {
+ fonts = new ArrayList();
+ }
+
+ /**
+ * Adds a font record to this workbook. If the FontRecord passed in has not
+ * been initialized, then its font index is determined based upon the size
+ * of the fonts list. The FontRecord's initialized method is called, and
+ * it is added to the list of fonts.
+ *
+ * @param f the font to add
+ */
+ public void addFont(FontRecord f)
+ {
+ if (!f.isInitialized())
+ {
+ int pos = fonts.size();
+
+ // Remember that the pos with index 4 is skipped
+ if (pos >= 4)
+ {
+ pos++;
+ }
+
+ f.initialize(pos);
+ fonts.add(f);
+ }
+ }
+
+ /**
+ * Used by FormattingRecord for retrieving the fonts for the
+ * hardcoded styles
+ *
+ * @param index the index of the font to return
+ * @return the font with the specified font index
+ */
+ public FontRecord getFont(int index)
+ {
+ // remember to allow for the fact that font index 4 is not used
+ if (index > 4)
+ {
+ index--;
+ }
+
+ return (FontRecord) fonts.get(index);
+ }
+
+ /**
+ * Writes out the list of fonts
+ *
+ * @param outputFile the compound file to write the data to
+ * @exception IOException
+ */
+ public void write(File outputFile) throws IOException
+ {
+ Iterator i = fonts.iterator();
+
+ FontRecord font = null;
+ while (i.hasNext())
+ {
+ font = (FontRecord) i.next();
+ outputFile.write(font);
+ }
+ }
+
+ /**
+ * Rationalizes all the fonts, removing any duplicates
+ *
+ * @return the mappings between new indexes and old ones
+ */
+ IndexMapping rationalize()
+ {
+ IndexMapping mapping = new IndexMapping(fonts.size() + 1);
+ // allow for skipping record 4
+
+ ArrayList newfonts = new ArrayList();
+ FontRecord fr = null;
+ int numremoved = 0;
+
+ // Preserve the default fonts
+ for (int i = 0; i < numDefaultFonts; i++)
+ {
+ fr = (FontRecord) fonts.get(i);
+ newfonts.add(fr);
+ mapping.setMapping(fr.getFontIndex(), fr.getFontIndex());
+ }
+
+ // Now do the rest
+ Iterator it = null;
+ FontRecord fr2 = null;
+ boolean duplicate = false;
+ for (int i = numDefaultFonts; i < fonts.size(); i++)
+ {
+ fr = (FontRecord) fonts.get(i);
+
+ // Compare to all the fonts currently on the list
+ duplicate = false;
+ it = newfonts.iterator();
+ while (it.hasNext() && !duplicate)
+ {
+ fr2 = (FontRecord) it.next();
+ if (fr.equals(fr2))
+ {
+ duplicate = true;
+ mapping.setMapping(fr.getFontIndex(),
+ mapping.getNewIndex(fr2.getFontIndex()));
+ numremoved++;
+ }
+ }
+
+ if (!duplicate)
+ {
+ // Add to the new list
+ newfonts.add(fr);
+ int newindex = fr.getFontIndex() - numremoved;
+ Assert.verify(newindex > 4);
+ mapping.setMapping(fr.getFontIndex(), newindex);
+ }
+ }
+
+ // Iterate through the remaining fonts, updating all the font indices
+ it = newfonts.iterator();
+ while (it.hasNext())
+ {
+ fr = (FontRecord) it.next();
+ fr.initialize(mapping.getNewIndex(fr.getFontIndex()));
+ }
+
+ fonts = newfonts;
+
+ return mapping;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/FormatRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/FormatRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/FormatRecord.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,642 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import java.text.DateFormat;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.format.Format;
+import jxl.read.biff.Record;
+
+/**
+ * A non-built in format record
+ */
+public class FormatRecord extends WritableRecordData
+ implements DisplayFormat, Format
+{
+ /**
+ * The logger
+ */
+ public static Logger logger = Logger.getLogger(FormatRecord.class);
+
+ /**
+ * Initialized flag
+ */
+ private boolean initialized;
+
+ /**
+ * The raw data
+ */
+ private byte[] data;
+
+ /**
+ * The index code
+ */
+ private int indexCode;
+
+ /**
+ * The formatting string
+ */
+ private String formatString;
+
+ /**
+ * Indicates whether this is a date formatting record
+ */
+ private boolean date;
+
+ /**
+ * Indicates whether this a number formatting record
+ */
+ private boolean number;
+
+ /**
+ * The format object
+ */
+ private java.text.Format format;
+
+ /**
+ * The date strings to look for
+ */
+ private static String[] dateStrings = new String[]
+ {
+ "dd",
+ "mm",
+ "yy",
+ "hh",
+ "ss",
+ "m/",
+ "/d"
+ };
+
+ // Type to distinguish between biff7 and biff8
+ private static class BiffType
+ {
+ }
+
+ public static final BiffType biff8 = new BiffType();
+ public static final BiffType biff7 = new BiffType();
+
+ /**
+ * Constructor invoked when copying sheets
+ *
+ * @param fmt the format string
+ * @param refno the index code
+ */
+ FormatRecord(String fmt, int refno)
+ {
+ super(Type.FORMAT);
+ formatString = fmt;
+ indexCode = refno;
+ initialized = true;
+ }
+
+ /**
+ * Constructor used by writable formats
+ */
+ protected FormatRecord()
+ {
+ super(Type.FORMAT);
+ initialized = false;
+ }
+
+ /**
+ * Copy constructor - can be invoked by public access
+ *
+ * @param fr the format to copy
+ */
+ protected FormatRecord(FormatRecord fr)
+ {
+ super(Type.FORMAT);
+ initialized = false;
+
+ formatString = fr.formatString;
+ date = fr.date;
+ number = fr.number;
+ // format = (java.text.Format) fr.format.clone();
+ }
+
+ /**
+ * Constructs this object from the raw data. Used when reading in a
+ * format record
+ *
+ * @param t the raw data
+ * @param ws the workbook settings
+ * @param biffType biff type dummy overload
+ */
+ public FormatRecord(Record t, WorkbookSettings ws, BiffType biffType)
+ {
+ super(t);
+
+ byte[] data = getRecord().getData();
+ indexCode = IntegerHelper.getInt(data[0], data[1]);
+ initialized = true;
+
+ if (biffType == biff8)
+ {
+ int numchars = IntegerHelper.getInt(data[2], data[3]);
+ if (data[4] == 0)
+ {
+ formatString = StringHelper.getString(data, numchars, 5, ws);
+ }
+ else
+ {
+ formatString = StringHelper.getUnicodeString(data, numchars, 5);
+ }
+ }
+ else
+ {
+ int numchars = data[2];
+ byte[] chars = new byte[numchars];
+ System.arraycopy(data, 3, chars, 0, chars.length);
+ formatString = new String(chars);
+ }
+
+ date = false;
+ number = false;
+
+ // First see if this is a date format
+ for (int i = 0 ; i < dateStrings.length; i++)
+ {
+ String dateString = dateStrings[i];
+ if (formatString.indexOf(dateString) != -1 ||
+ formatString.indexOf(dateString.toUpperCase()) != -1)
+ {
+ date = true;
+ break;
+ }
+ }
+
+ // See if this is number format - look for the # or 0 characters
+ if (!date)
+ {
+ if (formatString.indexOf('#') != -1 ||
+ formatString.indexOf('0') != -1 )
+ {
+ number = true;
+ }
+ }
+ }
+
+ /**
+ * Used to get the data when writing out the format record
+ *
+ * @return the raw data
+ */
+ public byte[] getData()
+ {
+ data = new byte[formatString.length() * 2 + 3 + 2];
+
+ IntegerHelper.getTwoBytes(indexCode, data, 0);
+ IntegerHelper.getTwoBytes(formatString.length(), data, 2);
+ data[4] = (byte) 1; // unicode indicator
+ StringHelper.getUnicodeBytes(formatString, data, 5);
+
+ return data;
+ }
+
+ /**
+ * Gets the format index of this record
+ *
+ * @return the format index of this record
+ */
+ public int getFormatIndex()
+ {
+ return indexCode;
+ }
+
+ /**
+ * Accessor to see whether this object is initialized or not.
+ *
+ * @return TRUE if this font record has been initialized, FALSE otherwise
+ */
+ public boolean isInitialized()
+ {
+ return initialized;
+ }
+
+ /**
+ * Sets the index of this record. Called from the FormattingRecords
+ * object
+ *
+ * @param pos the position of this font in the workbooks font list
+ */
+
+ public void initialize(int pos)
+ {
+ indexCode = pos;
+ initialized = true;
+ }
+
+ /**
+ * Replaces all instances of search with replace in the input. Used for
+ * replacing microsoft number formatting characters with java equivalents
+ *
+ * @param input the format string
+ * @param search the Excel character to be replaced
+ * @param replace the java equivalent
+ * @return the input string with the specified substring replaced
+ */
+ protected final String replace(String input, String search, String replace)
+ {
+ String fmtstr = input;
+ int pos = fmtstr.indexOf(search);
+ while (pos != -1)
+ {
+ StringBuffer tmp = new StringBuffer(fmtstr.substring(0, pos));
+ tmp.append(replace);
+ tmp.append(fmtstr.substring(pos + search.length()));
+ fmtstr = tmp.toString();
+ pos = fmtstr.indexOf(search);
+ }
+ return fmtstr;
+ }
+
+ /**
+ * Called by the immediate subclass to set the string
+ * once the Java-Excel replacements have been done
+ *
+ * @param s the format string
+ */
+ protected final void setFormatString(String s)
+ {
+ formatString = s;
+ }
+
+ /**
+ * Sees if this format is a date format
+ *
+ * @return TRUE if this format is a date
+ */
+ public final boolean isDate()
+ {
+ return date;
+ }
+
+ /**
+ * Sees if this format is a number format
+ *
+ * @return TRUE if this format is a number
+ */
+ public final boolean isNumber()
+ {
+ return number;
+ }
+
+ /**
+ * Gets the java equivalent number format for the formatString
+ *
+ * @return The java equivalent of the number format for this object
+ */
+ public final NumberFormat getNumberFormat()
+ {
+ if (format != null && format instanceof NumberFormat)
+ {
+ return (NumberFormat) format;
+ }
+
+ try
+ {
+ String fs = formatString;
+
+ // Replace the Excel formatting characters with java equivalents
+ fs = replace(fs, "E+", "E");
+ fs = replace(fs, "_)", "");
+ fs = replace(fs, "_", "");
+ fs = replace(fs, "[Red]", "");
+ fs = replace(fs, "\\", "");
+
+ format = new DecimalFormat(fs);
+ }
+ catch (IllegalArgumentException e)
+ {
+ // Something went wrong with the date format - fail silently
+ // and return a default value
+ format = new DecimalFormat("#.###");
+ }
+
+ return (NumberFormat) format;
+ }
+
+ /**
+ * Gets the java equivalent date format for the formatString
+ *
+ * @return The java equivalent of the date format for this object
+ */
+ public final DateFormat getDateFormat()
+ {
+ if (format != null && format instanceof DateFormat)
+ {
+ return (DateFormat) format;
+ }
+
+ String fmt = formatString;
+
+ // Replace the AM/PM indicator with an a
+ int pos = fmt.indexOf("AM/PM");
+ while (pos != -1)
+ {
+ StringBuffer sb = new StringBuffer(fmt.substring(0, pos));
+ sb.append('a');
+ sb.append(fmt.substring(pos + 5));
+ fmt = sb.toString();
+ pos = fmt.indexOf("AM/PM");
+ }
+
+ // Replace ss.0 with ss.SSS (necessary to always specify milliseconds
+ // because of NT)
+ pos = fmt.indexOf("ss.0");
+ while (pos != -1)
+ {
+ StringBuffer sb = new StringBuffer(fmt.substring(0, pos));
+ sb.append("ss.SSS");
+
+ // Keep going until we run out of zeros
+ pos += 4;
+ while (pos < fmt.length() && fmt.charAt(pos) == '0')
+ {
+ pos++;
+ }
+
+ sb.append(fmt.substring(pos));
+ fmt = sb.toString();
+ pos = fmt.indexOf("ss.0");
+ }
+
+
+ // Filter out the backslashes
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < fmt.length(); i++)
+ {
+ if (fmt.charAt(i) != '\\')
+ {
+ sb.append(fmt.charAt(i));
+ }
+ }
+
+ fmt = sb.toString();
+
+ // If the date format starts with anything inside square brackets then
+ // filter tham out
+ if (fmt.charAt(0) == '[')
+ {
+ int end = fmt.indexOf(']');
+ if (end != -1)
+ {
+ fmt = fmt.substring(end+1);
+ }
+ }
+
+ // Get rid of some spurious characters that can creep in
+ fmt = replace(fmt, ";@", "");
+
+ // We need to convert the month indicator m, to upper case when we
+ // are dealing with dates
+ char[] formatBytes = fmt.toCharArray();
+
+ for (int i = 0; i < formatBytes.length; i++)
+ {
+ if (formatBytes[i] == 'm')
+ {
+ // Firstly, see if the preceding character is also an m. If so,
+ // copy that
+ if (i > 0 && (formatBytes[i - 1] == 'm' || formatBytes[i - 1] == 'M'))
+ {
+ formatBytes[i] = formatBytes[i - 1];
+ }
+ else
+ {
+ // There is no easy way out. We have to deduce whether this an
+ // minute or a month? See which is closest out of the
+ // letters H d s or y
+ // First, h
+ int minuteDist = Integer.MAX_VALUE;
+ for (int j = i - 1; j > 0; j--)
+ {
+ if (formatBytes[j] == 'h')
+ {
+ minuteDist = i - j;
+ break;
+ }
+ }
+
+ for (int j = i + 1; j < formatBytes.length; j++)
+ {
+ if (formatBytes[j] == 'h')
+ {
+ minuteDist = Math.min(minuteDist, j - i);
+ break;
+ }
+ }
+
+ for (int j = i - 1; j > 0; j--)
+ {
+ if (formatBytes[j] == 'H')
+ {
+ minuteDist = i - j;
+ break;
+ }
+ }
+
+ for (int j = i + 1; j < formatBytes.length; j++)
+ {
+ if (formatBytes[j] == 'H')
+ {
+ minuteDist = Math.min(minuteDist, j - i);
+ break;
+ }
+ }
+
+ // Now repeat for s
+ for (int j = i - 1; j > 0; j--)
+ {
+ if (formatBytes[j] == 's')
+ {
+ minuteDist = Math.min(minuteDist, i - j);
+ break;
+ }
+ }
+ for (int j = i + 1; j < formatBytes.length; j++)
+ {
+ if (formatBytes[j] == 's')
+ {
+ minuteDist = Math.min(minuteDist, j - i);
+ break;
+ }
+ }
+ // We now have the distance of the closest character which could
+ // indicate the the m refers to a minute
+ // Repeat for d and y
+ int monthDist = Integer.MAX_VALUE;
+ for (int j = i - 1; j > 0; j--)
+ {
+ if (formatBytes[j] == 'd')
+ {
+ monthDist = i - j;
+ break;
+ }
+ }
+
+ for (int j = i + 1; j < formatBytes.length; j++)
+ {
+ if (formatBytes[j] == 'd')
+ {
+ monthDist = Math.min(monthDist, j - i);
+ break;
+ }
+ }
+ // Now repeat for y
+ for (int j = i - 1; j > 0; j--)
+ {
+ if (formatBytes[j] == 'y')
+ {
+ monthDist = Math.min(monthDist, i - j);
+ break;
+ }
+ }
+ for (int j = i + 1; j < formatBytes.length; j++)
+ {
+ if (formatBytes[j] == 'y')
+ {
+ monthDist = Math.min(monthDist, j - i);
+ break;
+ }
+ }
+
+ if (monthDist < minuteDist)
+ {
+ // The month indicator is closer, so convert to a capital M
+ formatBytes[i] = Character.toUpperCase(formatBytes[i]);
+ }
+ else if ((monthDist == minuteDist) &&
+ (monthDist != Integer.MAX_VALUE))
+ {
+ // They are equidistant. As a tie-breaker, take the formatting
+ // character which precedes the m
+ char ind = formatBytes[i - monthDist];
+ if (ind == 'y' || ind == 'd')
+ {
+ // The preceding item indicates a month measure, so convert
+ formatBytes[i] = Character.toUpperCase(formatBytes[i]);
+ }
+ }
+ }
+ }
+ }
+
+ try
+ {
+ this.format = new SimpleDateFormat(new String(formatBytes));
+ }
+ catch (IllegalArgumentException e)
+ {
+ // There was a spurious character - fail silently
+ this.format = new SimpleDateFormat("dd MM yyyy hh:mm:ss");
+ }
+ return (DateFormat) this.format;
+ }
+
+ /**
+ * Gets the index code, for use as a hash value
+ *
+ * @return the ifmt code for this cell
+ */
+ public int getIndexCode()
+ {
+ return indexCode;
+ }
+
+ /**
+ * Gets the formatting string.
+ *
+ * @return the excel format string
+ */
+ public String getFormatString()
+ {
+ return formatString;
+ }
+
+ /**
+ * Indicates whether this formula is a built in
+ *
+ * @return FALSE
+ */
+ public boolean isBuiltIn()
+ {
+ return false;
+ }
+
+ /**
+ * Standard hash code method
+ * @return the hash code value for this object
+ */
+ public int hashCode()
+ {
+ return formatString.hashCode();
+ }
+
+ /**
+ * Standard equals method. This compares the contents of two
+ * format records, and not their indexCodes, which are ignored
+ *
+ * @param o the object to compare
+ * @return TRUE if the two objects are equal, FALSE otherwise
+ */
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+
+ if (!(o instanceof FormatRecord))
+ {
+ return false;
+ }
+
+ FormatRecord fr = (FormatRecord) o;
+
+ // Initialized format comparison
+ if (initialized && fr.initialized)
+ {
+ // Must be either a number or a date format
+ if (date != fr.date ||
+ number != fr.number)
+ {
+ return false;
+ }
+
+ return formatString.equals(fr.formatString);
+ }
+
+ // Uninitialized format comparison
+ return formatString.equals(fr.formatString);
+ }
+}
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/FormattingRecords.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/FormattingRecords.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/FormattingRecords.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,573 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.format.Colour;
+import jxl.format.RGB;
+import jxl.write.biff.File;
+
+/**
+ * The list of XF records and formatting records for the workbook
+ */
+public class FormattingRecords
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(FormattingRecords.class);
+
+ /**
+ * A hash map of FormatRecords, for random access retrieval when reading
+ * in a spreadsheet
+ */
+ private HashMap formats;
+
+ /**
+ * A list of formats, used when writing out a spreadsheet
+ */
+ private ArrayList formatsList;
+
+ /**
+ * The list of extended format records
+ */
+ private ArrayList xfRecords;
+
+ /**
+ * The next available index number for custom format records
+ */
+ private int nextCustomIndexNumber;
+
+ /**
+ * A handle to the available fonts
+ */
+ private Fonts fonts;
+
+ /**
+ * The colour palette
+ */
+ private PaletteRecord palette;
+
+ /**
+ * The start index number for custom format records
+ */
+ private static final int customFormatStartIndex = 0xa4;
+
+ /**
+ * The maximum number of format records. This is some weird internal
+ * Excel constraint
+ */
+ private static final int maxFormatRecordsIndex = 0x1b9;
+
+ /**
+ * The minimum number of XF records for a sheet. The rationalization
+ * processes commences immediately after this number
+ */
+ private static final int minXFRecords = 21;
+
+ /**
+ * Constructor
+ *
+ * @param f the container for the fonts
+ */
+ public FormattingRecords(Fonts f)
+ {
+ xfRecords = new ArrayList(10);
+ formats = new HashMap(10);
+ formatsList = new ArrayList(10);
+ fonts = f;
+ nextCustomIndexNumber = customFormatStartIndex;
+ }
+
+ /**
+ * Adds an extended formatting record to the list. If the XF record passed
+ * in has not been initialized, its index is determined based on the
+ * xfRecords list, and
+ * this position is passed to the XF records initialize method
+ *
+ * @param xf the xf record to add
+ * @exception NumFormatRecordsException
+ */
+ public final void addStyle(XFRecord xf)
+ throws NumFormatRecordsException
+ {
+ if (!xf.isInitialized())
+ {
+ int pos = xfRecords.size();
+ xf.initialize(pos, this, fonts);
+ xfRecords.add(xf);
+ }
+ else
+ {
+ // The XF record has probably been read in. If the index is greater
+ // Than the size of the list, then it is not a preset format,
+ // so add it
+ if (xf.getXFIndex() >= xfRecords.size())
+ {
+ xfRecords.add(xf);
+ }
+ }
+ }
+
+ /**
+ * Adds a cell format to the hash map, keyed on its index. If the format
+ * record is not initialized, then its index number is determined and its
+ * initialize method called. If the font is not a built in format, then it
+ * is added to the list of formats for writing out
+ *
+ * @param fr the format record
+ */
+ public final void addFormat(DisplayFormat fr)
+ throws NumFormatRecordsException
+ {
+ // Handle the case the where the index number in the read Excel
+ // file exhibits some major weirdness
+ if (fr.isInitialized() &&
+ fr.getFormatIndex() >= maxFormatRecordsIndex)
+ {
+ logger.warn("Format index exceeds Excel maximum - assigning custom " +
+ "number");
+ fr.initialize(nextCustomIndexNumber);
+ nextCustomIndexNumber++;
+ }
+
+ // Initialize the format record with a custom index number
+ if (!fr.isInitialized())
+ {
+ fr.initialize(nextCustomIndexNumber);
+ nextCustomIndexNumber++;
+ }
+
+ if (nextCustomIndexNumber > maxFormatRecordsIndex)
+ {
+ nextCustomIndexNumber = maxFormatRecordsIndex;
+ throw new NumFormatRecordsException();
+ }
+
+ if (fr.getFormatIndex() >= nextCustomIndexNumber)
+ {
+ nextCustomIndexNumber = fr.getFormatIndex() + 1;
+ }
+
+ if (!fr.isBuiltIn())
+ {
+ formatsList.add(fr);
+ formats.put(new Integer(fr.getFormatIndex()), fr);
+ }
+ }
+
+ /**
+ * Sees if the extended formatting record at the specified position
+ * represents a date. First checks against the built in formats, and
+ * then checks against the hash map of FormatRecords
+ *
+ * @param pos the xf format index
+ * @return TRUE if this format index is formatted as a Date
+ */
+ public final boolean isDate(int pos)
+ {
+ XFRecord xfr = (XFRecord) xfRecords.get(pos);
+
+ if (xfr.isDate())
+ {
+ return true;
+ }
+
+ FormatRecord fr = (FormatRecord)
+ formats.get(new Integer(xfr.getFormatRecord()));
+
+ return fr == null ? false : fr.isDate();
+ }
+
+ /**
+ * Gets the DateFormat used to format the cell.
+ *
+ * @param pos the xf format index
+ * @return the DateFormat object used to format the date in the original
+ * excel cell
+ */
+ public final DateFormat getDateFormat(int pos)
+ {
+ XFRecord xfr = (XFRecord) xfRecords.get(pos);
+
+ if (xfr.isDate())
+ {
+ return xfr.getDateFormat();
+ }
+
+ FormatRecord fr = (FormatRecord)
+ formats.get(new Integer(xfr.getFormatRecord()));
+
+ if (fr == null)
+ {
+ return null;
+ }
+
+ return fr.isDate() ? fr.getDateFormat() : null;
+ }
+
+ /**
+ * Gets the NumberFormat used to format the cell.
+ *
+ * @param pos the xf format index
+ * @return the DateFormat object used to format the date in the original
+ * excel cell
+ */
+ public final NumberFormat getNumberFormat(int pos)
+ {
+ XFRecord xfr = (XFRecord) xfRecords.get(pos);
+
+ if (xfr.isNumber())
+ {
+ return xfr.getNumberFormat();
+ }
+
+ FormatRecord fr = (FormatRecord)
+ formats.get(new Integer(xfr.getFormatRecord()));
+
+ if (fr == null)
+ {
+ return null;
+ }
+
+ return fr.isNumber() ? fr.getNumberFormat() : null;
+ }
+
+ /**
+ * Gets the format record
+ *
+ * @param index the formatting record index to retrieve
+ * @return the format record at the specified index
+ */
+ FormatRecord getFormatRecord(int index)
+ {
+ return (FormatRecord)
+ formats.get(new Integer(index));
+ }
+ /**
+ * Writes out all the format records and the XF records
+ *
+ * @param outputFile the file to write to
+ * @exception IOException
+ */
+ public void write(File outputFile) throws IOException
+ {
+ // Write out all the formats
+ Iterator i = formatsList.iterator();
+ FormatRecord fr = null;
+ while (i.hasNext())
+ {
+ fr = (FormatRecord) i.next();
+ outputFile.write(fr);
+ }
+
+ // Write out the styles
+ i = xfRecords.iterator();
+ XFRecord xfr = null;
+ while (i.hasNext())
+ {
+ xfr = (XFRecord) i.next();
+ outputFile.write(xfr);
+ }
+
+ // Write out the style records
+ BuiltInStyle style = new BuiltInStyle(0x10, 3);
+ outputFile.write(style);
+
+ style = new BuiltInStyle(0x11, 6);
+ outputFile.write(style);
+
+ style = new BuiltInStyle(0x12, 4);
+ outputFile.write(style);
+
+ style = new BuiltInStyle(0x13, 7);
+ outputFile.write(style);
+
+ style = new BuiltInStyle(0x0, 0);
+ outputFile.write(style);
+
+ style = new BuiltInStyle(0x14, 5);
+ outputFile.write(style);
+ }
+
+ /**
+ * Accessor for the fonts used by this workbook
+ *
+ * @return the fonts container
+ */
+ protected final Fonts getFonts()
+ {
+ return fonts;
+ }
+
+ /**
+ * Gets the XFRecord for the specified index. Used when copying individual
+ * cells
+ *
+ * @param index the XF record to retrieve
+ * @return the XF record at the specified index
+ */
+ public final XFRecord getXFRecord(int index)
+ {
+ return (XFRecord) xfRecords.get(index);
+ }
+
+ /**
+ * Gets the number of formatting records on the list. This is used by the
+ * writable subclass because there is an upper limit on the amount of
+ * format records that are allowed to be present in an excel sheet
+ *
+ * @return the number of format records present
+ */
+ protected final int getNumberOfFormatRecords()
+ {
+ return formatsList.size();
+ }
+
+ /**
+ * Rationalizes all the fonts, removing duplicate entries
+ *
+ * @return the list of new font index number
+ */
+ public IndexMapping rationalizeFonts()
+ {
+ return fonts.rationalize();
+ }
+
+ /**
+ * Rationalizes the cell formats. Duplicate
+ * formats are removed and the format indexed of the cells
+ * adjusted accordingly
+ *
+ * @param fontMapping the font mapping index numbers
+ * @param formatMapping the format mapping index numbers
+ * @return the list of new font index number
+ */
+ public IndexMapping rationalize(IndexMapping fontMapping,
+ IndexMapping formatMapping)
+ {
+ // Update the index codes for the XF records using the format
+ // mapping and the font mapping
+ // at the same time
+ XFRecord xfr = null;
+ for (Iterator it = xfRecords.iterator(); it.hasNext();)
+ {
+ xfr = (XFRecord) it.next();
+
+ if (xfr.getFormatRecord() >= customFormatStartIndex)
+ {
+ xfr.setFormatIndex(formatMapping.getNewIndex(xfr.getFormatRecord()));
+ }
+
+ xfr.setFontIndex(fontMapping.getNewIndex(xfr.getFontIndex()));
+ }
+
+ ArrayList newrecords = new ArrayList(minXFRecords);
+ IndexMapping mapping = new IndexMapping(xfRecords.size());
+ int numremoved = 0;
+
+ int numXFRecords = Math.min(minXFRecords, xfRecords.size());
+ // Copy across the fundamental styles
+ for (int i = 0; i < numXFRecords; i++)
+ {
+ newrecords.add(xfRecords.get(i));
+ mapping.setMapping(i, i);
+ }
+
+ if (numXFRecords < minXFRecords)
+ {
+ logger.warn("There are less than the expected minimum number of " +
+ "XF records");
+ return mapping;
+ }
+
+ // Iterate through the old list
+ for (int i = minXFRecords; i < xfRecords.size(); i++)
+ {
+ XFRecord xf = (XFRecord) xfRecords.get(i);
+
+ // Compare against formats already on the list
+ boolean duplicate = false;
+ for (Iterator it = newrecords.iterator();
+ it.hasNext() && !duplicate;)
+ {
+ XFRecord xf2 = (XFRecord) it.next();
+ if (xf2.equals(xf))
+ {
+ duplicate = true;
+ mapping.setMapping(i, mapping.getNewIndex(xf2.getXFIndex()));
+ numremoved++;
+ }
+ }
+
+ // If this format is not a duplicate then add it to the new list
+ if (!duplicate)
+ {
+ newrecords.add(xf);
+ mapping.setMapping(i, i - numremoved);
+ }
+ }
+
+ // It is sufficient to merely change the xf index field on all XFRecords
+ // In this case, CellValues which refer to defunct format records
+ // will nevertheless be written out with the correct index number
+ for (Iterator i = xfRecords.iterator(); i.hasNext();)
+ {
+ XFRecord xf = (XFRecord) i.next();
+ xf.rationalize(mapping);
+ }
+
+ // Set the new list
+ xfRecords = newrecords;
+
+ return mapping;
+ }
+
+ /**
+ * Rationalizes the display formats. Duplicate
+ * formats are removed and the format indices of the cells
+ * adjusted accordingly. It is invoked immediately prior to writing
+ * writing out the sheet
+ * @return the index mapping between the old display formats and the
+ * rationalized ones
+ */
+ public IndexMapping rationalizeDisplayFormats()
+ {
+ ArrayList newformats = new ArrayList();
+ int numremoved = 0;
+ IndexMapping mapping = new IndexMapping(nextCustomIndexNumber);
+
+ // Iterate through the old list
+ Iterator i = formatsList.iterator();
+ DisplayFormat df = null;
+ DisplayFormat df2 = null;
+ boolean duplicate = false;
+ while (i.hasNext())
+ {
+ df = (DisplayFormat) i.next();
+
+ Assert.verify(!df.isBuiltIn());
+
+ // Compare against formats already on the list
+ Iterator i2 = newformats.iterator();
+ duplicate = false;
+ while (i2.hasNext() && !duplicate)
+ {
+ df2 = (DisplayFormat) i2.next();
+ if (df2.equals(df))
+ {
+ duplicate = true;
+ mapping.setMapping(df.getFormatIndex(),
+ mapping.getNewIndex(df2.getFormatIndex()));
+ numremoved++;
+ }
+ }
+
+ // If this format is not a duplicate then add it to the new list
+ if (!duplicate)
+ {
+ newformats.add(df);
+ int indexnum = df.getFormatIndex() - numremoved;
+ if (indexnum > maxFormatRecordsIndex)
+ {
+ logger.warn("Too many number formats - using default format.");
+ indexnum = 0; // the default number format index
+ }
+ mapping.setMapping(df.getFormatIndex(),
+ df.getFormatIndex() - numremoved);
+ }
+ }
+
+ // Set the new list
+ formatsList = newformats;
+
+ // Update the index codes for the remaining formats
+ i = formatsList.iterator();
+
+ while (i.hasNext())
+ {
+ df = (DisplayFormat) i.next();
+ df.initialize(mapping.getNewIndex(df.getFormatIndex()));
+ }
+
+ return mapping;
+ }
+
+ /**
+ * Accessor for the colour palette
+ *
+ * @return the palette
+ */
+ public PaletteRecord getPalette()
+ {
+ return palette;
+ }
+
+ /**
+ * Called from the WorkbookParser to set the colour palette
+ *
+ * @param pr the palette
+ */
+ public void setPalette(PaletteRecord pr)
+ {
+ palette = pr;
+ }
+
+ /**
+ * Sets the RGB value for the specified colour for this workbook
+ *
+ * @param c the colour whose RGB value is to be overwritten
+ * @param r the red portion to set (0-255)
+ * @param g the green portion to set (0-255)
+ * @param b the blue portion to set (0-255)
+ */
+ public void setColourRGB(Colour c, int r, int g, int b)
+ {
+ if (palette == null)
+ {
+ palette = new PaletteRecord();
+ }
+ palette.setColourRGB(c, r, g, b);
+ }
+
+ /**
+ * Accessor for the RGB value for the specified colour
+ *
+ * @return the RGB for the specified colour
+ */
+ public RGB getColourRGB(Colour c)
+ {
+ if (palette == null)
+ {
+ return c.getDefaultRGB();
+ }
+
+ return palette.getColourRGB(c);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/FormulaData.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/FormulaData.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/FormulaData.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,40 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import jxl.Cell;
+import jxl.biff.formula.FormulaException;
+
+/**
+ * Interface which is used for copying formulas from a read only
+ * to a writable spreadsheet
+ */
+public interface FormulaData extends Cell
+{
+ /**
+ * Gets the raw bytes for the formula. This will include the
+ * parsed tokens array EXCLUDING the standard cell information
+ * (row, column, xfindex)
+ *
+ * @return the raw record data
+ * @exception FormulaException
+ */
+ public byte[] getFormulaData() throws FormulaException;
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/HeaderFooter.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/HeaderFooter.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/HeaderFooter.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,654 @@
+/*********************************************************************
+ *
+ * Copyright (C) 2004 Andrew Khan, Eric Jung
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ***************************************************************************/
+
+package jxl.biff;
+
+import common.Logger;
+
+/**
+ * Class which represents an Excel header or footer. Information for this
+ * class came from Microsoft Knowledge Base Article 142136
+ * (previously Q142136).
+ *
+ * This class encapsulates three internal structures representing the header
+ * or footer contents which appear on the left, right or central part of the
+ * page
+ */
+public abstract class HeaderFooter
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(HeaderFooter.class);
+
+ // Codes to format text
+
+ /**
+ * Turns bold printing on or off
+ */
+ private static final String BOLD_TOGGLE = "&B";
+
+ /**
+ * Turns underline printing on or off
+ */
+ private static final String UNDERLINE_TOGGLE = "&U";
+
+ /**
+ * Turns italic printing on or off
+ */
+ private static final String ITALICS_TOGGLE = "&I";
+
+ /**
+ * Turns strikethrough printing on or off
+ */
+ private static final String STRIKETHROUGH_TOGGLE = "&S";
+
+ /**
+ * Turns double-underline printing on or off
+ */
+ private static final String DOUBLE_UNDERLINE_TOGGLE = "&E";
+
+ /**
+ * Turns superscript printing on or off
+ */
+ private static final String SUPERSCRIPT_TOGGLE = "&X";
+
+ /**
+ * Turns subscript printing on or off
+ */
+ private static final String SUBSCRIPT_TOGGLE = "&Y";
+
+ /**
+ * Turns outline printing on or off (Macintosh only)
+ */
+ private static final String OUTLINE_TOGGLE = "&O";
+
+ /**
+ * Turns shadow printing on or off (Macintosh only)
+ */
+ private static final String SHADOW_TOGGLE = "&H";
+
+ /**
+ * Left-aligns the characters that follow
+ */
+ private static final String LEFT_ALIGN = "&L";
+
+ /**
+ * Centres the characters that follow
+ */
+ private static final String CENTRE = "&C";
+
+ /**
+ * Right-aligns the characters that follow
+ */
+ private static final String RIGHT_ALIGN = "&R";
+
+ // Codes to insert specific data
+
+ /**
+ * Prints the page number
+ */
+ private static final String PAGENUM = "&P";
+
+ /**
+ * Prints the total number of pages in the document
+ */
+ private static final String TOTAL_PAGENUM = "&N";
+
+ /**
+ * Prints the current date
+ */
+ private static final String DATE = "&D";
+
+ /**
+ * Prints the current time
+ */
+ private static final String TIME = "&T";
+
+ /**
+ * Prints the name of the workbook
+ */
+ private static final String WORKBOOK_NAME = "&F";
+
+ /**
+ * Prints the name of the worksheet
+ */
+ private static final String WORKSHEET_NAME = "&A";
+
+ /**
+ * The contents - a simple wrapper around a string buffer
+ */
+ protected static class Contents
+ {
+ /**
+ * The buffer containing the header/footer string
+ */
+ private StringBuffer contents;
+
+ /**
+ * The constructor
+ */
+ protected Contents()
+ {
+ contents = new StringBuffer();
+ }
+
+ /**
+ * Constructor used when reading worksheets. The string contains all
+ * the formatting (but not alignment characters
+ *
+ * @param s the format string
+ */
+ protected Contents(String s)
+ {
+ contents = new StringBuffer(s);
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param copy the contents to copy
+ */
+ protected Contents(Contents copy)
+ {
+ contents = new StringBuffer(copy.getContents());
+ }
+
+ /**
+ * Retrieves a String
ified
+ * version of this object
+ *
+ * @return the header string
+ */
+ protected String getContents()
+ {
+ return contents != null ? contents.toString() : "";
+ }
+
+ /**
+ * Internal method which appends the text to the string buffer
+ *
+ * @param txt
+ */
+ private void appendInternal(String txt)
+ {
+ if (contents == null)
+ {
+ contents = new StringBuffer();
+ }
+
+ contents.append(txt);
+ }
+
+ /**
+ * Internal method which appends the text to the string buffer
+ *
+ * @param ch
+ */
+ private void appendInternal(char ch)
+ {
+ if (contents == null)
+ {
+ contents = new StringBuffer();
+ }
+
+ contents.append(ch);
+ }
+
+ /**
+ * Appends the text to the string buffer
+ *
+ * @param txt
+ */
+ protected void append(String txt)
+ {
+ appendInternal(txt);
+ }
+
+ /**
+ * Turns bold printing on or off. Bold printing
+ * is initially off. Text subsequently appended to
+ * this object will be bolded until this method is
+ * called again.
+ */
+ protected void toggleBold()
+ {
+ appendInternal(BOLD_TOGGLE);
+ }
+
+ /**
+ * Turns underline printing on or off. Underline printing
+ * is initially off. Text subsequently appended to
+ * this object will be underlined until this method is
+ * called again.
+ */
+ protected void toggleUnderline()
+ {
+ appendInternal(UNDERLINE_TOGGLE);
+ }
+
+ /**
+ * Turns italics printing on or off. Italics printing
+ * is initially off. Text subsequently appended to
+ * this object will be italicized until this method is
+ * called again.
+ */
+ protected void toggleItalics()
+ {
+ appendInternal(ITALICS_TOGGLE);
+ }
+
+ /**
+ * Turns strikethrough printing on or off. Strikethrough printing
+ * is initially off. Text subsequently appended to
+ * this object will be striked out until this method is
+ * called again.
+ */
+ protected void toggleStrikethrough()
+ {
+ appendInternal(STRIKETHROUGH_TOGGLE);
+ }
+
+ /**
+ * Turns double-underline printing on or off. Double-underline printing
+ * is initially off. Text subsequently appended to
+ * this object will be double-underlined until this method is
+ * called again.
+ */
+ protected void toggleDoubleUnderline()
+ {
+ appendInternal(DOUBLE_UNDERLINE_TOGGLE);
+ }
+
+ /**
+ * Turns superscript printing on or off. Superscript printing
+ * is initially off. Text subsequently appended to
+ * this object will be superscripted until this method is
+ * called again.
+ */
+ protected void toggleSuperScript()
+ {
+ appendInternal(SUPERSCRIPT_TOGGLE);
+ }
+
+ /**
+ * Turns subscript printing on or off. Subscript printing
+ * is initially off. Text subsequently appended to
+ * this object will be subscripted until this method is
+ * called again.
+ */
+ protected void toggleSubScript()
+ {
+ appendInternal(SUBSCRIPT_TOGGLE);
+ }
+
+ /**
+ * Turns outline printing on or off (Macintosh only).
+ * Outline printing is initially off. Text subsequently appended
+ * to this object will be outlined until this method is
+ * called again.
+ */
+ protected void toggleOutline()
+ {
+ appendInternal(OUTLINE_TOGGLE);
+ }
+
+ /**
+ * Turns shadow printing on or off (Macintosh only).
+ * Shadow printing is initially off. Text subsequently appended
+ * to this object will be shadowed until this method is
+ * called again.
+ */
+ protected void toggleShadow()
+ {
+ appendInternal(SHADOW_TOGGLE);
+ }
+
+ /**
+ * Sets the font of text subsequently appended to this
+ * object.. Previously appended text is not affected.
+ *
+ * Note: no checking is performed to
+ * determine if fontName is a valid font.
+ *
+ * @param fontName name of the font to use
+ */
+ protected void setFontName(String fontName)
+ {
+ // Font name must be in quotations
+ appendInternal("&\"");
+ appendInternal(fontName);
+ appendInternal('\"');
+ }
+
+ /**
+ * Sets the font size of text subsequently appended to this
+ * object. Previously appended text is not affected.
+ *
+ * Valid point sizes are between 1 and 99 (inclusive). If
+ * size is outside this range, this method returns false
+ * and does not change font size. If size is within this
+ * range, the font size is changed and true is returned.
+ *
+ * @param size The size in points. Valid point sizes are
+ * between 1 and 99 (inclusive).
+ * @return true if the font size was changed, false if font
+ * size was not changed because 1 > size > 99.
+ */
+ protected boolean setFontSize(int size)
+ {
+ if (size < 1 || size > 99)
+ {
+ return false;
+ }
+
+ // A two digit number should be used -- even if the
+ // leading number is just a zero.
+ String fontSize;
+ if (size < 10)
+ {
+ // single-digit -- make two digit
+ fontSize = "0" + size;
+ }
+ else
+ {
+ fontSize = Integer.toString(size);
+ }
+
+ appendInternal('&');
+ appendInternal(fontSize);
+ return true;
+ }
+
+ /**
+ * Appends the page number
+ */
+ protected void appendPageNumber()
+ {
+ appendInternal(PAGENUM);
+ }
+
+ /**
+ * Appends the total number of pages
+ */
+ protected void appendTotalPages()
+ {
+ appendInternal(TOTAL_PAGENUM);
+ }
+
+ /**
+ * Appends the current date
+ */
+ protected void appendDate()
+ {
+ appendInternal(DATE);
+ }
+
+ /**
+ * Appends the current time
+ */
+ protected void appendTime()
+ {
+ appendInternal(TIME);
+ }
+
+ /**
+ * Appends the workbook name
+ */
+ protected void appendWorkbookName()
+ {
+ appendInternal(WORKBOOK_NAME);
+ }
+
+ /**
+ * Appends the worksheet name
+ */
+ protected void appendWorkSheetName()
+ {
+ appendInternal(WORKSHEET_NAME);
+ }
+
+ /**
+ * Clears the contents of this portion
+ */
+ protected void clear()
+ {
+ contents = null;
+ }
+
+ /**
+ * Queries if the contents are empty
+ *
+ * @return TRUE if the contents are empty, FALSE otherwise
+ */
+ protected boolean empty()
+ {
+ if (contents == null || contents.length() == 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * The left aligned header/footer contents
+ */
+ private Contents left;
+
+ /**
+ * The right aligned header/footer contents
+ */
+ private Contents right;
+
+ /**
+ * The centrally aligned header/footer contents
+ */
+ private Contents centre;
+
+ /**
+ * Default constructor.
+ */
+ protected HeaderFooter()
+ {
+ left = createContents();
+ right = createContents();
+ centre = createContents();
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param c the item to copy
+ */
+ protected HeaderFooter(HeaderFooter hf)
+ {
+ left = createContents(hf.left);
+ right = createContents(hf.right);
+ centre = createContents(hf.centre);
+ }
+
+ /**
+ * Constructor used when reading workbooks to separate the left, right
+ * a central part of the strings into their constituent parts
+ */
+ protected HeaderFooter(String s)
+ {
+ if (s == null || s.length() == 0)
+ {
+ left = createContents();
+ right = createContents();
+ centre = createContents();
+ return;
+ }
+
+ int pos = 0;
+ int leftPos = s.indexOf(LEFT_ALIGN);
+ int rightPos = s.indexOf(RIGHT_ALIGN);
+ int centrePos = s.indexOf(CENTRE);
+
+ // Do the left position string
+ if (pos == leftPos)
+ {
+ if (centrePos != -1)
+ {
+ left = createContents(s.substring(pos + 2, centrePos));
+ pos = centrePos;
+ }
+ else if (rightPos != -1 )
+ {
+ left = createContents(s.substring(pos + 2, rightPos));
+ pos = rightPos;
+ }
+ else
+ {
+ left = createContents(s.substring(pos + 2));
+ pos = s.length();
+ }
+ }
+
+ // Do the centrally positioned part of the string. This is the default
+ // if no alignment string is specified
+ if (pos == centrePos ||
+ (leftPos == -1 && rightPos == -1 && centrePos == -1))
+ {
+ if (rightPos != -1)
+ {
+ centre = createContents(s.substring(pos + 2, rightPos));
+ pos = rightPos;
+ }
+ else
+ {
+ int cpos = (pos == centrePos) ? pos + 2 : pos;
+ centre = createContents(s.substring(cpos));
+ pos = s.length();
+ }
+ }
+
+ // Do the right positioned part of the string
+ if (pos == rightPos)
+ {
+ right = createContents(s.substring(pos + 2));
+ pos = s.length();
+ }
+
+ if (left == null)
+ {
+ left = createContents();
+ }
+
+ if (centre == null)
+ {
+ centre = createContents();
+ }
+
+ if (right == null)
+ {
+ right = createContents();
+ }
+ }
+
+ /**
+ * Retrieves a String
ified
+ * version of this object
+ *
+ * @return the header string
+ */
+ public String toString()
+ {
+ StringBuffer hf = new StringBuffer();
+ if (!left.empty())
+ {
+ hf.append(LEFT_ALIGN);
+ hf.append(left.getContents());
+ }
+
+ if (!centre.empty())
+ {
+ hf.append(CENTRE);
+ hf.append(centre.getContents());
+ }
+
+ if (!right.empty())
+ {
+ hf.append(RIGHT_ALIGN);
+ hf.append(right.getContents());
+ }
+
+ return hf.toString();
+ }
+
+ /**
+ * Accessor for the contents which appear on the right hand side of the page
+ *
+ * @return the right aligned contents
+ */
+ protected Contents getRightText()
+ {
+ return right;
+ }
+
+ /**
+ * Accessor for the contents which in the centre of the page
+ *
+ * @return the centrally aligned contents
+ */
+ protected Contents getCentreText()
+ {
+ return centre;
+ }
+
+ /**
+ * Accessor for the contents which appear on the left hand side of the page
+ *
+ * @return the left aligned contents
+ */
+ protected Contents getLeftText()
+ {
+ return left;
+ }
+
+ /**
+ * Clears the contents of the header/footer
+ */
+ protected void clear()
+ {
+ left.clear();
+ right.clear();
+ centre.clear();
+ }
+
+ /**
+ * Creates internal class of the appropriate type
+ */
+ protected abstract Contents createContents();
+
+ /**
+ * Creates internal class of the appropriate type
+ */
+ protected abstract Contents createContents(String s);
+
+ /**
+ * Creates internal class of the appropriate type
+ */
+ protected abstract Contents createContents(Contents c);
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/IndexMapping.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/IndexMapping.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/IndexMapping.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,70 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Logger;
+
+/**
+ * This class is a wrapper for a list of mappings between indices.
+ * It is used when removing duplicate records and specifies the new
+ * index for cells which have the duplicate format
+ */
+public final class IndexMapping
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(IndexMapping.class);
+
+ /**
+ * The array of new indexes for an old one
+ */
+ private int[] newIndices;
+
+ /**
+ * Constructor
+ *
+ * @param size the number of index numbers to be mapped
+ */
+ public IndexMapping(int size)
+ {
+ newIndices = new int[size];
+ }
+
+ /**
+ * Sets a mapping
+ * @param oldIndex the old index
+ * @param newIndex the new index
+ */
+ public void setMapping(int oldIndex, int newIndex)
+ {
+ newIndices[oldIndex] = newIndex;
+ }
+
+ /**
+ * Gets the new cell format index
+ * @param oldIndex the existing index number
+ * @return the new index number
+ */
+ public int getNewIndex(int oldIndex)
+ {
+ return newIndices[oldIndex];
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/IntegerHelper.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/IntegerHelper.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/IntegerHelper.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,149 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+/**
+ * Converts excel byte representations into integers
+ */
+public final class IntegerHelper
+{
+ /**
+ * Private constructor disables the instantiation of this object
+ */
+ private IntegerHelper()
+ {
+ }
+
+ /**
+ * Gets an int from two bytes
+ *
+ * @param b2 the second byte
+ * @param b1 the first byte
+ * @return The integer value
+ */
+ public static int getInt(byte b1, byte b2)
+ {
+ int i1 = b1 & 0xff;
+ int i2 = b2 & 0xff;
+ int val = i2 << 8 | i1;
+ return val;
+ }
+
+ /**
+ * Gets an short from two bytes
+ *
+ * @param b2 the second byte
+ * @param b1 the first byte
+ * @return The short value
+ */
+ public static short getShort(byte b1, byte b2)
+ {
+ short i1 = (short) (b1 & 0xff);
+ short i2 = (short) (b2 & 0xff);
+ short val = (short) (i2 << 8 | i1);
+ return val;
+ }
+
+
+ /**
+ * Gets an int from four bytes, doing all the necessary swapping
+ *
+ * @param b1 a byte
+ * @param b2 a byte
+ * @param b3 a byte
+ * @param b4 a byte
+ * @return the integer value represented by the four bytes
+ */
+ public static int getInt(byte b1, byte b2, byte b3, byte b4)
+ {
+ int i1 = getInt(b1, b2);
+ int i2 = getInt(b3, b4);
+
+ int val = i2 << 16 | i1;
+ return val;
+ }
+
+ /**
+ * Gets a two byte array from an integer
+ *
+ * @param i the integer
+ * @return the two bytes
+ */
+ public static byte[] getTwoBytes(int i)
+ {
+ byte[] bytes = new byte[2];
+
+ bytes[0] = (byte) (i & 0xff);
+ bytes[1] = (byte) ((i & 0xff00) >> 8);
+
+ return bytes;
+ }
+
+ /**
+ * Gets a four byte array from an integer
+ *
+ * @param i the integer
+ * @return a four byte array
+ */
+ public static byte[] getFourBytes(int i)
+ {
+ byte[] bytes = new byte[4];
+
+ int i1 = i & 0xffff;
+ int i2 = (i & 0xffff0000) >> 16;
+
+ getTwoBytes(i1, bytes, 0);
+ getTwoBytes(i2, bytes, 2);
+
+ return bytes;
+ }
+
+
+ /**
+ * Converts an integer into two bytes, and places it in the array at the
+ * specified position
+ *
+ * @param target the array to place the byte data into
+ * @param pos the position at which to place the data
+ * @param i the integer value to convert
+ */
+ public static void getTwoBytes(int i, byte[] target, int pos)
+ {
+ target[pos] = (byte) (i & 0xff);
+ target[pos + 1] = (byte) ((i & 0xff00) >> 8);
+ }
+
+ /**
+ * Converts an integer into four bytes, and places it in the array at the
+ * specified position
+ *
+ * @param target the array which is to contain the converted data
+ * @param pos the position in the array in which to place the data
+ * @param i the integer to convert
+ */
+ public static void getFourBytes(int i, byte[] target, int pos)
+ {
+ byte[] bytes = getFourBytes(i);
+ target[pos] = bytes[0];
+ target[pos + 1] = bytes[1];
+ target[pos + 2] = bytes[2];
+ target[pos + 3] = bytes[3];
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/NumFormatRecordsException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/NumFormatRecordsException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/NumFormatRecordsException.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,36 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+/**
+ * Excel places a constraint on the number of format records that
+ * are allowed. This exception is thrown when that number is exceeded
+ * This is a static exception and should be handled internally
+ */
+public class NumFormatRecordsException extends Exception
+{
+ /**
+ * Constructor
+ */
+ public NumFormatRecordsException()
+ {
+ super("Internal error: max number of FORMAT records exceeded");
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/PaletteRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/PaletteRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/PaletteRecord.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,228 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import jxl.format.Colour;
+import jxl.format.RGB;
+import jxl.read.biff.Record;
+
+/**
+ * A record representing the RGB colour palette
+ */
+public class PaletteRecord extends WritableRecordData
+{
+ /**
+ * The list of bespoke rgb colours used by this sheet
+ */
+ private RGB[] rgbColours = new RGB[numColours];
+
+ /**
+ * A dirty flag indicating that this palette has been tampered with
+ * in some way
+ */
+ private boolean dirty;
+
+ /**
+ * Flag indicating that the palette was read in
+ */
+ private boolean read;
+
+ /**
+ * Initialized flag
+ */
+ private boolean initialized;
+
+ /**
+ * The number of colours in the palette
+ */
+ private static final int numColours = 56;
+
+ /**
+ * Constructor
+ *
+ * @param t the raw bytes
+ */
+ public PaletteRecord(Record t)
+ {
+ super(t);
+
+ initialized = false;
+ dirty = false;
+ read = true;
+ }
+
+ /**
+ * Default constructor - used when there is no palette specified
+ */
+ public PaletteRecord()
+ {
+ super(Type.PALETTE);
+
+ initialized = true;
+ dirty = false;
+ read = false;
+
+ // Initialize the array with all the default colours
+ Colour[] colours = Colour.getAllColours();
+
+ for (int i = 0; i < colours.length; i++)
+ {
+ Colour c = colours[i];
+ setColourRGB(c,
+ c.getDefaultRGB().getRed(),
+ c.getDefaultRGB().getGreen(),
+ c.getDefaultRGB().getBlue());
+ }
+ }
+
+ /**
+ * Accessor for the binary data - used when copying
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ // Palette was read in, but has not been changed
+ if (read && !dirty)
+ {
+ return getRecord().getData();
+ }
+
+ byte[] data = new byte[numColours * 4 + 2];
+ int pos = 0;
+
+ // Set the number of records
+ IntegerHelper.getTwoBytes(numColours, data, pos);
+
+ // Set the rgb content
+ for (int i = 0; i < numColours; i++)
+ {
+ pos = i * 4 + 2;
+ data[pos] = (byte) rgbColours[i].getRed();
+ data[pos + 1] = (byte) rgbColours[i].getGreen();
+ data[pos + 2] = (byte) rgbColours[i].getBlue();
+ }
+
+ return data;
+ }
+
+ /**
+ * Initialize the record data
+ */
+ private void initialize()
+ {
+ byte[] data = getRecord().getData();
+
+ int numrecords = IntegerHelper.getInt(data[0], data[1]);
+
+ for (int i = 0; i < numrecords; i++)
+ {
+ int pos = i * 4 + 2;
+ int red = IntegerHelper.getInt(data[pos], (byte) 0);
+ int green = IntegerHelper.getInt(data[pos + 1], (byte) 0);
+ int blue = IntegerHelper.getInt(data[pos + 2], (byte) 0);
+ rgbColours[i] = new RGB(red, green, blue);
+ }
+
+ initialized = true;
+ }
+
+ /**
+ * Accessor for the dirty flag, which indicates if this palette has been
+ * modified
+ *
+ * @return TRUE if the palette has been modified, FALSE if it is the default
+ */
+ public boolean isDirty()
+ {
+ return dirty;
+ }
+
+ /**
+ * Sets the RGB value for the specified colour for this workbook
+ *
+ * @param c the colour whose RGB value is to be overwritten
+ * @param r the red portion to set (0-255)
+ * @param g the green portion to set (0-255)
+ * @param b the blue portion to set (0-255)
+ */
+ public void setColourRGB(Colour c, int r, int g, int b)
+ {
+ // Only colours on the standard palette with values 8-64 are acceptable
+ int pos = c.getValue() - 8;
+ if (pos < 0 || pos >= numColours)
+ {
+ return;
+ }
+
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ // Force the colours into the range 0-255
+ r = setValueRange(r, 0, 0xff);
+ g = setValueRange(g, 0, 0xff);
+ b = setValueRange(b, 0, 0xff);
+
+ rgbColours[pos] = new RGB(r, g, b);
+
+ // Indicate that the palette has been modified
+ dirty = true;
+ }
+
+ /**
+ * Gets the colour RGB from the palette
+ *
+ * @param c the colour
+ * @return an RGB structure
+ */
+ public RGB getColourRGB(Colour c)
+ {
+ // Only colours on the standard palette with values 8-64 are acceptable
+ int pos = c.getValue() - 8;
+ if (pos < 0 || pos >= numColours)
+ {
+ return c.getDefaultRGB();
+ }
+
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return rgbColours[pos];
+ }
+
+ /**
+ * Forces the value passed in to be between the range passed in
+ *
+ * @param val the value to constrain
+ * @param min the minimum acceptable value
+ * @param max the maximum acceptable value
+ * @return the constrained value
+ */
+ private int setValueRange(int val, int min, int max)
+ {
+ val = Math.max(val, min);
+ val = Math.min(val, max);
+ return val;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/RangeImpl.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/RangeImpl.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/RangeImpl.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,169 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Logger;
+
+import jxl.Cell;
+import jxl.Range;
+import jxl.Sheet;
+
+/**
+ * Implementation class for the Range interface. This merely
+ * holds the raw range information, and when the time comes, it
+ * interrogates the workbook for the object.
+ * This does not keep handles to the objects for performance reasons,
+ * as this could impact garbage collection on larger spreadsheets
+ */
+public class RangeImpl implements Range
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(RangeImpl.class);
+
+ /**
+ * A handle to the workbook
+ */
+ private WorkbookMethods workbook;
+
+ /**
+ * The sheet index containing the column at the top left
+ */
+ private int sheet1;
+
+ /**
+ * The column number of the cell at the top left of the range
+ */
+ private int column1;
+
+ /**
+ * The row number of the cell at the top left of the range
+ */
+ private int row1;
+
+ /**
+ * The sheet index of the cell at the bottom right
+ */
+ private int sheet2;
+
+ /**
+ * The column index of the cell at the bottom right
+ */
+ private int column2;
+
+ /**
+ * The row index of the cell at the bottom right
+ */
+ private int row2;
+
+ /**
+ * Constructor
+ * @param w the workbook
+ * @param es the external sheet
+ * @param s1 the sheet of the top left cell of the range
+ * @param c1 the column number of the top left cell of the range
+ * @param r1 the row number of the top left cell of the range
+ * @param s2 the sheet of the bottom right cell
+ * @param c2 the column number of the bottom right cell of the range
+ * @param r2 the row number of the bottomr right cell of the range
+ */
+ public RangeImpl(WorkbookMethods w,
+ int s1, int c1, int r1,
+ int s2, int c2, int r2)
+ {
+ workbook = w;
+ sheet1 = s1;
+ sheet2 = s2;
+ row1 = r1;
+ row2 = r2;
+ column1 = c1;
+ column2 = c2;
+ }
+
+ /**
+ * Gets the cell at the top left of this range
+ *
+ * @return the cell at the top left
+ */
+ public Cell getTopLeft()
+ {
+ Sheet s = workbook.getReadSheet(sheet1);
+
+ if (column1 < s.getColumns() &&
+ row1 < s.getRows())
+ {
+ return s.getCell(column1, row1);
+ }
+ else
+ {
+ return new EmptyCell(column1, row1);
+ }
+ }
+
+ /**
+ * Gets the cell at the bottom right of this range
+ *
+ * @return the cell at the bottom right
+ */
+ public Cell getBottomRight()
+ {
+ Sheet s = workbook.getReadSheet(sheet2);
+
+ if (column2 < s.getColumns() &&
+ row2 < s.getRows())
+ {
+ return s.getCell(column2, row2);
+ }
+ else
+ {
+ return new EmptyCell(column2, row2);
+ }
+ }
+
+ /**
+ * Gets the index of the first sheet in the range
+ *
+ * @return the index of the first sheet in the range
+ */
+ public int getFirstSheetIndex()
+ {
+ return sheet1;
+ }
+
+ /**
+ * Gets the index of the last sheet in the range
+ *
+ * @return the index of the last sheet in the range
+ */
+ public int getLastSheetIndex()
+ {
+ return sheet2;
+ }
+}
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/RecordData.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/RecordData.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/RecordData.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,88 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import jxl.read.biff.Record;
+
+/**
+ * The record data within a record
+ */
+public abstract class RecordData
+{
+ /**
+ * The raw data
+ */
+ private Record record;
+
+ /**
+ * The Biff code for this record. This is set up when the record is
+ * used for writing
+ */
+ private int code;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param r the raw data
+ */
+ protected RecordData(Record r)
+ {
+ record = r;
+ code = r.getCode();
+ }
+
+ /**
+ * Constructor used by the writable records
+ *
+ * @param t the type
+ */
+ protected RecordData(Type t)
+ {
+ code = t.value;
+ }
+
+ /**
+ * Returns the raw data to its subclasses
+ *
+ * @return the raw data
+ */
+ protected Record getRecord()
+ {
+ return record;
+ }
+
+ /**
+ * Accessor for the code
+ *
+ * @return the code
+ */
+ protected final int getCode()
+ {
+ return code;
+ }
+}
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/SheetRangeImpl.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/SheetRangeImpl.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/SheetRangeImpl.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,329 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import jxl.Cell;
+import jxl.Range;
+import jxl.Sheet;
+
+/**
+ * Implementation class for the Range interface. This merely
+ * holds the raw range information. This implementation is used
+ * for ranges which are present on the current working sheet, so the
+ * getSheetIndex merely returns -1
+ */
+public class SheetRangeImpl implements Range
+{
+ /**
+ * A handle to the sheet containing this range
+ */
+ private Sheet sheet;
+
+ /**
+ * The column number of the cell at the top left of the range
+ */
+ private int column1;
+
+ /**
+ * The row number of the cell at the top left of the range
+ */
+ private int row1;
+
+ /**
+ * The column index of the cell at the bottom right
+ */
+ private int column2;
+
+ /**
+ * The row index of the cell at the bottom right
+ */
+ private int row2;
+
+ /**
+ * Constructor
+ * @param s the sheet containing the range
+ * @param c1 the column number of the top left cell of the range
+ * @param r1 the row number of the top left cell of the range
+ * @param c2 the column number of the bottom right cell of the range
+ * @param r2 the row number of the bottomr right cell of the range
+ */
+ public SheetRangeImpl(Sheet s, int c1, int r1,
+ int c2, int r2)
+ {
+ sheet = s;
+ row1 = r1;
+ row2 = r2;
+ column1 = c1;
+ column2 = c2;
+ }
+
+ /**
+ * A copy constructor used for copying ranges between sheets
+ *
+ * @param c the range to copy from
+ * @param s the writable sheet
+ */
+ public SheetRangeImpl(SheetRangeImpl c, Sheet s)
+ {
+ sheet = s;
+ row1 = c.row1;
+ row2 = c.row2;
+ column1 = c.column1;
+ column2 = c.column2;
+ }
+
+ /**
+ * Gets the cell at the top left of this range
+ *
+ * @return the cell at the top left
+ */
+ public Cell getTopLeft()
+ {
+ // If the print area exceeds the bounds of the sheet, then handle
+ // it here. The sheet implementation will give a NPE
+ if (column1 >= sheet.getColumns() ||
+ row1 >= sheet.getRows())
+ {
+ return new EmptyCell(column1,row1);
+ }
+
+ return sheet.getCell(column1, row1);
+ }
+
+ /**
+ * Gets the cell at the bottom right of this range
+ *
+ * @return the cell at the bottom right
+ */
+ public Cell getBottomRight()
+ {
+ // If the print area exceeds the bounds of the sheet, then handle
+ // it here. The sheet implementation will give a NPE
+ if (column2 >= sheet.getColumns() ||
+ row2 >= sheet.getRows())
+ {
+ return new EmptyCell(column2,row2);
+ }
+
+ return sheet.getCell(column2, row2);
+ }
+
+ /**
+ * Not supported. Returns -1, indicating that it refers to the current
+ * sheet
+ *
+ * @return -1
+ */
+ public int getFirstSheetIndex()
+ {
+ return -1;
+ }
+
+ /**
+ * Not supported. Returns -1, indicating that it refers to the current
+ * sheet
+ *
+ * @return -1
+ */
+ public int getLastSheetIndex()
+ {
+ return -1;
+ }
+
+ /**
+ * Sees whether there are any intersections between this range and the
+ * range passed in. This method is used internally by the WritableSheet to
+ * verify the integrity of merged cells, hyperlinks etc. Ranges are
+ * only ever compared for the same sheet
+ *
+ * @param range the range to compare against
+ * @return TRUE if the ranges intersect, FALSE otherwise
+ */
+ public boolean intersects(SheetRangeImpl range)
+ {
+ if (range == this)
+ {
+ return true;
+ }
+
+ if (row2 < range.row1 ||
+ row1 > range.row2 ||
+ column2 < range.column1 ||
+ column1 > range.column2)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * To string method - primarily used during debugging
+ *
+ * @return the string version of this object
+ */
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ CellReferenceHelper.getCellReference(column1, row1, sb);
+ sb.append('-');
+ CellReferenceHelper.getCellReference(column2, row2, sb);
+ return sb.toString();
+ }
+
+ /**
+ * A row has been inserted, so adjust the range objects accordingly
+ *
+ * @param r the row which has been inserted
+ */
+ public void insertRow(int r)
+ {
+ if (r > row2)
+ {
+ return;
+ }
+
+ if (r <= row1)
+ {
+ row1++;
+ }
+
+ if (r <= row2)
+ {
+ row2++;
+ }
+ }
+
+ /**
+ * A column has been inserted, so adjust the range objects accordingly
+ *
+ * @param c the column which has been inserted
+ */
+ public void insertColumn(int c)
+ {
+ if (c > column2)
+ {
+ return;
+ }
+
+ if (c <= column1)
+ {
+ column1++;
+ }
+
+ if (c <= column2)
+ {
+ column2++;
+ }
+ }
+
+ /**
+ * A row has been removed, so adjust the range objects accordingly
+ *
+ * @param r the row which has been inserted
+ */
+ public void removeRow(int r)
+ {
+ if (r > row2)
+ {
+ return;
+ }
+
+ if (r < row1)
+ {
+ row1--;
+ }
+
+ if (r < row2)
+ {
+ row2--;
+ }
+ }
+
+ /**
+ * A column has been removed, so adjust the range objects accordingly
+ *
+ * @param c the column which has been removed
+ */
+ public void removeColumn(int c)
+ {
+ if (c > column2)
+ {
+ return;
+ }
+
+ if (c < column1)
+ {
+ column1--;
+ }
+
+ if (c < column2)
+ {
+ column2--;
+ }
+ }
+
+ /**
+ * Standard hash code method
+ *
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ return 0xffff ^ row1 ^ row2 ^ column1 ^ column2;
+ }
+
+ /**
+ * Standard equals method
+ *
+ * @param o the object to compare
+ * @return TRUE if the two objects are the same, FALSE otherwise
+ */
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+
+ if (!(o instanceof SheetRangeImpl))
+ {
+ return false;
+ }
+
+ SheetRangeImpl compare = (SheetRangeImpl) o;
+
+ return (column1 == compare.column1 &&
+ column2 == compare.column2 &&
+ row1 == compare.row1 &&
+ row2 == compare.row2);
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/StringHelper.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/StringHelper.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/StringHelper.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,227 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import java.io.UnsupportedEncodingException;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+
+/**
+ * Helper function to convert Java string objects to and from the byte
+ * representations
+ */
+public final class StringHelper
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(StringHelper.class);
+
+ // Due to a a Sun bug in some versions of JVM 1.4, the UnicodeLittle
+ // encoding doesn't always work. Making this a public static field
+ // enables client code access to this (but in an undocumented and
+ // unsupported fashion). Suggested alternative values for this
+ // are "UTF-16LE" or "UnicodeLittleUnmarked"
+ public static String UNICODE_ENCODING = "UnicodeLittle";
+
+ /**
+ * Private default constructor to prevent instantiation
+ */
+ private StringHelper()
+ {
+ }
+
+ /**
+ * Gets the bytes of the specified string. This will simply return the ASCII
+ * values of the characters in the string
+ *
+ * @param s the string to convert into bytes
+ * @return the ASCII values of the characters in the string
+ * @deprecated
+ */
+ public static byte[] getBytes(String s)
+ {
+ return s.getBytes();
+ }
+
+ /**
+ * Gets the bytes of the specified string. This will simply return the ASCII
+ * values of the characters in the string
+ *
+ * @param s the string to convert into bytes
+ * @return the ASCII values of the characters in the string
+ */
+ public static byte[] getBytes(String s, WorkbookSettings ws)
+ {
+ try
+ {
+ return s.getBytes(ws.getEncoding());
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ // fail silently
+ return null;
+ }
+ }
+
+ /**
+ * Converts the string into a little-endian array of Unicode bytes
+ *
+ * @param s the string to convert
+ * @return the unicode values of the characters in the string
+ */
+ public static byte[] getUnicodeBytes(String s)
+ {
+ try
+ {
+ byte[] b = s.getBytes(UNICODE_ENCODING);
+
+ // Sometimes this method writes out the unicode
+ // identifier
+ if (b.length == (s.length() * 2 + 2))
+ {
+ byte[] b2 = new byte[b.length - 2];
+ System.arraycopy(b, 2, b2, 0, b2.length);
+ b = b2;
+ }
+ return b;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ // Fail silently
+ return null;
+ }
+ }
+
+
+ /**
+ * Gets the ASCII bytes from the specified string and places them in the
+ * array at the specified position
+ *
+ * @param pos the position at which to place the converted data
+ * @param s the string to convert
+ * @param d the byte array which will contain the converted string data
+ */
+ public static void getBytes(String s, byte[] d, int pos)
+ {
+ byte[] b = getBytes(s);
+ System.arraycopy(b, 0, d, pos, b.length);
+ }
+
+ /**
+ * Inserts the unicode byte representation of the specified string into the
+ * array passed in
+ *
+ * @param pos the position at which to insert the converted data
+ * @param s the string to convert
+ * @param d the byte array which will hold the string data
+ */
+ public static void getUnicodeBytes(String s, byte[] d, int pos)
+ {
+ byte[] b = getUnicodeBytes(s);
+ System.arraycopy(b, 0, d, pos, b.length);
+ }
+
+ /**
+ * Gets a string from the data array using the character encoding for
+ * this workbook
+ *
+ * @param pos The start position of the string
+ * @param length The number of characters in the string
+ * @param d The byte data
+ * @param ws the workbook settings
+ * @return the string built up from the raw bytes
+ */
+ public static String getString(byte[] d, int length, int pos,
+ WorkbookSettings ws)
+ {
+ if( length == 0 )
+ {
+ return ""; // Reduces number of new Strings
+ }
+
+ try
+ {
+ return new String(d, pos, length, ws.getEncoding());
+ // byte[] b = new byte[length];
+ // System.arraycopy(d, pos, b, 0, length);
+ // return new String(b, ws.getEncoding());
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ logger.warn(e.toString());
+ return "";
+ }
+ }
+
+ /**
+ * Gets a string from the data array
+ *
+ * @param pos The start position of the string
+ * @param length The number of characters in the string
+ * @param d The byte data
+ * @return the string built up from the unicode characters
+ */
+ public static String getUnicodeString(byte[] d, int length, int pos)
+ {
+ try
+ {
+ byte[] b = new byte[length * 2];
+ System.arraycopy(d, pos, b, 0, length * 2);
+ return new String(b, UNICODE_ENCODING);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ // Fail silently
+ return "";
+ }
+ }
+
+ /**
+ * Replaces all instances of search with replace in the input.
+ * Even though later versions of java can use string.replace()
+ * this is included Java 1.2 compatibility
+ *
+ * @param input the format string
+ * @param search the Excel character to be replaced
+ * @param replace the java equivalent
+ * @return the input string with the specified substring replaced
+ */
+ public static final String replace(String input,
+ String search,
+ String replace)
+ {
+ String fmtstr = input;
+ int pos = fmtstr.indexOf(search);
+ while (pos != -1)
+ {
+ StringBuffer tmp = new StringBuffer(fmtstr.substring(0, pos));
+ tmp.append(replace);
+ tmp.append(fmtstr.substring(pos + search.length()));
+ fmtstr = tmp.toString();
+ pos = fmtstr.indexOf(search, pos+replace.length());
+ }
+ return fmtstr;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/Type.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/Type.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/Type.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,493 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+/**
+ * An enumeration class which contains the biff types
+ */
+public final class Type
+{
+ /**
+ * The biff value for this type
+ */
+ public final int value;
+ /**
+ * An array of all types
+ */
+ private static Type[] types = new Type[0];
+
+ /**
+ * Constructor
+ * Sets the biff value and adds this type to the array of all types
+ *
+ * @param v the biff code for the type
+ */
+ private Type(int v)
+ {
+ value = v;
+
+ // Add to the list of available types
+ Type[] newTypes = new Type[types.length + 1];
+ System.arraycopy(types, 0, newTypes, 0, types.length);
+ newTypes[types.length] = this;
+ types = newTypes;
+ }
+
+ private static class ArbitraryType {};
+ private static ArbitraryType arbitrary = new ArbitraryType();
+
+ /**
+ * Constructor used for the creation of arbitrary types
+ */
+ private Type(int v, ArbitraryType arb)
+ {
+ value = v;
+ }
+
+ /**
+ * Standard hash code method
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ return value;
+ }
+
+ /**
+ * Standard equals method
+ * @param o the object to compare
+ * @return TRUE if the objects are equal, FALSE otherwise
+ */
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+
+ if (!(o instanceof Type))
+ {
+ return false;
+ }
+
+ Type t = (Type) o;
+
+ return value == t.value;
+ }
+
+ /**
+ * Gets the type object from its integer value
+ * @param v the internal code
+ * @return the type
+ */
+ public static Type getType(int v)
+ {
+ for (int i = 0; i < types.length; i++)
+ {
+ if (types[i].value == v)
+ {
+ return types[i];
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ /**
+ * Used to create an arbitrary record type. This method is only
+ * used during bespoke debugging process. The creation of an
+ * arbitrary type does not add it to the static list of known types
+ */
+ public static Type createType(int v)
+ {
+ return new Type(v, arbitrary);
+ }
+
+ /**
+ */
+ public static final Type BOF = new Type(0x809);
+ /**
+ */
+ public static final Type EOF = new Type(0x0a);
+ /**
+ */
+ public static final Type BOUNDSHEET = new Type(0x85);
+ /**
+ */
+ public static final Type SUPBOOK = new Type(0x1ae);
+ /**
+ */
+ public static final Type EXTERNSHEET = new Type(0x17);
+ /**
+ */
+ public static final Type DIMENSION = new Type(0x200);
+ /**
+ */
+ public static final Type BLANK = new Type(0x201);
+ /**
+ */
+ public static final Type MULBLANK = new Type(0xbe);
+ /**
+ */
+ public static final Type ROW = new Type(0x208);
+ /**
+ */
+ public static final Type NOTE = new Type(0x1c);
+ /**
+ */
+ public static final Type TXO = new Type(0x1b6);
+ /**
+ */
+ public static final Type RK = new Type(0x7e);
+ /**
+ */
+ public static final Type RK2 = new Type(0x27e);
+ /**
+ */
+ public static final Type MULRK = new Type(0xbd);
+ /**
+ */
+ public static final Type INDEX = new Type(0x20b);
+ /**
+ */
+ public static final Type DBCELL = new Type(0xd7);
+ /**
+ */
+ public static final Type SST = new Type(0xfc);
+ /**
+ */
+ public static final Type COLINFO = new Type(0x7d);
+ /**
+ */
+ public static final Type EXTSST = new Type(0xff);
+ /**
+ */
+ public static final Type CONTINUE = new Type(0x3c);
+ /**
+ */
+ public static final Type LABEL = new Type(0x204);
+ /**
+ */
+ public static final Type RSTRING = new Type(0xd6);
+ /**
+ */
+ public static final Type LABELSST = new Type(0xfd);
+ /**
+ */
+ public static final Type NUMBER = new Type(0x203);
+ /**
+ */
+ public static final Type NAME = new Type(0x18);
+ /**
+ */
+ public static final Type TABID = new Type(0x13d);
+ /**
+ */
+ public static final Type ARRAY = new Type(0x221);
+ /**
+ */
+ public static final Type STRING = new Type(0x207);
+ /**
+ */
+ public static final Type FORMULA = new Type(0x406);
+ /**
+ */
+ public static final Type FORMULA2 = new Type(0x6);
+ /**
+ */
+ public static final Type SHAREDFORMULA = new Type(0x4bc);
+ /**
+ */
+ public static final Type FORMAT = new Type(0x41e);
+ /**
+ */
+ public static final Type XF = new Type(0xe0);
+ /**
+ */
+ public static final Type BOOLERR = new Type(0x205);
+ /**
+ */
+ public static final Type INTERFACEHDR = new Type(0xe1);
+ /**
+ */
+ public static final Type SAVERECALC = new Type(0x5f);
+ /**
+ */
+ public static final Type INTERFACEEND = new Type(0xe2);
+ /**
+ */
+ public static final Type XCT = new Type(0x59);
+ /**
+ */
+ public static final Type CRN = new Type(0x5a);
+ /**
+ */
+ public static final Type DEFCOLWIDTH = new Type(0x55);
+ /**
+ */
+ public static final Type DEFAULTROWHEIGHT = new Type(0x225);
+ /**
+ */
+ public static final Type WRITEACCESS = new Type(0x5c);
+ /**
+ */
+ public static final Type WSBOOL = new Type(0x81);
+ /**
+ */
+ public static final Type CODEPAGE = new Type(0x42);
+ /**
+ */
+ public static final Type DSF = new Type(0x161);
+ /**
+ */
+ public static final Type FNGROUPCOUNT = new Type(0x9c);
+ /**
+ */
+ public static final Type FILTERMODE = new Type(0x9b);
+ /**
+ */
+ public static final Type AUTOFILTERINFO = new Type(0x9d);
+ /**
+ */
+ public static final Type AUTOFILTER = new Type(0x9e);
+ /**
+ */
+ public static final Type COUNTRY = new Type(0x8c);
+ /**
+ */
+ public static final Type PROTECT = new Type(0x12);
+ /**
+ */
+ public static final Type SCENPROTECT = new Type(0xdd);
+ /**
+ */
+ public static final Type OBJPROTECT = new Type(0x63);
+ /**
+ */
+ public static final Type PRINTHEADERS = new Type(0x2a);
+ /**
+ */
+ public static final Type HEADER = new Type(0x14);
+ /**
+ */
+ public static final Type FOOTER = new Type(0x15);
+ /**
+ */
+ public static final Type HCENTER = new Type(0x83);
+ /**
+ */
+ public static final Type VCENTER = new Type(0x84);
+ /**
+ */
+ public static final Type FILEPASS = new Type(0x2f);
+ /**
+ */
+ public static final Type SETUP = new Type(0xa1);
+ /**
+ */
+ public static final Type PRINTGRIDLINES = new Type(0x2b);
+ /**
+ */
+ public static final Type GRIDSET = new Type(0x82);
+ /**
+ */
+ public static final Type GUTS = new Type(0x80);
+ /**
+ */
+ public static final Type WINDOWPROTECT = new Type(0x19);
+ /**
+ */
+ public static final Type PROT4REV = new Type(0x1af);
+ /**
+ */
+ public static final Type PROT4REVPASS = new Type(0x1bc);
+ /**
+ */
+ public static final Type PASSWORD = new Type(0x13);
+ /**
+ */
+ public static final Type REFRESHALL = new Type(0x1b7);
+ /**
+ */
+ public static final Type WINDOW1 = new Type(0x3d);
+ /**
+ */
+ public static final Type WINDOW2 = new Type(0x23e);
+ /**
+ */
+ public static final Type BACKUP = new Type(0x40);
+ /**
+ */
+ public static final Type HIDEOBJ = new Type(0x8d);
+ /**
+ */
+ public static final Type NINETEENFOUR = new Type(0x22);
+ /**
+ */
+ public static final Type PRECISION = new Type(0xe);
+ /**
+ */
+ public static final Type BOOKBOOL = new Type(0xda);
+ /**
+ */
+ public static final Type FONT = new Type(0x31);
+ /**
+ */
+ public static final Type MMS = new Type(0xc1);
+ /**
+ */
+ public static final Type CALCMODE = new Type(0x0d);
+ /**
+ */
+ public static final Type CALCCOUNT = new Type(0x0c);
+ /**
+ */
+ public static final Type REFMODE = new Type(0x0f);
+ /**
+ */
+ public static final Type TEMPLATE = new Type(0x60);
+ /**
+ */
+ public static final Type OBJPROJ = new Type(0xd3);
+ /**
+ */
+ public static final Type DELTA = new Type(0x10);
+ /**
+ */
+ public static final Type MERGEDCELLS = new Type(0xe5);
+ /**
+ */
+ public static final Type ITERATION = new Type(0x11);
+ /**
+ */
+ public static final Type STYLE = new Type(0x293);
+ /**
+ */
+ public static final Type USESELFS = new Type(0x160);
+ /**
+ */
+ public static final Type VERTICALPAGEBREAKS = new Type(0x1a);
+ /**
+ */
+ public static final Type HORIZONTALPAGEBREAKS = new Type(0x1b);
+ /**
+ */
+ public static final Type SELECTION = new Type(0x1d);
+ /**
+ */
+ public static final Type HLINK = new Type(0x1b8);
+ /**
+ */
+ public static final Type OBJ = new Type(0x5d);
+ /**
+ */
+ public static final Type MSODRAWING = new Type(0xec);
+ /**
+ */
+ public static final Type MSODRAWINGGROUP = new Type(0xeb);
+ /**
+ */
+ public static final Type LEFTMARGIN = new Type(0x26);
+ /**
+ */
+ public static final Type RIGHTMARGIN = new Type(0x27);
+ /**
+ */
+ public static final Type TOPMARGIN = new Type(0x28);
+ /**
+ */
+ public static final Type BOTTOMMARGIN = new Type(0x29);
+ /**
+ */
+ public static final Type EXTERNNAME = new Type(0x23);
+ /**
+ */
+ public static final Type PALETTE = new Type(0x92);
+ /**
+ */
+ public static final Type PLS = new Type(0x4d);
+ /**
+ */
+ public static final Type SCL = new Type(0xa0);
+ /**
+ */
+ public static final Type PANE = new Type(0x41);
+ /**
+ */
+ public static final Type WEIRD1 = new Type(0xef);
+ /**
+ */
+ public static final Type SORT = new Type(0x90);
+ /**
+ */
+ public static final Type CONDFMT = new Type(0x1b0);
+ /**
+ */
+ public static final Type CF = new Type(0x1b1);
+ /**
+ */
+ public static final Type DV = new Type(0x1be);
+ /**
+ */
+ public static final Type DVAL = new Type(0x1b2);
+ /**
+ */
+ public static final Type BUTTONPROPERTYSET = new Type(0x1ba);
+
+ // Chart types
+ /**
+ */
+ public static final Type FONTX = new Type(0x1026);
+ /**
+ */
+ public static final Type IFMT = new Type(0x104e);
+ /**
+ */
+ public static final Type FBI = new Type(0x1060);
+ /**
+ */
+ public static final Type ALRUNS = new Type(0x1050);
+ /**
+ */
+ public static final Type SERIES = new Type(0x1003);
+ /**
+ */
+ public static final Type SERIESLIST = new Type(0x1016);
+ /**
+ */
+ public static final Type SBASEREF = new Type(0x1048);
+ /**
+ */
+ public static final Type UNKNOWN = new Type(0xffff);
+
+ // Unknown types
+ public static final Type U1C0 = new Type(0x1c0);
+ public static final Type U1C1 = new Type(0x1c1);
+
+}
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/WorkbookMethods.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/WorkbookMethods.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/WorkbookMethods.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,53 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import jxl.Sheet;
+/**
+ * An interface containing some common workbook methods. This so that
+ * objects which are re-used for both readable and writable workbooks
+ * can still make the same method calls on a workbook
+ */
+public interface WorkbookMethods
+{
+ /**
+ * Gets the specified sheet within this workbook
+ *
+ * @param index the zero based index of the required sheet
+ * @return The sheet specified by the index
+ */
+ public Sheet getReadSheet(int index);
+
+ /**
+ * Gets the name at the specified index
+ *
+ * @param index the index into the name table
+ * @return the name of the cell
+ */
+ public String getName(int index);
+
+ /**
+ * Gets the index of the name record for the name
+ *
+ * @param name the name
+ * @return the index in the name table
+ */
+ public int getNameIndex(String name);
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/WorkspaceInformationRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/WorkspaceInformationRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/WorkspaceInformationRecord.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,159 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Logger;
+import jxl.read.biff.Record;
+
+/**
+ * A record detailing whether the sheet is protected
+ */
+public class WorkspaceInformationRecord extends WritableRecordData
+{
+ // the logger
+ private static Logger logger =
+ Logger.getLogger(WorkspaceInformationRecord.class);
+
+ /**
+ * The options byte
+ */
+ private int wsoptions;
+
+ /**
+ * The row outlines
+ */
+ private boolean rowOutlines;
+
+ /**
+ * The column outlines
+ */
+ private boolean columnOutlines;
+
+ /**
+ * The fit to pages flag
+ */
+ private boolean fitToPages;
+
+ // the masks
+ private static final int FIT_TO_PAGES = 0x100;
+ private static final int SHOW_ROW_OUTLINE_SYMBOLS = 0x400;
+ private static final int SHOW_COLUMN_OUTLINE_SYMBOLS = 0x800;
+ private static final int DEFAULT_OPTIONS = 0x4c1;
+
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ */
+ public WorkspaceInformationRecord(Record t)
+ {
+ super(t);
+ byte[] data = getRecord().getData();
+
+ wsoptions = IntegerHelper.getInt(data[0], data[1]);
+ fitToPages = (wsoptions | FIT_TO_PAGES) != 0;
+ rowOutlines = (wsoptions | SHOW_ROW_OUTLINE_SYMBOLS) != 0;
+ columnOutlines = (wsoptions | SHOW_COLUMN_OUTLINE_SYMBOLS) != 0;
+ }
+
+ /**
+ * Constructs this object from the raw data
+ */
+ public WorkspaceInformationRecord()
+ {
+ super(Type.WSBOOL);
+ wsoptions = DEFAULT_OPTIONS;
+ }
+
+ /**
+ * Gets the fit to pages flag
+ *
+ * @return TRUE if fit to pages is set
+ */
+ public boolean getFitToPages()
+ {
+ return fitToPages;
+ }
+
+ /**
+ * Sets the fit to page flag
+ *
+ * @param b fit to page indicator
+ */
+ public void setFitToPages(boolean b)
+ {
+ fitToPages = b;
+ }
+
+ /**
+ * Sets the outlines
+ */
+ public void setRowOutlines(boolean ro)
+ {
+ rowOutlines = true;
+ }
+
+ /**
+ * Sets the outlines
+ */
+ public void setColumnOutlines(boolean ro)
+ {
+ rowOutlines = true;
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[2];
+
+ if (fitToPages)
+ {
+ wsoptions |= FIT_TO_PAGES;
+ }
+
+ if (rowOutlines)
+ {
+ wsoptions |= SHOW_ROW_OUTLINE_SYMBOLS;
+ }
+
+ if (columnOutlines)
+ {
+ wsoptions |= SHOW_COLUMN_OUTLINE_SYMBOLS;
+ }
+
+ IntegerHelper.getTwoBytes(wsoptions, data, 0);
+
+ return data;
+ }
+}
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/WritableRecordData.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/WritableRecordData.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/WritableRecordData.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,146 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff;
+
+import common.Logger;
+
+import jxl.read.biff.Record;
+
+/**
+ * Extension of the standard RecordData which is used to support those
+ * records which, once read, may also be written
+ */
+public abstract class WritableRecordData extends RecordData
+ implements ByteData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(WritableRecordData.class);
+ /**
+ * The maximum length allowed by Excel for any record length
+ */
+ protected static final int maxRecordLength = 8228;
+
+ /**
+ * Constructor used by the writable records
+ *
+ * @param t the biff type of this record
+ */
+ protected WritableRecordData(Type t)
+ {
+ super(t);
+ }
+
+ /**
+ * Constructor used when reading a record
+ *
+ * @param t the raw data read from the biff file
+ */
+ protected WritableRecordData(Record t)
+ {
+ super(t);
+ }
+
+ /**
+ * Used when writing out records. This portion of the method handles the
+ * biff code and the length of the record and appends on the data retrieved
+ * from the subclasses
+ *
+ * @return the full record data to be written out to the compound file
+ */
+ public final byte[] getBytes()
+ {
+ byte[] data = getData();
+
+ int dataLength = data.length;
+
+ // Don't the call the automatic continuation code for now
+ // Assert.verify(dataLength <= maxRecordLength - 4);
+ // If the bytes length is greater than the max record length
+ // then split out the data set into continue records
+ if (data.length > maxRecordLength - 4)
+ {
+ dataLength = maxRecordLength - 4;
+ data = handleContinueRecords(data);
+ }
+
+ byte[] bytes = new byte[data.length + 4];
+
+ System.arraycopy(data, 0, bytes, 4, data.length);
+
+ IntegerHelper.getTwoBytes(getCode(), bytes, 0);
+ IntegerHelper.getTwoBytes(dataLength, bytes, 2);
+
+ return bytes;
+ }
+
+ /**
+ * The number of bytes for this record exceeds the maximum record
+ * length, so a continue is required
+ * @param data the raw data
+ * @return the continued data
+ */
+ private byte[] handleContinueRecords(byte[] data)
+ {
+ // Deduce the number of continue records
+ int continuedData = data.length - (maxRecordLength - 4);
+ int numContinueRecords = continuedData / (maxRecordLength - 4) + 1;
+
+ // Create the new byte array, allowing for the continue records
+ // code and length
+ byte[] newdata = new byte[data.length + numContinueRecords * 4];
+
+ // Copy the bona fide record data into the beginning of the super
+ // record
+ System.arraycopy(data, 0, newdata, 0, maxRecordLength - 4);
+ int oldarraypos = maxRecordLength - 4;
+ int newarraypos = maxRecordLength - 4;
+
+ // Now handle all the continue records
+ for (int i = 0; i < numContinueRecords; i++)
+ {
+ // The number of bytes to add into the new array
+ int length = Math.min(data.length - oldarraypos, maxRecordLength - 4);
+
+ // Add in the continue record code
+ IntegerHelper.getTwoBytes(Type.CONTINUE.value, newdata, newarraypos);
+ IntegerHelper.getTwoBytes(length, newdata, newarraypos + 2);
+
+ // Copy in as much of the new data as possible
+ System.arraycopy(data, oldarraypos, newdata, newarraypos + 4, length);
+
+ // Update the position counters
+ oldarraypos += length;
+ newarraypos += length + 4;
+ }
+
+ return newdata;
+ }
+
+ /**
+ * Abstract method called by the getBytes method. Subclasses implement
+ * this method to incorporate their specific binary data - excluding the
+ * biff code and record length, which is handled by this class
+ *
+ * @return subclass specific biff data
+ */
+ protected abstract byte[] getData();
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/XFRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/XFRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/XFRecord.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,1687 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+
+package jxl.biff;
+
+import java.text.DateFormat;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.format.Alignment;
+import jxl.format.Border;
+import jxl.format.BorderLineStyle;
+import jxl.format.CellFormat;
+import jxl.format.Colour;
+import jxl.format.Font;
+import jxl.format.Format;
+import jxl.format.Orientation;
+import jxl.format.Pattern;
+import jxl.format.VerticalAlignment;
+import jxl.read.biff.Record;
+
+/**
+ * Holds an extended formatting record
+ */
+public class XFRecord extends WritableRecordData implements CellFormat
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(XFRecord.class);
+
+ /**
+ * The index to the format record
+ */
+ public int formatIndex;
+
+ /**
+ * The index of the parent format
+ */
+ private int parentFormat;
+
+ /**
+ * The format type
+ */
+ private XFType xfFormatType;
+
+ /**
+ * Indicates whether this is a date formatting record
+ */
+ private boolean date;
+
+ /**
+ * Indicates whether this is a number formatting record
+ */
+ private boolean number;
+
+ /**
+ * The date format for this record. Deduced when the record is
+ * read in from a spreadsheet
+ */
+ private DateFormat dateFormat;
+
+ /**
+ * The number format for this record. Deduced when the record is read in
+ * from a spreadsheet
+ */
+ private NumberFormat numberFormat;
+
+ /**
+ * The used attribute. Needs to be preserved in order to get accurate
+ * rationalization
+ */
+ private byte usedAttributes;
+ /**
+ * The index to the font record used by this XF record
+ */
+ private int fontIndex;
+ /**
+ * Flag to indicate whether this XF record represents a locked cell
+ */
+ private boolean locked;
+ /**
+ * Flag to indicate whether this XF record is hidden
+ */
+ private boolean hidden;
+ /**
+ * The alignment for this cell (left, right, centre)
+ */
+ private Alignment align;
+ /**
+ * The vertical alignment for the cell (top, bottom, centre)
+ */
+ private VerticalAlignment valign;
+ /**
+ * The orientation of the cell
+ */
+ private Orientation orientation;
+ /**
+ * Flag to indicates whether the data (normally text) in the cell will be
+ * wrapped around to fit in the cell width
+ */
+ private boolean wrap;
+
+ /**
+ * Indentation of the cell text
+ */
+ private int indentation;
+
+ /**
+ * Flag to indicate that this format is shrink to fit
+ */
+ private boolean shrinkToFit;
+
+ /**
+ * The border indicator for the left of this cell
+ */
+ private BorderLineStyle leftBorder;
+ /**
+ * The border indicator for the right of the cell
+ */
+ private BorderLineStyle rightBorder;
+ /**
+ * The border indicator for the top of the cell
+ */
+ private BorderLineStyle topBorder;
+ /**
+ * The border indicator for the bottom of the cell
+ */
+ private BorderLineStyle bottomBorder;
+
+ /**
+ * The border colour for the left of the cell
+ */
+ private Colour leftBorderColour;
+ /**
+ * The border colour for the right of the cell
+ */
+ private Colour rightBorderColour;
+ /**
+ * The border colour for the top of the cell
+ */
+ private Colour topBorderColour;
+ /**
+ * The border colour for the bottom of the cell
+ */
+ private Colour bottomBorderColour;
+
+ /**
+ * The background colour
+ */
+ private Colour backgroundColour;
+ /**
+ * The background pattern
+ */
+ private Pattern pattern;
+ /**
+ * The options mask which is used to store the processed cell options (such
+ * as alignment, borders etc)
+ */
+ private int options;
+ /**
+ * The index of this XF record within the workbook
+ */
+ private int xfIndex;
+ /**
+ * The font object for this XF record
+ */
+ private FontRecord font;
+ /**
+ * The format object for this XF record. This is used when creating
+ * a writable record
+ */
+ private DisplayFormat format;
+ /**
+ * Flag to indicate whether this XF record has been initialized
+ */
+ private boolean initialized;
+
+ /**
+ * Indicates whether this cell was constructed by an API or read
+ * from an existing Excel file
+ */
+ private boolean read;
+
+ /**
+ * The excel format for this record. This is used to display the actual
+ * excel format string back to the user (eg. when generating certain
+ * types of XML document) as opposed to the java equivalent
+ */
+ private Format excelFormat;
+
+ /**
+ * Flag to indicate whether the format information has been initialized.
+ * This is false if the xf record has been read in, but true if it
+ * has been written
+ */
+ private boolean formatInfoInitialized;
+
+ /**
+ * Flag to indicate whether this cell was copied. If it was copied, then
+ * it can be set to uninitialized, allowing us to change certain format
+ * information
+ */
+ private boolean copied;
+
+ /**
+ * A handle to the formatting records. The purpose of this is
+ * to read the formatting information back, for the purposes of
+ * output eg. to some form of XML
+ */
+ private FormattingRecords formattingRecords;
+
+ /**
+ * Constants for the used attributes
+ */
+ private static final int USE_FONT = 0x4;
+ private static final int USE_FORMAT = 0x8;
+ private static final int USE_ALIGNMENT = 0x10;
+ private static final int USE_BORDER = 0x20;
+ private static final int USE_BACKGROUND = 0x40;
+ private static final int USE_PROTECTION = 0x80;
+ private static final int USE_DEFAULT_VALUE=0xf8;
+
+ /**
+ * The list of built in date format values
+ */
+ private static final int[] dateFormats = new int[]
+ {0xe,
+ 0xf,
+ 0x10,
+ 0x11,
+ 0x12,
+ 0x13,
+ 0x14,
+ 0x15,
+ 0x16,
+ 0x2d,
+ 0x2e,
+ 0x2f};
+
+ /**
+ * The list of java date format equivalents
+ */
+ private static final DateFormat[] javaDateFormats = new DateFormat[]
+ {SimpleDateFormat.getDateInstance(DateFormat.SHORT),
+ SimpleDateFormat.getDateInstance(DateFormat.MEDIUM),
+ new SimpleDateFormat("d-MMM"),
+ new SimpleDateFormat("MMM-yy"),
+ new SimpleDateFormat("h:mm a"),
+ new SimpleDateFormat("h:mm:ss a"),
+ new SimpleDateFormat("H:mm"),
+ new SimpleDateFormat("H:mm:ss"),
+ new SimpleDateFormat("M/d/yy H:mm"),
+ new SimpleDateFormat("mm:ss"),
+ new SimpleDateFormat("H:mm:ss"),
+ new SimpleDateFormat("mm:ss.S")};
+
+ /**
+ * The list of built in number format values
+ */
+ private static int[] numberFormats = new int[]
+ {0x1,
+ 0x2,
+ 0x3,
+ 0x4,
+ 0x5,
+ 0x6,
+ 0x7,
+ 0x8,
+ 0x9,
+ 0xa,
+ 0xb,
+ 0x25,
+ 0x26,
+ 0x27,
+ 0x28,
+ 0x29,
+ 0x2a,
+ 0x2b,
+ 0x2c,
+ 0x30};
+
+ /**
+ * The list of java number format equivalents
+ */
+ private static NumberFormat[] javaNumberFormats = new NumberFormat[]
+ {new DecimalFormat("0"),
+ new DecimalFormat("0.00"),
+ new DecimalFormat("#,##0"),
+ new DecimalFormat("#,##0.00"),
+ new DecimalFormat("$#,##0;($#,##0)"),
+ new DecimalFormat("$#,##0;($#,##0)"),
+ new DecimalFormat("$#,##0.00;($#,##0.00)"),
+ new DecimalFormat("$#,##0.00;($#,##0.00)"),
+ new DecimalFormat("0%"),
+ new DecimalFormat("0.00%"),
+ new DecimalFormat("0.00E00"),
+ new DecimalFormat("#,##0;(#,##0)"),
+ new DecimalFormat("#,##0;(#,##0)"),
+ new DecimalFormat("#,##0.00;(#,##0.00)"),
+ new DecimalFormat("#,##0.00;(#,##0.00)"),
+ new DecimalFormat("#,##0;(#,##0)"),
+ new DecimalFormat("$#,##0;($#,##0)"),
+ new DecimalFormat("#,##0.00;(#,##0.00)"),
+ new DecimalFormat("$#,##0.00;($#,##0.00)"),
+ new DecimalFormat("##0.0E0")};
+
+ // Type to distinguish between biff7 and biff8
+ private static class BiffType {};
+
+ public static final BiffType biff8 = new BiffType();
+ public static final BiffType biff7 = new BiffType();
+
+ /**
+ * The biff type
+ */
+ private BiffType biffType;
+
+ // Type to distinguish between cell and style records
+ private static class XFType
+ {
+ }
+ protected static final XFType cell = new XFType();
+ protected static final XFType style = new XFType();
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param bt the biff type
+ */
+ public XFRecord(Record t, WorkbookSettings ws, BiffType bt)
+ {
+ super(t);
+
+ biffType = bt;
+
+ byte[] data = getRecord().getData();
+
+ fontIndex = IntegerHelper.getInt(data[0], data[1]);
+ formatIndex = IntegerHelper.getInt(data[2], data[3]);
+ date = false;
+ number = false;
+
+
+ // Compare against the date formats
+ for (int i = 0; i < dateFormats.length && date == false; i++)
+ {
+ if (formatIndex == dateFormats[i])
+ {
+ date = true;
+ dateFormat = javaDateFormats[i];
+ }
+ }
+
+ // Compare against the number formats
+ for (int i = 0; i < numberFormats.length && number == false; i++)
+ {
+ if (formatIndex == numberFormats[i])
+ {
+ number = true;
+ DecimalFormat df = (DecimalFormat) javaNumberFormats[i].clone();
+ DecimalFormatSymbols symbols =
+ new DecimalFormatSymbols(ws.getLocale());
+ df.setDecimalFormatSymbols(symbols);
+ numberFormat = df;
+ //numberFormat = javaNumberFormats[i];
+ }
+ }
+
+ // Initialize the parent format and the type
+ int cellAttributes = IntegerHelper.getInt(data[4], data[5]);
+ parentFormat = (cellAttributes & 0xfff0) >> 4;
+
+ int formatType = cellAttributes & 0x4;
+ xfFormatType = formatType == 0 ? cell : style;
+ locked = ((cellAttributes & 0x1) != 0);
+ hidden = ((cellAttributes & 0x2) != 0);
+
+ if (xfFormatType == cell &&
+ (parentFormat & 0xfff) == 0xfff)
+ {
+ // Something is screwy with the parent format - set to zero
+ parentFormat = 0;
+ logger.warn("Invalid parent format found - ignoring");
+ }
+
+ initialized = false;
+ read = true;
+ formatInfoInitialized = false;
+ copied = false;
+ }
+
+ /**
+ * A constructor used when creating a writable record
+ *
+ * @param fnt the font
+ * @param form the format
+ */
+ public XFRecord(FontRecord fnt, DisplayFormat form)
+ {
+ super(Type.XF);
+
+ initialized = false;
+ locked = true;
+ hidden = false;
+ align = Alignment.GENERAL;
+ valign = VerticalAlignment.BOTTOM;
+ orientation = Orientation.HORIZONTAL;
+ wrap = false;
+ leftBorder = BorderLineStyle.NONE;
+ rightBorder = BorderLineStyle.NONE;
+ topBorder = BorderLineStyle.NONE;
+ bottomBorder = BorderLineStyle.NONE;
+ leftBorderColour = Colour.AUTOMATIC;
+ rightBorderColour = Colour.AUTOMATIC;
+ topBorderColour = Colour.AUTOMATIC;
+ bottomBorderColour = Colour.AUTOMATIC;
+ pattern = Pattern.NONE;
+ backgroundColour = Colour.DEFAULT_BACKGROUND;
+ indentation = 0;
+ shrinkToFit = false;
+ usedAttributes = (byte) (USE_FONT | USE_FORMAT |
+ USE_BACKGROUND | USE_ALIGNMENT | USE_BORDER);
+
+ // This will be set by the initialize method and the subclass respectively
+ parentFormat = 0;
+ xfFormatType = null;
+
+ font = fnt;
+ format = form;
+ biffType = biff8;
+ read = false;
+ copied = false;
+ formatInfoInitialized = true;
+
+ Assert.verify(font != null);
+ Assert.verify(format != null);
+ }
+
+ /**
+ * Copy constructor. Used for copying writable formats, typically
+ * when duplicating formats to handle merged cells
+ *
+ * @param fmt XFRecord
+ */
+ protected XFRecord(XFRecord fmt)
+ {
+ super(Type.XF);
+
+ initialized = false;
+ locked = fmt.locked;
+ hidden = fmt.hidden;
+ align = fmt.align;
+ valign = fmt.valign;
+ orientation = fmt.orientation;
+ wrap = fmt.wrap;
+ leftBorder = fmt.leftBorder;
+ rightBorder = fmt.rightBorder;
+ topBorder = fmt.topBorder;
+ bottomBorder = fmt.bottomBorder;
+ leftBorderColour = fmt.leftBorderColour;
+ rightBorderColour = fmt.rightBorderColour;
+ topBorderColour = fmt.topBorderColour;
+ bottomBorderColour = fmt.bottomBorderColour;
+ pattern = fmt.pattern;
+ xfFormatType = fmt.xfFormatType;
+ indentation = fmt.indentation;
+ shrinkToFit = fmt.shrinkToFit;
+ parentFormat = fmt.parentFormat;
+ backgroundColour = fmt.backgroundColour;
+
+ // Shallow copy is sufficient for these purposes
+ font = fmt.font;
+ format = fmt.format;
+
+ fontIndex = fmt.fontIndex;
+ formatIndex = fmt.formatIndex;
+
+ formatInfoInitialized = fmt.formatInfoInitialized;
+
+ biffType = biff8;
+ read = false;
+ copied = true;
+ }
+
+ /**
+ * A public copy constructor which can be used for copy formats between
+ * different sheets. Unlike the the other copy constructor, this
+ * version does a deep copy
+ *
+ * @param cellFormat the format to copy
+ */
+ protected XFRecord(CellFormat cellFormat)
+ {
+ super(Type.XF);
+
+ Assert.verify(cellFormat != null);
+ Assert.verify(cellFormat instanceof XFRecord);
+ XFRecord fmt = (XFRecord) cellFormat;
+
+ if (!fmt.formatInfoInitialized)
+ {
+ fmt.initializeFormatInformation();
+ }
+
+ locked = fmt.locked;
+ hidden = fmt.hidden;
+ align = fmt.align;
+ valign = fmt.valign;
+ orientation = fmt.orientation;
+ wrap = fmt.wrap;
+ leftBorder = fmt.leftBorder;
+ rightBorder = fmt.rightBorder;
+ topBorder = fmt.topBorder;
+ bottomBorder = fmt.bottomBorder;
+ leftBorderColour = fmt.leftBorderColour;
+ rightBorderColour = fmt.rightBorderColour;
+ topBorderColour = fmt.topBorderColour;
+ bottomBorderColour = fmt.bottomBorderColour;
+ pattern = fmt.pattern;
+ xfFormatType = fmt.xfFormatType;
+ parentFormat = fmt.parentFormat;
+ indentation = fmt.indentation;
+ shrinkToFit = fmt.shrinkToFit;
+ backgroundColour = fmt.backgroundColour;
+
+ // Deep copy of the font
+ font = new FontRecord(fmt.getFont());
+
+ // Copy the format
+ if (fmt.getFormat() == null)
+ {
+ // format is writable
+ if (fmt.format.isBuiltIn())
+ {
+ format = fmt.format;
+ }
+ else
+ {
+ // Format is not built in, so do a deep copy
+ format = new FormatRecord((FormatRecord) fmt.format);
+ }
+ }
+ else if (fmt.getFormat() instanceof BuiltInFormat)
+ {
+ // read excel format is built in
+ excelFormat = (BuiltInFormat) fmt.excelFormat;
+ format = (BuiltInFormat) fmt.excelFormat;
+ }
+ else
+ {
+ // read excel format is user defined
+ Assert.verify(fmt.formatInfoInitialized);
+
+ // in this case FormattingRecords should initialize the excelFormat
+ // field with an instance of FormatRecord
+ Assert.verify(fmt.excelFormat instanceof FormatRecord);
+
+ // Format is not built in, so do a deep copy
+ FormatRecord fr = new FormatRecord((FormatRecord) fmt.excelFormat);
+
+ // Set both format fields to be the same object, since
+ // FormatRecord implements all the necessary interfaces
+ excelFormat = fr;
+ format = fr;
+ }
+
+ biffType = biff8;
+
+ // The format info should be all OK by virtue of the deep copy
+ formatInfoInitialized = true;
+
+ // This format was not read in
+ read = false;
+
+ // Treat this as a new cell record, so set the copied flag to false
+ copied = false;
+
+ // The font or format indexes need to be set, so set initialized to false
+ initialized = false;
+ }
+
+ /**
+ * Gets the java date format for this format record
+ *
+ * @return returns the date format
+ */
+ public DateFormat getDateFormat()
+ {
+ return dateFormat;
+ }
+
+ /**
+ * Gets the java number format for this format record
+ *
+ * @return returns the number format
+ */
+ public NumberFormat getNumberFormat()
+ {
+ return numberFormat;
+ }
+
+ /**
+ * Gets the lookup number of the format record
+ *
+ * @return returns the lookup number of the format record
+ */
+ public int getFormatRecord()
+ {
+ return formatIndex;
+ }
+
+ /**
+ * Sees if this format is a date format
+ *
+ * @return TRUE if this refers to a built in date format
+ */
+ public boolean isDate()
+ {
+ return date;
+ }
+
+ /**
+ * Sees if this format is a number format
+ *
+ * @return TRUE if this refers to a built in date format
+ */
+ public boolean isNumber()
+ {
+ return number;
+ }
+
+ /**
+ * Converts the various fields into binary data. If this object has
+ * been read from an Excel file rather than being requested by a user (ie.
+ * if the read flag is TRUE) then
+ * no processing takes place and the raw data is simply returned.
+ *
+ * @return the raw data for writing
+ */
+ public byte[] getData()
+ {
+ // Format rationalization process means that we always want to
+ // regenerate the format info - even if the spreadsheet was
+ // read in
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+
+ byte[] data = new byte[20];
+
+ IntegerHelper.getTwoBytes(fontIndex, data, 0);
+ IntegerHelper.getTwoBytes(formatIndex, data, 2);
+
+ // Do the cell attributes
+ int cellAttributes = 0;
+
+ if (getLocked())
+ {
+ cellAttributes |= 0x01;
+ }
+
+ if (getHidden())
+ {
+ cellAttributes |= 0x02;
+ }
+
+ if (xfFormatType == style)
+ {
+ cellAttributes |= 0x04;
+ parentFormat = 0xffff;
+ }
+
+ cellAttributes |= (parentFormat << 4);
+
+ IntegerHelper.getTwoBytes(cellAttributes, data, 4);
+
+ int alignMask = align.getValue();
+
+ if (wrap)
+ {
+ alignMask |= 0x08;
+ }
+
+ alignMask |= (valign.getValue() << 4);
+
+ alignMask |= (orientation.getValue() << 8);
+
+ IntegerHelper.getTwoBytes(alignMask, data, 6);
+
+ data[9] = (byte) 0x10;
+
+ // Set the borders
+ int borderMask = leftBorder.getValue();
+ borderMask |= (rightBorder.getValue() << 4);
+ borderMask |= (topBorder.getValue() << 8);
+ borderMask |= (bottomBorder.getValue() << 12);
+
+ IntegerHelper.getTwoBytes(borderMask, data, 10);
+
+ // Set the border palette information if border mask is non zero
+ // Hard code the colours to be black
+ if (borderMask != 0)
+ {
+ byte lc = (byte)leftBorderColour.getValue();
+ byte rc = (byte)rightBorderColour.getValue();
+ byte tc = (byte)topBorderColour.getValue();
+ byte bc = (byte)bottomBorderColour.getValue();
+
+ int sideColourMask = (lc & 0x7f) | ((rc & 0x7f) << 7);
+ int topColourMask = (tc & 0x7f) | ((bc & 0x7f) << 7);
+
+ IntegerHelper.getTwoBytes(sideColourMask, data, 12);
+ IntegerHelper.getTwoBytes(topColourMask, data, 14);
+ }
+
+ // Set the background pattern
+ int patternVal = pattern.getValue() << 10;
+ IntegerHelper.getTwoBytes(patternVal, data, 16);
+
+ // Set the colour palette
+ int colourPaletteMask = backgroundColour.getValue();
+ colourPaletteMask |= (0x40 << 7);
+ IntegerHelper.getTwoBytes(colourPaletteMask, data, 18);
+
+ // Set the cell options
+ options |= indentation & 0x0f;
+
+ if (shrinkToFit)
+ {
+ options |= 0x10;
+ }
+ else
+ {
+ options &= 0xef;
+ }
+
+ data[8] = (byte) options;
+
+ if (biffType == biff8)
+ {
+ data[9] = (byte) usedAttributes;
+ }
+
+ return data;
+ }
+
+ /**
+ * Accessor for the locked flag
+ *
+ * @return TRUE if this XF record locks cells, FALSE otherwise
+ */
+ protected final boolean getLocked()
+ {
+ return locked;
+ }
+
+ /**
+ * Accessor for the hidden flag
+ *
+ * @return TRUE if this XF record hides the cell, FALSE otherwise
+ */
+ protected final boolean getHidden()
+ {
+ return hidden;
+ }
+
+ /**
+ * Sets whether or not this XF record locks the cell
+ *
+ * @param l the locked flag
+ */
+ protected final void setXFLocked(boolean l)
+ {
+ locked = l;
+ usedAttributes |= USE_PROTECTION;
+ }
+
+ /**
+ * Sets the cell options
+ *
+ * @param opt the cell options
+ */
+ protected final void setXFCellOptions(int opt)
+ {
+ options |= opt;
+ }
+
+ /**
+ * Sets the horizontal alignment for the data in this cell.
+ * This method should only be called from its writable subclass
+ * CellXFRecord
+ *
+ * @param a the alignment
+ */
+ protected void setXFAlignment(Alignment a)
+ {
+ Assert.verify(!initialized);
+ align = a;
+ usedAttributes |= USE_ALIGNMENT;
+ }
+
+ /**
+ * Sets the indentation
+ *
+ * @param i the indentation
+ */
+ protected void setXFIndentation(int i)
+ {
+ Assert.verify(!initialized);
+ indentation = i;
+ usedAttributes |= USE_ALIGNMENT;
+ }
+
+ /**
+ * Sets the shrink to fit flag
+ *
+ * @param s the shrink to fit flag
+ */
+ protected void setXFShrinkToFit(boolean s)
+ {
+ Assert.verify(!initialized);
+ shrinkToFit = s;
+ usedAttributes |= USE_ALIGNMENT;
+ }
+
+ /**
+ * Gets the horizontal cell alignment
+ *
+ * @return the alignment
+ */
+ public Alignment getAlignment()
+ {
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+
+ return align;
+ }
+
+ /**
+ * Gets the indentation
+ *
+ * @return the indentation
+ */
+ public int getIndentation()
+ {
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+
+ return indentation;
+ }
+
+ /**
+ * Gets the shrink to fit flag
+ *
+ * @return TRUE if this format is shrink to fit, FALSE otherise
+ */
+ public boolean isShrinkToFit()
+ {
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+
+ return shrinkToFit;
+ }
+
+ /**
+ * Accessor for whether a particular cell is locked
+ *
+ * @return TRUE if this cell is locked, FALSE otherwise
+ */
+ public boolean isLocked()
+ {
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+
+ return locked;
+ }
+
+
+ /**
+ * Gets the vertical cell alignment
+ *
+ * @return the alignment
+ */
+ public VerticalAlignment getVerticalAlignment()
+ {
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+
+ return valign;
+ }
+
+ /**
+ * Gets the orientation
+ *
+ * @return the orientation
+ */
+ public Orientation getOrientation()
+ {
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+
+ return orientation;
+ }
+
+ /**
+ * Sets the horizontal alignment for the data in this cell.
+ * This method should only be called from its writable subclass
+ * CellXFRecord
+ *
+ * @param c the background colour
+ * @param p the background pattern
+ */
+ protected void setXFBackground(Colour c, Pattern p)
+ {
+ Assert.verify(!initialized);
+ backgroundColour = c;
+ pattern = p;
+ usedAttributes |= USE_BACKGROUND;
+ }
+
+ /**
+ * Gets the background colour used by this cell
+ *
+ * @return the foreground colour
+ */
+ public Colour getBackgroundColour()
+ {
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+
+ return backgroundColour;
+ }
+
+ /**
+ * Gets the pattern used by this cell format
+ *
+ * @return the background pattern
+ */
+ public Pattern getPattern()
+ {
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+
+ return pattern;
+ }
+
+ /**
+ * Sets the vertical alignment for the data in this cell
+ * This method should only be called from its writable subclass
+ * CellXFRecord
+
+ *
+ * @param va the vertical alignment
+ */
+ protected void setXFVerticalAlignment(VerticalAlignment va)
+ {
+ Assert.verify(!initialized);
+ valign = va;
+ usedAttributes |= USE_ALIGNMENT;
+ }
+
+ /**
+ * Sets the vertical alignment for the data in this cell
+ * This method should only be called from its writable subclass
+ * CellXFRecord
+
+ *
+ * @param o the orientation
+ */
+ protected void setXFOrientation(Orientation o)
+ {
+ Assert.verify(!initialized);
+ orientation = o;
+ usedAttributes |= USE_ALIGNMENT;
+ }
+
+ /**
+ * Sets whether the data in this cell is wrapped
+ * This method should only be called from its writable subclass
+ * CellXFRecord
+ *
+ * @param w the wrap flag
+ */
+ protected void setXFWrap(boolean w)
+ {
+ Assert.verify(!initialized);
+ wrap = w;
+ usedAttributes |= USE_ALIGNMENT;
+ }
+
+ /**
+ * Gets whether or not the contents of this cell are wrapped
+ *
+ * @return TRUE if this cell's contents are wrapped, FALSE otherwise
+ */
+ public boolean getWrap()
+ {
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+
+ return wrap;
+ }
+
+ /**
+ * Sets the border for this cell
+ * This method should only be called from its writable subclass
+ * CellXFRecord
+ *
+ * @param b the border
+ * @param ls the border line style
+ */
+ protected void setXFBorder(Border b, BorderLineStyle ls, Colour c)
+ {
+ Assert.verify(!initialized);
+
+ if (c == Colour.BLACK || c == Colour.UNKNOWN)
+ {
+ c = Colour.PALETTE_BLACK;
+ }
+
+ if (b == Border.LEFT)
+ {
+ leftBorder = ls;
+ leftBorderColour = c;
+ }
+ else if (b == Border.RIGHT)
+ {
+ rightBorder = ls;
+ rightBorderColour = c;
+ }
+ else if (b == Border.TOP)
+ {
+ topBorder = ls;
+ topBorderColour = c;
+ }
+ else if (b == Border.BOTTOM)
+ {
+ bottomBorder = ls;
+ bottomBorderColour = c;
+ }
+
+ usedAttributes |= USE_BORDER;
+
+ return;
+ }
+
+
+ /**
+ * Gets the line style for the given cell border
+ * If a border type of ALL or NONE is specified, then a line style of
+ * NONE is returned
+ *
+ * @param border the cell border we are interested in
+ * @return the line style of the specified border
+ */
+ public BorderLineStyle getBorder(Border border)
+ {
+ return getBorderLine(border);
+ }
+
+ /**
+ * Gets the line style for the given cell border
+ * If a border type of ALL or NONE is specified, then a line style of
+ * NONE is returned
+ *
+ * @param border the cell border we are interested in
+ * @return the line style of the specified border
+ */
+ public BorderLineStyle getBorderLine(Border border)
+ {
+ // Don't bother with the short cut records
+ if (border == Border.NONE ||
+ border == Border.ALL)
+ {
+ return BorderLineStyle.NONE;
+ }
+
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+
+ if (border == Border.LEFT)
+ {
+ return leftBorder;
+ }
+ else if (border == Border.RIGHT)
+ {
+ return rightBorder;
+ }
+ else if (border == Border.TOP)
+ {
+ return topBorder;
+ }
+ else if (border == Border.BOTTOM)
+ {
+ return bottomBorder;
+ }
+
+ return BorderLineStyle.NONE;
+ }
+
+ /**
+ * Gets the line style for the given cell border
+ * If a border type of ALL or NONE is specified, then a line style of
+ * NONE is returned
+ *
+ * @param border the cell border we are interested in
+ * @return the line style of the specified border
+ */
+ public Colour getBorderColour(Border border)
+ {
+ // Don't bother with the short cut records
+ if (border == Border.NONE ||
+ border == Border.ALL)
+ {
+ return Colour.PALETTE_BLACK;
+ }
+
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+
+ if (border == Border.LEFT)
+ {
+ return leftBorderColour;
+ }
+ else if (border == Border.RIGHT)
+ {
+ return rightBorderColour;
+ }
+ else if (border == Border.TOP)
+ {
+ return topBorderColour;
+ }
+ else if (border == Border.BOTTOM)
+ {
+ return bottomBorderColour;
+ }
+
+ return Colour.BLACK;
+ }
+
+
+ /**
+ * Determines if this cell format has any borders at all. Used to
+ * set the new borders when merging a group of cells
+ *
+ * @return TRUE if this cell has any borders, FALSE otherwise
+ */
+ public final boolean hasBorders()
+ {
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+
+ if (leftBorder == BorderLineStyle.NONE &&
+ rightBorder == BorderLineStyle.NONE &&
+ topBorder == BorderLineStyle.NONE &&
+ bottomBorder == BorderLineStyle.NONE)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * If this cell has not been read in from an existing Excel sheet,
+ * then initializes this record with the XF index passed in. Calls
+ * initialized on the font and format record
+ *
+ * @param pos the xf index to initialize this record with
+ * @param fr the containing formatting records
+ * @param fonts the container for the fonts
+ * @exception NumFormatRecordsException
+ */
+ public final void initialize(int pos, FormattingRecords fr, Fonts fonts)
+ throws NumFormatRecordsException
+ {
+ xfIndex = pos;
+ formattingRecords = fr;
+
+ // If this file has been read in or copied,
+ // the font and format indexes will
+ // already be initialized, so just set the initialized flag and
+ // return
+ if (read || copied)
+ {
+ initialized = true;
+ return;
+ }
+
+ if (!font.isInitialized())
+ {
+ fonts.addFont(font);
+ }
+
+ if (!format.isInitialized())
+ {
+ fr.addFormat(format);
+ }
+
+ fontIndex = font.getFontIndex();
+ formatIndex = format.getFormatIndex();
+
+ initialized = true;
+ }
+
+ /**
+ * Resets the initialize flag. This is called by the constructor of
+ * WritableWorkbookImpl to reset the statically declared fonts
+ */
+ public final void uninitialize()
+ {
+ // As the default formats are cloned internally, the initialized
+ // flag should never be anything other than false
+ if (initialized == true)
+ {
+ logger.warn("A default format has been initialized");
+ }
+ initialized = false;
+ }
+
+ /**
+ * Sets the XF index. Called when rationalizing the XF records
+ * immediately prior to writing
+ *
+ * @param xfi the new xf index
+ */
+ final void setXFIndex(int xfi)
+ {
+ xfIndex = xfi;
+ }
+
+ /**
+ * Accessor for the XF index
+ *
+ * @return the XF index for this cell
+ */
+ public final int getXFIndex()
+ {
+ return xfIndex;
+ }
+
+ /**
+ * Accessor to see if this format is initialized
+ *
+ * @return TRUE if this format is initialized, FALSE otherwise
+ */
+ public final boolean isInitialized()
+ {
+ return initialized;
+ }
+
+ /**
+ * Accessor to see if this format was read in. Used when checking merged
+ * cells
+ *
+ * @return TRUE if this XF record was read in, FALSE if it was generated by
+ * the user API
+ */
+ public final boolean isRead()
+ {
+ return read;
+ }
+
+ /**
+ * Gets the format used by this format
+ *
+ * @return the format
+ */
+ public Format getFormat()
+ {
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+ return excelFormat;
+ }
+
+ /**
+ * Gets the font used by this format
+ *
+ * @return the font
+ */
+ public Font getFont()
+ {
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+ return font;
+ }
+
+ /**
+ * Initializes the internal format information from the data read in
+ */
+ private void initializeFormatInformation()
+ {
+ // Initialize the cell format string
+ if (formatIndex < BuiltInFormat.builtIns.length &&
+ BuiltInFormat.builtIns[formatIndex] != null)
+ {
+ excelFormat = BuiltInFormat.builtIns[formatIndex];
+ }
+ else
+ {
+ excelFormat = formattingRecords.getFormatRecord(formatIndex);
+ }
+
+ // Initialize the font
+ font = formattingRecords.getFonts().getFont(fontIndex);
+
+ // Initialize the cell format data from the binary record
+ byte[] data = getRecord().getData();
+
+ // Get the parent record
+ int cellAttributes = IntegerHelper.getInt(data[4], data[5]);
+ parentFormat = (cellAttributes & 0xfff0) >> 4;
+ int formatType = cellAttributes & 0x4;
+ xfFormatType = formatType == 0 ? cell : style;
+ locked = ((cellAttributes & 0x1) != 0);
+ hidden = ((cellAttributes & 0x2) != 0);
+
+ if (xfFormatType == cell &&
+ (parentFormat & 0xfff) == 0xfff)
+ {
+ // Something is screwy with the parent format - set to zero
+ parentFormat = 0;
+ logger.warn("Invalid parent format found - ignoring");
+ }
+
+
+ int alignMask = IntegerHelper.getInt(data[6], data[7]);
+
+ // Get the wrap
+ if ((alignMask & 0x08) != 0)
+ {
+ wrap = true;
+ }
+
+ // Get the horizontal alignment
+ align = Alignment.getAlignment(alignMask & 0x7);
+
+ // Get the vertical alignment
+ valign = VerticalAlignment.getAlignment((alignMask >> 4) & 0x7);
+
+ // Get the orientation
+ orientation = Orientation.getOrientation((alignMask >> 8) & 0xff);
+
+ int attr = IntegerHelper.getInt(data[8], data[9]);
+
+ // Get the indentation
+ indentation = attr & 0x0F;
+
+ // Get the shrink to fit flag
+ shrinkToFit = (attr & 0x10) != 0;
+
+ // Get the used attribute
+ if (biffType == biff8)
+ {
+ usedAttributes = data[9];
+ }
+
+ // Get the borders
+ int borderMask = IntegerHelper.getInt(data[10], data[11]);
+
+ leftBorder = BorderLineStyle.getStyle(borderMask & 0x7);
+ rightBorder = BorderLineStyle.getStyle((borderMask >> 4) & 0x7);
+ topBorder = BorderLineStyle.getStyle((borderMask >> 8) & 0x7);
+ bottomBorder = BorderLineStyle.getStyle((borderMask >> 12) & 0x7);
+
+ int borderColourMask = IntegerHelper.getInt(data[12], data[13]);
+
+ leftBorderColour = Colour.getInternalColour(borderColourMask & 0x7f);
+ rightBorderColour = Colour.getInternalColour
+ ((borderColourMask & 0x3f80) >> 7);
+
+ borderColourMask = IntegerHelper.getInt(data[14], data[15]);
+ topBorderColour = Colour.getInternalColour(borderColourMask & 0x7f);
+ bottomBorderColour = Colour.getInternalColour
+ ((borderColourMask & 0x3f80) >> 7);
+
+ if (biffType == biff8)
+ {
+ // Get the background pattern. This is the six most significant bits
+ int patternVal = IntegerHelper.getInt(data[16], data[17]);
+ patternVal = patternVal & 0xfc00;
+ patternVal = patternVal >> 10;
+ pattern = Pattern.getPattern(patternVal);
+
+ // Get the background colour
+ int colourPaletteMask = IntegerHelper.getInt(data[18], data[19]);
+ backgroundColour = Colour.getInternalColour(colourPaletteMask & 0x3f);
+
+ if (backgroundColour == Colour.UNKNOWN ||
+ backgroundColour == Colour.DEFAULT_BACKGROUND1)
+ {
+ backgroundColour = Colour.DEFAULT_BACKGROUND;
+ }
+ }
+ else
+ {
+ pattern = Pattern.NONE;
+ backgroundColour = Colour.DEFAULT_BACKGROUND;
+ }
+
+ // Set the lazy initialization flag
+ formatInfoInitialized = true;
+ }
+
+ /**
+ * Standard hash code implementation
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ // Must have its formats info initialized in order to compute the hash code
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+
+ int hashValue = 17;
+ int oddPrimeNumber = 37;
+
+ // The boolean fields
+ hashValue = oddPrimeNumber*hashValue + (hidden ? 1:0);
+ hashValue = oddPrimeNumber*hashValue + (locked ? 1:0);
+ hashValue = oddPrimeNumber*hashValue + (wrap ? 1:0);
+ hashValue = oddPrimeNumber*hashValue + (shrinkToFit ? 1:0);
+
+ // The enumerations
+ if (xfFormatType == cell)
+ {
+ hashValue = oddPrimeNumber*hashValue + 1;
+ }
+ else if (xfFormatType == style)
+ {
+ hashValue = oddPrimeNumber*hashValue + 2;
+ }
+
+ hashValue = oddPrimeNumber*hashValue + (align.getValue() + 1);
+ hashValue = oddPrimeNumber*hashValue + (valign.getValue() + 1);
+ hashValue = oddPrimeNumber*hashValue + (orientation.getValue());
+
+ hashValue ^= leftBorder.getDescription().hashCode();
+ hashValue ^= rightBorder.getDescription().hashCode();
+ hashValue ^= topBorder.getDescription().hashCode();
+ hashValue ^= bottomBorder.getDescription().hashCode();
+
+ hashValue = oddPrimeNumber*hashValue + (leftBorderColour.getValue());
+ hashValue = oddPrimeNumber*hashValue + (rightBorderColour.getValue());
+ hashValue = oddPrimeNumber*hashValue + (topBorderColour.getValue());
+ hashValue = oddPrimeNumber*hashValue + (bottomBorderColour.getValue());
+ hashValue = oddPrimeNumber*hashValue + (backgroundColour.getValue());
+ hashValue = oddPrimeNumber*hashValue + (pattern.getValue() + 1);
+
+ // The integer fields
+ hashValue = oddPrimeNumber*hashValue + usedAttributes;
+ hashValue = oddPrimeNumber*hashValue + parentFormat;
+ hashValue = oddPrimeNumber*hashValue + fontIndex;
+ hashValue = oddPrimeNumber*hashValue + formatIndex;
+ hashValue = oddPrimeNumber*hashValue + indentation;
+
+ return hashValue;
+ }
+
+ /**
+ * Equals method. This is called when comparing writable formats
+ * in order to prevent duplicate formats being added to the workbook
+ *
+ * @param o object to compare
+ * @return TRUE if the objects are equal, FALSE otherwise
+ */
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+
+ if (!(o instanceof XFRecord))
+ {
+ return false;
+ }
+
+ XFRecord xfr = (XFRecord) o;
+
+ // Both records must be writable and have their format info initialized
+ if (!formatInfoInitialized)
+ {
+ initializeFormatInformation();
+ }
+
+ if (!xfr.formatInfoInitialized)
+ {
+ xfr.initializeFormatInformation();
+ }
+
+ if (xfFormatType != xfr.xfFormatType ||
+ parentFormat != xfr.parentFormat ||
+ locked != xfr.locked ||
+ hidden != xfr.hidden ||
+ usedAttributes != xfr.usedAttributes)
+ {
+ return false;
+ }
+
+ if (align != xfr.align ||
+ valign != xfr.valign ||
+ orientation != xfr.orientation ||
+ wrap != xfr.wrap ||
+ shrinkToFit != xfr.shrinkToFit ||
+ indentation != xfr.indentation)
+ {
+ return false;
+ }
+
+ if (leftBorder != xfr.leftBorder ||
+ rightBorder != xfr.rightBorder ||
+ topBorder != xfr.topBorder ||
+ bottomBorder != xfr.bottomBorder)
+ {
+ return false;
+ }
+
+ if (leftBorderColour != xfr.leftBorderColour ||
+ rightBorderColour != xfr.rightBorderColour ||
+ topBorderColour != xfr.topBorderColour ||
+ bottomBorderColour != xfr.bottomBorderColour)
+ {
+ return false;
+ }
+
+ if (backgroundColour != xfr.backgroundColour ||
+ pattern != xfr.pattern)
+ {
+ return false;
+ }
+
+ if (initialized && xfr.initialized)
+ {
+ // Both formats are initialized, so it is sufficient to just do
+ // shallow equals on font, format objects,
+ // since we are testing for the presence of clones anwyay
+ // Use indices rather than objects because of the rationalization
+ // process (which does not set the object on an XFRecord)
+ if (fontIndex != xfr.fontIndex ||
+ formatIndex != xfr.formatIndex)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Perform a deep compare of fonts and formats
+ if (!font.equals(xfr.font) ||
+ !format.equals(xfr.format))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Sets the format index. This is called during the rationalization process
+ * when some of the duplicate number formats have been removed
+ * @param newindex the new format index
+ */
+ void setFormatIndex(int newindex)
+ {
+ formatIndex = newindex;
+ }
+
+ /**
+ * Accessor for the font index. Called by the FormattingRecords objects
+ * during the rationalization process
+ * @return the font index
+ */
+ public int getFontIndex()
+ {
+ return fontIndex;
+ }
+
+
+ /**
+ * Sets the font index. This is called during the rationalization process
+ * when some of the duplicate fonts have been removed
+ * @param newindex the new index
+ */
+ void setFontIndex(int newindex)
+ {
+ fontIndex = newindex;
+ }
+
+ /**
+ * Sets the format type and parent format from the writable subclass
+ * @param t the xf type
+ * @param pf the parent format
+ */
+ protected void setXFDetails(XFType t, int pf)
+ {
+ xfFormatType = t;
+ parentFormat = pf;
+ }
+
+ /**
+ * Changes the appropriate indexes during the rationalization process
+ * @param xfMapping the xf index re-mappings
+ */
+ void rationalize(IndexMapping xfMapping)
+ {
+ xfIndex = xfMapping.getNewIndex(xfIndex);
+
+ if (xfFormatType == cell)
+ {
+ parentFormat = xfMapping.getNewIndex(parentFormat);
+ }
+ }
+
+ /**
+ * Sets the font object with a workbook specific clone. Called from
+ * the CellValue object when the font has been identified as a statically
+ * shared font
+ * Also called to superimpose a HyperlinkFont on an existing label cell
+ */
+ public void setFont(FontRecord f)
+ {
+ // This style cannot be initialized, otherwise it would mean it would
+ // have been initialized with shared font
+ // However, sometimes (when setting a row or column format) an initialized
+ // XFRecord may have its font overridden by the column/row
+
+ font = f;
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/BStoreContainer.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/BStoreContainer.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/BStoreContainer.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,92 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import common.Logger;
+
+/**
+ * A BStoreContainer escher record
+ */
+class BStoreContainer extends EscherContainer
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(BStoreContainer.class);
+
+ /**
+ * The number of blips inside this container
+ */
+ private int numBlips;
+
+ /**
+ * Constructor used to instantiate this object when reading from an
+ * escher stream
+ *
+ * @param erd the escher data
+ */
+ public BStoreContainer(EscherRecordData erd)
+ {
+ super(erd);
+ numBlips = getInstance();
+ }
+
+ /**
+ * Constructor used when writing out an escher record
+ */
+ public BStoreContainer()
+ {
+ super(EscherRecordType.BSTORE_CONTAINER);
+ }
+
+ /**
+ * Sets the number of drawings in this container
+ *
+ * @param count the number of blips
+ */
+ void setNumBlips(int count)
+ {
+ numBlips = count;
+ setInstance(numBlips);
+ }
+
+ /**
+ * Accessor for the number of blips
+ *
+ * @return the number of blips
+ */
+ public int getNumBlips()
+ {
+ return numBlips;
+ }
+
+ /**
+ * Accessor for the drawing
+ *
+ * @param i the index number of the drawing to return
+ * @return the drawing
+ */
+ public BlipStoreEntry getDrawing(int i)
+ {
+ EscherRecord[] children = getChildren();
+ BlipStoreEntry bse = (BlipStoreEntry) children[i];
+ return bse;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/BlipStoreEntry.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/BlipStoreEntry.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/BlipStoreEntry.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,214 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.io.IOException;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+
+/**
+ * The data for this blip store entry. Typically this is the raw image data
+ */
+class BlipStoreEntry extends EscherAtom
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(BlipStoreEntry.class);
+
+ /**
+ * The type of the blip
+ */
+ private BlipType type;
+
+ /**
+ * The image data read in
+ */
+ private byte[] data;
+
+ /**
+ * The length of the image data
+ */
+ private int imageDataLength;
+
+ /**
+ * The reference count on this blip
+ */
+ private int referenceCount;
+
+ /**
+ * Flag to indicate that this entry was specified by the API, and not
+ * read in
+ */
+ private boolean write;
+
+ /**
+ * The start of the image data within this blip entry
+ */
+ private static final int IMAGE_DATA_OFFSET = 61;
+
+ /**
+ * Constructor
+ *
+ * @param erd the escher record data
+ */
+ public BlipStoreEntry(EscherRecordData erd)
+ {
+ super(erd);
+ type = BlipType.getType(getInstance());
+ write = false;
+ byte[] bytes = getBytes();
+ referenceCount = IntegerHelper.getInt(bytes[24], bytes[25],
+ bytes[26], bytes[27]);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param d the drawing
+ * @exception IOException
+ */
+ public BlipStoreEntry(Drawing d) throws IOException
+ {
+ super(EscherRecordType.BSE);
+ type = BlipType.PNG;
+ setVersion(2);
+ setInstance(type.getValue());
+
+ byte[] imageData = d.getImageBytes();
+ imageDataLength = imageData.length;
+ data = new byte[imageDataLength + IMAGE_DATA_OFFSET];
+ System.arraycopy(imageData, 0, data, IMAGE_DATA_OFFSET, imageDataLength);
+ referenceCount = d.getReferenceCount();
+ write = true;
+ }
+
+ /**
+ * Accessor for the blip type
+ *
+ * @return the blip type
+ */
+ public BlipType getBlipType()
+ {
+ return type;
+ }
+
+ /**
+ * Gets the data for this blip so that it can be written out
+ *
+ * @return the data for the blip
+ */
+ public byte[] getData()
+ {
+ if (write)
+ {
+ // Drawing has been specified by API
+
+ // Type on win32
+ data[0] = (byte) type.getValue();
+
+ // Type on MacOs
+ data[1] = (byte) type.getValue();
+
+ // The blip identifier
+ // IntegerHelper.getTwoBytes(0xfce1, data, 2);
+
+ // Unused tags - 18 bytes
+ // System.arraycopy(stuff, 0, data, 2, stuff.length);
+
+ // The size of the file
+ IntegerHelper.getFourBytes(imageDataLength + 8 + 17, data, 20);
+
+ // The reference count on the blip
+ IntegerHelper.getFourBytes(referenceCount, data, 24);
+
+ // Offset in the delay stream
+ IntegerHelper.getFourBytes(0, data, 28);
+
+ // Usage byte
+ data[32] = (byte) 0;
+
+ // Length of the blip name
+ data[33] = (byte) 0;
+
+ // Last two bytes unused
+ data[34] = (byte) 0x7e;
+ data[35] = (byte) 0x01;
+
+ // The blip itself
+ data[36] = (byte) 0;
+ data[37] = (byte) 0x6e;
+
+ // The blip identifier
+ IntegerHelper.getTwoBytes(0xf01e, data, 38);
+
+ // The length of the blip. This is the length of the image file plus
+ // 16 bytes
+ IntegerHelper.getFourBytes(imageDataLength + 17, data, 40);
+
+ // Unknown stuff
+ // System.arraycopy(stuff, 0, data, 44, stuff.length);
+ }
+ else
+ {
+ // drawing has been read in
+ data = getBytes();
+ }
+
+ return setHeaderData(data);
+ }
+
+ /**
+ * Reduces the reference count in this blip. Called when a drawing is
+ * removed
+ */
+ void dereference()
+ {
+ referenceCount--;
+ Assert.verify(referenceCount >= 0);
+ }
+
+ /**
+ * Accessor for the reference count on the blip
+ *
+ * @return the reference count on the blip
+ */
+ int getReferenceCount()
+ {
+ return referenceCount;
+ }
+
+ /**
+ * Accessor for the image data.
+ *
+ * @return the image data
+ */
+ byte[] getImageData()
+ {
+ byte[] allData = getBytes();
+ byte[] imageData = new byte[allData.length - IMAGE_DATA_OFFSET];
+ System.arraycopy(allData, IMAGE_DATA_OFFSET,
+ imageData, 0, imageData.length);
+ return imageData;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/BlipType.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/BlipType.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/BlipType.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,117 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+/**
+ * Enumeration for the BLIP type
+ */
+final class BlipType
+{
+ /**
+ * The blip type code
+ */
+ private int value;
+
+ /**
+ * The blip type description
+ */
+ private String desc;
+
+ /**
+ * All blip types
+ */
+ private static BlipType[] types = new BlipType[0];
+
+ /**
+ * Constructor
+ *
+ * @param val the code
+ * @param d the description
+ */
+ private BlipType(int val, String d)
+ {
+ value = val;
+ desc = d;
+
+ BlipType[] newtypes = new BlipType[types.length + 1];
+ System.arraycopy(types, 0, newtypes, 0, types.length);
+ newtypes[types.length] = this;
+ types = newtypes;
+ }
+
+ /**
+ * Accessor for the description
+ *
+ * @return the description
+ */
+ public String getDescription()
+ {
+ return desc;
+ }
+
+ /**
+ * Accessor for the value
+ *
+ * @return the value
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Gets the blip type given the value
+ *
+ * @param val get the value
+ * @return the blip type
+ */
+ public static BlipType getType(int val)
+ {
+ BlipType type = UNKNOWN;
+ for (int i = 0; i < types.length; i++)
+ {
+ if (types[i].value == val)
+ {
+ type = types[i];
+ break;
+ }
+ }
+
+ return type;
+ }
+
+ public static final BlipType ERROR = new BlipType(0, "Error");
+ // An error occured during loading
+ public static final BlipType UNKNOWN = new BlipType(1, "Unknown");
+ // An unknown blip type
+ public static final BlipType EMF = new BlipType(2, "EMF");
+ // Windows Enhanced Metafile
+ public static final BlipType WMF = new BlipType(3, "WMF");
+ // Windows Metafile
+ public static final BlipType PICT = new BlipType(4, "PICT");
+ // Macintosh PICT
+ public static final BlipType JPEG = new BlipType(5, "JPEG"); // JFIF
+ public static final BlipType PNG = new BlipType(6, "PNG"); // PNG
+ public static final BlipType DIB = new BlipType(7, "DIB"); // Windows DIB
+ public static final BlipType FIRST_CLIENT = new BlipType(32, "FIRST");
+ // First client defined blip type
+ public static final BlipType LAST_CLIENT = new BlipType(255, "LAST");
+ // Last client defined blip type
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/Button.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/Button.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/Button.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,867 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.io.IOException;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.ContinueRecord;
+import jxl.biff.IntegerHelper;
+import jxl.biff.StringHelper;
+import jxl.write.biff.File;
+
+/**
+ * Contains the various biff records used to copy a Button (from the
+ * Form toolbox) between workbook
+ */
+public class Button implements DrawingGroupObject
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(Button.class);
+
+ /**
+ * The spContainer that was read in
+ */
+ private EscherContainer readSpContainer;
+
+ /**
+ * The spContainer that was generated
+ */
+ private EscherContainer spContainer;
+
+ /**
+ * The MsoDrawingRecord associated with the drawing
+ */
+ private MsoDrawingRecord msoDrawingRecord;
+
+ /**
+ * The ObjRecord associated with the drawing
+ */
+ private ObjRecord objRecord;
+
+ /**
+ * Initialized flag
+ */
+ private boolean initialized = false;
+
+ /**
+ * The object id, assigned by the drawing group
+ */
+ private int objectId;
+
+ /**
+ * The blip id
+ */
+ private int blipId;
+
+ /**
+ * The shape id
+ */
+ private int shapeId;
+
+ /**
+ * The column
+ */
+ private int column;
+
+ /**
+ * The row position of the image
+ */
+ private int row;
+
+ /**
+ * The width of the image in cells
+ */
+ private double width;
+
+ /**
+ * The height of the image in cells
+ */
+ private double height;
+
+ /**
+ * The number of places this drawing is referenced
+ */
+ private int referenceCount;
+
+ /**
+ * The top level escher container
+ */
+ private EscherContainer escherData;
+
+ /**
+ * Where this image came from (read, written or a copy)
+ */
+ private Origin origin;
+
+ /**
+ * The drawing group for all the images
+ */
+ private DrawingGroup drawingGroup;
+
+ /**
+ * The drawing data
+ */
+ private DrawingData drawingData;
+
+ /**
+ * The type of this drawing object
+ */
+ private ShapeType type;
+
+ /**
+ * The drawing position on the sheet
+ */
+ private int drawingNumber;
+
+ /**
+ * An mso drawing record, which sometimes appears
+ */
+ private MsoDrawingRecord mso;
+
+ /**
+ * The text object record
+ */
+ private TextObjectRecord txo;
+
+ /**
+ * Text data from the first continue record
+ */
+ private ContinueRecord text;
+
+ /**
+ * Formatting data from the second continue record
+ */
+ private ContinueRecord formatting;
+
+ /**
+ * The comment text
+ */
+ private String commentText;
+
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings workbookSettings;
+
+ /**
+ * Constructor used when reading images
+ *
+ * @param msodr the drawing record
+ * @param obj the object record
+ * @param dd the drawing data for all drawings on this sheet
+ * @param dg the drawing group
+ * @param ws the workbook settings
+ */
+ public Button(MsoDrawingRecord msodr,
+ ObjRecord obj,
+ DrawingData dd,
+ DrawingGroup dg,
+ WorkbookSettings ws)
+ {
+ drawingGroup = dg;
+ msoDrawingRecord = msodr;
+ drawingData = dd;
+ objRecord = obj;
+ initialized = false;
+ workbookSettings = ws;
+ origin = Origin.READ;
+ drawingData.addData(msoDrawingRecord.getData());
+ drawingNumber = drawingData.getNumDrawings() - 1;
+ drawingGroup.addDrawing(this);
+
+ Assert.verify(msoDrawingRecord != null && objRecord != null);
+
+ initialize();
+ }
+
+ /**
+ * Copy constructor used to copy drawings from read to write
+ *
+ * @param dgo the drawing group object
+ * @param dg the drawing group
+ * @param ws the workbook settings
+ */
+ public Button(DrawingGroupObject dgo,
+ DrawingGroup dg,
+ WorkbookSettings ws)
+ {
+ Button d = (Button) dgo;
+ Assert.verify(d.origin == Origin.READ);
+ msoDrawingRecord = d.msoDrawingRecord;
+ objRecord = d.objRecord;
+ initialized = false;
+ origin = Origin.READ;
+ drawingData = d.drawingData;
+ drawingGroup = dg;
+ drawingNumber = d.drawingNumber;
+ drawingGroup.addDrawing(this);
+ mso = d.mso;
+ txo = d.txo;
+ text = d.text;
+ formatting = d.formatting;
+ workbookSettings = ws;
+ }
+
+ /**
+ * Initializes the member variables from the Escher stream data
+ */
+ private void initialize()
+ {
+ readSpContainer = drawingData.getSpContainer(drawingNumber);
+ Assert.verify(readSpContainer != null);
+
+ EscherRecord[] children = readSpContainer.getChildren();
+
+ Sp sp = (Sp) readSpContainer.getChildren()[0];
+ objectId = objRecord.getObjectId();
+ shapeId = sp.getShapeId();
+ type = ShapeType.getType(sp.getShapeType());
+
+ if (type == ShapeType.UNKNOWN)
+ {
+ logger.warn("Unknown shape type");
+ }
+
+ ClientAnchor clientAnchor = null;
+ for (int i = 0; i < children.length && clientAnchor == null; i++)
+ {
+ if (children[i].getType() == EscherRecordType.CLIENT_ANCHOR)
+ {
+ clientAnchor = (ClientAnchor) children[i];
+ }
+ }
+
+ if (clientAnchor == null)
+ {
+ logger.warn("Client anchor not found");
+ }
+ else
+ {
+ column = (int) clientAnchor.getX1() - 1;
+ row = (int) clientAnchor.getY1() + 1;
+ }
+
+ initialized = true;
+ }
+
+
+ /**
+ * Sets the object id. Invoked by the drawing group when the object is
+ * added to id
+ *
+ * @param objid the object id
+ * @param bip the blip id
+ * @param sid the shape id
+ */
+ public final void setObjectId(int objid, int bip, int sid)
+ {
+ objectId = objid;
+ blipId = bip;
+ shapeId = sid;
+
+ if (origin == Origin.READ)
+ {
+ origin = Origin.READ_WRITE;
+ }
+ }
+
+ /**
+ * Accessor for the object id
+ *
+ * @return the object id
+ */
+ public final int getObjectId()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return objectId;
+ }
+
+ /**
+ * Accessor for the shape id
+ *
+ * @return the object id
+ */
+ public final int getShapeId()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return shapeId;
+ }
+
+ /**
+ * Accessor for the blip id
+ *
+ * @return the blip id
+ */
+ public final int getBlipId()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return blipId;
+ }
+
+ /**
+ * Gets the drawing record which was read in
+ *
+ * @return the drawing record
+ */
+ public MsoDrawingRecord getMsoDrawingRecord()
+ {
+ return msoDrawingRecord;
+ }
+
+ /**
+ * Creates the main Sp container for the drawing
+ *
+ * @return the SP container
+ */
+ public EscherContainer getSpContainer()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ if (origin == Origin.READ)
+ {
+ return getReadSpContainer();
+ }
+
+ Assert.verify(false);
+
+ /*
+ if (spContainer == null)
+ {
+ spContainer = new SpContainer();
+ Sp sp = new Sp(type, shapeId, 2560);
+ spContainer.add(sp);
+ Opt opt = new Opt();
+ opt.addProperty(344, false, false, 0); // ?
+ opt.addProperty(385, false, false, 134217808); // fill colour
+ opt.addProperty(387, false, false, 134217808); // background colour
+ opt.addProperty(959, false, false, 131074); // hide
+ spContainer.add(opt);
+
+ ClientAnchor clientAnchor = new ClientAnchor(column + 1.3,
+ Math.max(0, row - 0.6),
+ column+3, row + 4);
+
+ spContainer.add(clientAnchor);
+
+ ClientData clientData = new ClientData();
+ spContainer.add(clientData);
+
+ ClientTextBox clientTextBox = new ClientTextBox();
+ spContainer.add(clientTextBox);
+ }
+ */
+
+ return spContainer;
+ }
+
+ /**
+ * Sets the drawing group for this drawing. Called by the drawing group
+ * when this drawing is added to it
+ *
+ * @param dg the drawing group
+ */
+ public void setDrawingGroup(DrawingGroup dg)
+ {
+ drawingGroup = dg;
+ }
+
+ /**
+ * Accessor for the drawing group
+ *
+ * @return the drawing group
+ */
+ public DrawingGroup getDrawingGroup()
+ {
+ return drawingGroup;
+ }
+
+ /**
+ * Gets the origin of this drawing
+ *
+ * @return where this drawing came from
+ */
+ public Origin getOrigin()
+ {
+ return origin;
+ }
+
+ /**
+ * Accessor for the reference count on this drawing
+ *
+ * @return the reference count
+ */
+ public int getReferenceCount()
+ {
+ return referenceCount;
+ }
+
+ /**
+ * Sets the new reference count on the drawing
+ *
+ * @param r the new reference count
+ */
+ public void setReferenceCount(int r)
+ {
+ referenceCount = r;
+ }
+
+ /**
+ * Accessor for the column of this drawing
+ *
+ * @return the column
+ */
+ public double getX()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ return column;
+ }
+
+ /**
+ * Sets the column position of this drawing. Used when inserting/removing
+ * columns from the spreadsheet
+ *
+ * @param x the column
+ */
+ public void setX(double x)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ column = (int) x;
+ }
+
+ /**
+ * Accessor for the row of this drawing
+ *
+ * @return the row
+ */
+ public double getY()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return row;
+ }
+
+ /**
+ * Accessor for the row of the drawing
+ *
+ * @param y the row
+ */
+ public void setY(double y)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ row = (int) y;
+ }
+
+
+ /**
+ * Accessor for the width of this drawing
+ *
+ * @return the number of columns spanned by this image
+ */
+ public double getWidth()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return width;
+ }
+
+ /**
+ * Accessor for the width
+ *
+ * @param w the number of columns to span
+ */
+ public void setWidth(double w)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ width = w;
+ }
+
+ /**
+ * Accessor for the height of this drawing
+ *
+ * @return the number of rows spanned by this image
+ */
+ public double getHeight()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return height;
+ }
+
+ /**
+ * Accessor for the height of this drawing
+ *
+ * @param h the number of rows spanned by this image
+ */
+ public void setHeight(double h)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ height = h;
+ }
+
+
+ /**
+ * Gets the SpContainer that was read in
+ *
+ * @return the read sp container
+ */
+ private EscherContainer getReadSpContainer()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return readSpContainer;
+ }
+
+ /**
+ * Accessor for the image data
+ *
+ * @return the image data
+ */
+ public byte[] getImageData()
+ {
+ Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE);
+
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return drawingGroup.getImageData(blipId);
+ }
+
+ /**
+ * Accessor for the type
+ *
+ * @return the type
+ */
+ public ShapeType getType()
+ {
+ return type;
+ }
+
+ /**
+ * Sets the text object
+ *
+ * @param t the text object record
+ */
+ public void setTextObject(TextObjectRecord t)
+ {
+ txo = t;
+ }
+
+ /**
+ * Sets the text data
+ *
+ * @param t continuation record
+ */
+ public void setText(ContinueRecord t)
+ {
+ text = t;
+ }
+
+ /**
+ * Sets the formatting
+ *
+ * @param t continue record
+ */
+ public void setFormatting(ContinueRecord t)
+ {
+ formatting = t;
+ }
+
+ /**
+ * Accessor for the image data
+ *
+ * @return the image data
+ */
+ public byte[] getImageBytes()
+ {
+ Assert.verify(false);
+ return null;
+ }
+
+ /**
+ * Accessor for the image file path. Normally this is the absolute path
+ * of a file on the directory system, but if this drawing was constructed
+ * using an byte[] then the blip id is returned
+ *
+ * @return the image file path, or the blip id
+ */
+ public String getImageFilePath()
+ {
+ Assert.verify(false);
+ return null;
+ }
+
+ /**
+ * The drawing record
+ *
+ * @param d the drawing record
+ */
+ public void addMso(MsoDrawingRecord d)
+ {
+ mso = d;
+ drawingData.addRawData(mso.getData());
+ }
+
+ /**
+ * Writes out any additional records
+ *
+ * @param outputFile the output file
+ * @exception IOException
+ */
+ public void writeAdditionalRecords(File outputFile) throws IOException
+ {
+ if (origin == Origin.READ)
+ {
+ outputFile.write(objRecord);
+
+ if (mso != null)
+ {
+ outputFile.write(mso);
+ }
+ outputFile.write(txo);
+ outputFile.write(text);
+ if (formatting != null)
+ {
+ outputFile.write(formatting);
+ }
+ return;
+ }
+
+ Assert.verify(false);
+
+ // Create the obj record
+ ObjRecord objrec = new ObjRecord(objectId,
+ ObjRecord.EXCELNOTE);
+
+ outputFile.write(objrec);
+
+ // Create the mso data record. Write the text box record again,
+ // although it is already included in the SpContainer
+ ClientTextBox textBox = new ClientTextBox();
+ MsoDrawingRecord msod = new MsoDrawingRecord(textBox.getData());
+ outputFile.write(msod);
+
+ TextObjectRecord tor = new TextObjectRecord(getText());
+ outputFile.write(tor);
+
+ // Data for the first continue record
+ byte[] textData = new byte[commentText.length() * 2 + 1];
+ textData[0] = 0x1; // unicode indicator
+ StringHelper.getUnicodeBytes(commentText, textData, 1);
+ //StringHelper.getBytes(commentText, textData, 1);
+ ContinueRecord textContinue = new ContinueRecord(textData);
+ outputFile.write(textContinue);
+
+ // Data for the formatting runs
+
+ byte[] frData = new byte[16];
+
+ // First txo run (the user)
+ IntegerHelper.getTwoBytes(0, frData, 0); // index to the first character
+ IntegerHelper.getTwoBytes(0, frData, 2); // index to the font(default)
+ // Mandatory last txo run
+ IntegerHelper.getTwoBytes(commentText.length(), frData, 8);
+ IntegerHelper.getTwoBytes(0, frData, 10); // index to the font(default)
+
+ ContinueRecord frContinue = new ContinueRecord(frData);
+ outputFile.write(frContinue);
+ }
+
+ /**
+ * Writes any records that need to be written after all the drawing group
+ * objects have been written
+ * Writes out all the note records
+ *
+ * @param outputFile the output file
+ */
+ public void writeTailRecords(File outputFile)
+ {
+ }
+
+ /**
+ * Accessor for the row. As buttons are not associated with a cell,
+ * does nothing here
+ *
+ * @return the row number
+ */
+ public int getRow()
+ {
+ return 0;
+ }
+
+ /**
+ * Accessor for the column. As buttons are not associated with a cell,
+ * does nothing here
+ *
+ * @return the column number
+ */
+ public int getColumn()
+ {
+ return 0;
+ }
+
+ /**
+ * Accessor for the text on the button
+ *
+ * @return the button text
+ */
+ public String getText()
+ {
+ if (commentText == null)
+ {
+ Assert.verify(text != null);
+
+ byte[] td = text.getData();
+ if (td[0] == 0)
+ {
+ commentText = StringHelper.getString
+ (td, td.length - 1, 1, workbookSettings);
+ }
+ else
+ {
+ commentText = StringHelper.getUnicodeString
+ (td, (td.length - 1) / 2, 1);
+ }
+ }
+
+ return commentText;
+ }
+
+ /**
+ * Hashing algorithm
+ *
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ return commentText.hashCode();
+ }
+
+ /**
+ * Called when the comment text is changed during the sheet copy process
+ *
+ * @param t the new text
+ */
+ public void setButtonText(String t)
+ {
+ commentText = t;
+
+ if (origin == Origin.READ)
+ {
+ origin = Origin.READ_WRITE;
+ }
+ }
+
+ /**
+ * Accessor for the first drawing on the sheet. This is used when
+ * copying unmodified sheets to indicate that this drawing contains
+ * the first time Escher gubbins
+ *
+ * @return TRUE if this MSORecord is the first drawing on the sheet
+ */
+ public boolean isFirst()
+ {
+ return mso.isFirst();
+ }
+
+ /**
+ * Queries whether this object is a form object. Form objects have their
+ * drawings records spread over TXO and CONTINUE records and
+ * require special handling
+ *
+ * @return TRUE if this is a form object, FALSE otherwise
+ */
+ public boolean isFormObject()
+ {
+ return true;
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/Chart.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/Chart.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/Chart.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,270 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.ByteData;
+import jxl.biff.IndexMapping;
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.read.biff.File;
+
+/**
+ * Contains the various biff records used to insert a chart into a
+ * worksheet
+ */
+public class Chart implements ByteData, EscherStream
+{
+ /**
+ * The logger
+ */
+ private static final Logger logger = Logger.getLogger(Chart.class);
+
+ /**
+ * The MsoDrawingRecord associated with the chart
+ */
+ private MsoDrawingRecord msoDrawingRecord;
+
+ /**
+ * The ObjRecord associated with the chart
+ */
+ private ObjRecord objRecord;
+
+ /**
+ * The start pos of the chart bof stream in the data file
+ */
+ private int startpos;
+
+ /**
+ * The start pos of the chart bof stream in the data file
+ */
+ private int endpos;
+
+ /**
+ * A handle to the Excel file
+ */
+ private File file;
+
+ /**
+ * The drawing data
+ */
+ private DrawingData drawingData;
+
+ /**
+ * The drawing number
+ */
+ private int drawingNumber;
+
+ /**
+ * The chart byte data
+ */
+ private byte[] data;
+
+ /**
+ * Flag which indicates that the byte data has been initialized
+ */
+ private boolean initialized;
+
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings workbookSettings;
+
+ /**
+ * Constructor
+ *
+ * @param mso a MsoDrawingRecord
value
+ * @param obj an ObjRecord
value
+ * @param dd the drawing data
+ * @param sp an int
value
+ * @param ep an int
value
+ * @param f a File
value
+ * @param ws the workbook settings
+ */
+ public Chart(MsoDrawingRecord mso,
+ ObjRecord obj,
+ DrawingData dd,
+ int sp, int ep, File f, WorkbookSettings ws)
+ {
+ msoDrawingRecord = mso;
+ objRecord = obj;
+ startpos = sp;
+ endpos = ep;
+ file = f;
+ workbookSettings = ws;
+
+ // msoDrawingRecord is null if the entire sheet consists of just the
+ // chart. In this case, as there is only one drawing on the page,
+ // it isn't necessary to add to the drawing data record anyway
+ if (msoDrawingRecord != null)
+ {
+ drawingData = dd;
+ drawingData.addData(msoDrawingRecord.getRecord().getData());
+ drawingNumber = drawingData.getNumDrawings() - 1;
+ }
+
+ initialized = false;
+
+ // Note: mso and obj values can be null if we are creating a chart
+ // which takes up an entire worksheet. Check that both are null or both
+ // not null though
+ Assert.verify((mso != null && obj != null) ||
+ (mso == null && obj == null));
+ }
+
+ /**
+ * Gets the entire binary record for the chart as a chunk of binary data
+ *
+ * @return the bytes
+ */
+ public byte[] getBytes()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return data;
+ }
+
+ /**
+ * Implementation of the EscherStream method
+ *
+ * @return the data
+ */
+ public byte[] getData()
+ {
+ return msoDrawingRecord.getRecord().getData();
+ }
+
+ /**
+ * Initializes the charts byte data
+ */
+ private void initialize()
+ {
+ data = file.read(startpos, endpos - startpos);
+ initialized = true;
+ }
+
+ /**
+ * Rationalizes the sheet's xf index mapping
+ * @param xfMapping the index mapping for XFRecords
+ * @param fontMapping the index mapping for fonts
+ * @param formatMapping the index mapping for formats
+ */
+ public void rationalize(IndexMapping xfMapping,
+ IndexMapping fontMapping,
+ IndexMapping formatMapping)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ // Read through the array, looking for the data types
+ // This is a total hack bodge for now - it will eventually need to be
+ // integrated properly
+ int pos = 0;
+ int code = 0;
+ int length = 0;
+ Type type = null;
+ while (pos < data.length)
+ {
+ code = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ length = IntegerHelper.getInt(data[pos + 2], data[pos + 3]);
+
+ type = Type.getType(code);
+
+ if (type == Type.FONTX)
+ {
+ int fontind = IntegerHelper.getInt(data[pos + 4], data[pos + 5]);
+ IntegerHelper.getTwoBytes(fontMapping.getNewIndex(fontind),
+ data, pos + 4);
+ }
+ else if (type == Type.FBI)
+ {
+ int fontind = IntegerHelper.getInt(data[pos + 12], data[pos + 13]);
+ IntegerHelper.getTwoBytes(fontMapping.getNewIndex(fontind),
+ data, pos + 12);
+ }
+ else if (type == Type.IFMT)
+ {
+ int formind = IntegerHelper.getInt(data[pos + 4], data[pos + 5]);
+ IntegerHelper.getTwoBytes(formatMapping.getNewIndex(formind),
+ data, pos + 4);
+ }
+ else if (type == Type.ALRUNS)
+ {
+ int numRuns = IntegerHelper.getInt(data[pos + 4], data[pos + 5]);
+ int fontPos = pos + 6;
+ for (int i = 0 ; i < numRuns; i++)
+ {
+ int fontind = IntegerHelper.getInt(data[fontPos + 2],
+ data[fontPos + 3]);
+ IntegerHelper.getTwoBytes(fontMapping.getNewIndex(fontind),
+ data, fontPos + 2);
+ fontPos += 4;
+ }
+ }
+
+ pos += length + 4;
+ }
+ }
+
+ /**
+ * Gets the SpContainer containing the charts drawing information
+ *
+ * @return the spContainer
+ */
+ EscherContainer getSpContainer()
+ {
+ EscherContainer spContainer = drawingData.getSpContainer(drawingNumber);
+
+ return spContainer;
+ }
+
+ /**
+ * Accessor for the mso drawing record
+ *
+ * @return the drawing record
+ */
+ MsoDrawingRecord getMsoDrawingRecord()
+ {
+ return msoDrawingRecord;
+ }
+
+ /**
+ * Accessor for the obj record
+ *
+ * @return the obj record
+ */
+ ObjRecord getObjRecord()
+ {
+ return objRecord;
+ }
+}
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/Chunk.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/Chunk.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/Chunk.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,43 @@
+/*********************************************************************
+*
+* Copyright (C) 2006 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+class Chunk
+{
+ private int pos;
+ private int length;
+ private ChunkType type;
+ private byte[] data;
+
+ public Chunk(int p, int l, ChunkType ct, byte[] d)
+ {
+ pos = p;
+ length = l;
+ type = ct;
+ data = new byte[length];
+ System.arraycopy(d, pos, data, 0, length);
+
+ }
+
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/ChunkType.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/ChunkType.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/ChunkType.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,74 @@
+/*********************************************************************
+*
+* Copyright (C) 2006 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.util.Arrays;
+
+/**
+ * Enumeration for the various chunk types
+ */
+class ChunkType
+{
+ private byte[] id;
+ private String name;
+
+ private static ChunkType[] chunkTypes = new ChunkType[0];
+
+ private ChunkType(int d1, int d2, int d3, int d4, String n)
+ {
+ id = new byte[] {(byte) d1, (byte) d2, (byte) d3, (byte) d4};
+ name = n;
+
+ ChunkType[] ct = new ChunkType[chunkTypes.length + 1];
+ System.arraycopy(chunkTypes, 0, ct, 0, chunkTypes.length);
+ ct[chunkTypes.length] = this;
+ chunkTypes = ct;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public static ChunkType getChunkType(byte d1, byte d2, byte d3, byte d4)
+ {
+ byte[] cmp = new byte[] {d1, d2, d3, d4};
+
+ boolean found = false;
+ ChunkType chunk = ChunkType.UNKNOWN;
+
+ for (int i = 0; i < chunkTypes.length && !found ; i++)
+ {
+ if (Arrays.equals(chunkTypes[i].id, cmp))
+ {
+ chunk = chunkTypes[i];
+ found = true;
+ }
+ }
+
+ return chunk;
+ }
+
+
+ public static ChunkType IHDR = new ChunkType(0x49, 0x48, 0x44, 0x52,"IHDR");
+ public static ChunkType IEND = new ChunkType(0x49, 0x45, 0x4e, 0x44,"IEND");
+ public static ChunkType PHYS = new ChunkType(0x70, 0x48, 0x59, 0x73,"pHYs");
+ public static ChunkType UNKNOWN = new ChunkType(0xff, 0xff, 0xff, 0xff, "UNKNOWN");
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/ClientAnchor.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/ClientAnchor.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/ClientAnchor.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,211 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+
+/**
+ * The client anchor record
+ */
+class ClientAnchor extends EscherAtom
+{
+ /**
+ * The logger
+ */
+ private static final Logger logger = Logger.getLogger(ClientAnchor.class);
+
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * The properties
+ */
+ private int properties;
+
+ /**
+ * The x1 position
+ */
+ private double x1;
+
+ /**
+ * The y1 position
+ */
+ private double y1;
+
+ /**
+ * The x2 position
+ */
+ private double x2;
+
+ /**
+ * The y2 position
+ */
+ private double y2;
+
+ /**
+ * Constructor
+ *
+ * @param erd the escher record data
+ */
+ public ClientAnchor(EscherRecordData erd)
+ {
+ super(erd);
+ byte[] bytes = getBytes();
+
+ // The properties
+ properties = IntegerHelper.getInt(bytes[0], bytes[1]);
+
+ // The x1 cell
+ int x1Cell = IntegerHelper.getInt(bytes[2], bytes[3]);
+ int x1Fraction = IntegerHelper.getInt(bytes[4], bytes[5]);
+
+ x1 = x1Cell + (double) x1Fraction / (double) 1024;
+
+ // The y1 cell
+ int y1Cell = IntegerHelper.getInt(bytes[6], bytes[7]);
+ int y1Fraction = IntegerHelper.getInt(bytes[8], bytes[9]);
+
+ y1 = y1Cell + (double) y1Fraction / (double) 256;
+
+ // The x2 cell
+ int x2Cell = IntegerHelper.getInt(bytes[10], bytes[11]);
+ int x2Fraction = IntegerHelper.getInt(bytes[12], bytes[13]);
+
+ x2 = x2Cell + (double) x2Fraction / (double) 1024;
+
+ // The y1 cell
+ int y2Cell = IntegerHelper.getInt(bytes[14], bytes[15]);
+ int y2Fraction = IntegerHelper.getInt(bytes[16], bytes[17]);
+
+ y2 = y2Cell + (double) y2Fraction / (double) 256;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param x1 the x1 position
+ * @param y1 the y1 position
+ * @param x2 the x2 position
+ * @param y2 the y2 position
+ * @param props the anchor properties
+ */
+ public ClientAnchor(double x1, double y1, double x2, double y2, int props)
+ {
+ super(EscherRecordType.CLIENT_ANCHOR);
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ properties = props;
+ }
+
+ /**
+ * Gets the client anchor data
+ *
+ * @return the data
+ */
+ byte[] getData()
+ {
+ data = new byte[18];
+ IntegerHelper.getTwoBytes(properties, data, 0);
+
+ // The x1 cell
+ IntegerHelper.getTwoBytes((int) x1, data, 2);
+
+ // The x1 fraction into the cell 0-1024
+ int x1fraction = (int) ((x1 - (int) x1) * 1024);
+ IntegerHelper.getTwoBytes(x1fraction, data, 4);
+
+ // The y1 cell
+ IntegerHelper.getTwoBytes((int) y1, data, 6);
+
+ // The y1 fraction into the cell 0-256
+ int y1fraction = (int) ((y1 - (int) y1) * 256);
+ IntegerHelper.getTwoBytes(y1fraction, data, 8);
+
+ // The x2 cell
+ IntegerHelper.getTwoBytes((int) x2, data, 10);
+
+ // The x2 fraction into the cell 0-1024
+ int x2fraction = (int) ((x2 - (int) x2) * 1024);
+ IntegerHelper.getTwoBytes(x2fraction, data, 12);
+
+ // The y2 cell
+ IntegerHelper.getTwoBytes((int) y2, data, 14);
+
+ // The y2 fraction into the cell 0-256
+ int y2fraction = (int) ((y2 - (int) y2) * 256);
+ IntegerHelper.getTwoBytes(y2fraction, data, 16);
+
+ return setHeaderData(data);
+ }
+
+ /**
+ * Accessor for the x1 position
+ *
+ * @return the x1 position
+ */
+ double getX1()
+ {
+ return x1;
+ }
+
+ /**
+ * Accessor for the y1 position
+ *
+ * @return the y1 position
+ */
+ double getY1()
+ {
+ return y1;
+ }
+
+ /**
+ * Accessor for the x2 position
+ *
+ * @return the x2 position
+ */
+ double getX2()
+ {
+ return x2;
+ }
+
+ /**
+ * Accessor for the y2 position
+ *
+ * @return the y2 position
+ */
+ double getY2()
+ {
+ return y2;
+ }
+
+ /**
+ * Accessor for the anchor properties
+ */
+ int getProperties()
+ {
+ return properties;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/ClientData.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/ClientData.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/ClientData.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,67 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import common.Logger;
+
+/**
+ * The client data
+ */
+class ClientData extends EscherAtom
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(ClientData.class);
+
+ /**
+ * The raw data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param erd the record data
+ */
+ public ClientData(EscherRecordData erd)
+ {
+ super(erd);
+ }
+
+ /**
+ * Constructor
+ */
+ public ClientData()
+ {
+ super(EscherRecordType.CLIENT_DATA);
+ }
+
+ /**
+ * Accessor for the raw data
+ *
+ * @return the binary data
+ */
+ byte[] getData()
+ {
+ data = new byte[0];
+ return setHeaderData(data);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/ClientTextBox.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/ClientTextBox.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/ClientTextBox.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,67 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import common.Logger;
+
+/**
+ * ???
+ */
+class ClientTextBox extends EscherAtom
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(ClientTextBox.class);
+
+ /**
+ * The raw data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param erd
+ */
+ public ClientTextBox(EscherRecordData erd)
+ {
+ super(erd);
+ }
+
+ /**
+ * Constructor
+ */
+ public ClientTextBox()
+ {
+ super(EscherRecordType.CLIENT_TEXT_BOX);
+ }
+
+ /**
+ * Accessor for the raw data
+ *
+ * @return
+ */
+ byte[] getData()
+ {
+ data = new byte[0];
+ return setHeaderData(data);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/ComboBox.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/ComboBox.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/ComboBox.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,706 @@
+/*********************************************************************
+*
+* Copyright (C) 2006 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.io.IOException;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.write.biff.File;
+
+/**
+ * Contains the various biff records used to copy a ComboBox (from the
+ * Form toolbox) between workbook
+ */
+public class ComboBox implements DrawingGroupObject
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(ComboBox.class);
+
+ /**
+ * The spContainer that was read in
+ */
+ private EscherContainer readSpContainer;
+
+ /**
+ * The spContainer that was generated
+ */
+ private EscherContainer spContainer;
+
+ /**
+ * The MsoDrawingRecord associated with the drawing
+ */
+ private MsoDrawingRecord msoDrawingRecord;
+
+ /**
+ * The ObjRecord associated with the drawing
+ */
+ private ObjRecord objRecord;
+
+ /**
+ * Initialized flag
+ */
+ private boolean initialized = false;
+
+ /**
+ * The object id, assigned by the drawing group
+ */
+ private int objectId;
+
+ /**
+ * The blip id
+ */
+ private int blipId;
+
+ /**
+ * The shape id
+ */
+ private int shapeId;
+
+ /**
+ * The column
+ */
+ private int column;
+
+ /**
+ * The row position of the image
+ */
+ private int row;
+
+ /**
+ * The width of the image in cells
+ */
+ private double width;
+
+ /**
+ * The height of the image in cells
+ */
+ private double height;
+
+ /**
+ * The number of places this drawing is referenced
+ */
+ private int referenceCount;
+
+ /**
+ * The top level escher container
+ */
+ private EscherContainer escherData;
+
+ /**
+ * Where this image came from (read, written or a copy)
+ */
+ private Origin origin;
+
+ /**
+ * The drawing group for all the images
+ */
+ private DrawingGroup drawingGroup;
+
+ /**
+ * The drawing data
+ */
+ private DrawingData drawingData;
+
+ /**
+ * The type of this drawing object
+ */
+ private ShapeType type;
+
+ /**
+ * The drawing position on the sheet
+ */
+ private int drawingNumber;
+
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings workbookSettings;
+
+ /**
+ * Constructor used when reading images
+ *
+ * @param mso the drawing record
+ * @param obj the object record
+ * @param dd the drawing data for all drawings on this sheet
+ * @param dg the drawing group
+ * @param ws the workbook settings
+ */
+ public ComboBox(MsoDrawingRecord mso, ObjRecord obj, DrawingData dd,
+ DrawingGroup dg, WorkbookSettings ws)
+ {
+ drawingGroup = dg;
+ msoDrawingRecord = mso;
+ drawingData = dd;
+ objRecord = obj;
+ initialized = false;
+ workbookSettings = ws;
+ origin = Origin.READ;
+ drawingData.addData(msoDrawingRecord.getData());
+ drawingNumber = drawingData.getNumDrawings() - 1;
+ drawingGroup.addDrawing(this);
+
+ Assert.verify(mso != null && obj != null);
+
+ initialize();
+ }
+
+ /**
+ * Copy constructor used to copy drawings from read to write
+ *
+ * @param dgo the drawing group object
+ * @param dg the drawing group
+ * @param ws the workbook settings
+ */
+ public ComboBox(DrawingGroupObject dgo,
+ DrawingGroup dg,
+ WorkbookSettings ws)
+ {
+ ComboBox d = (ComboBox) dgo;
+ Assert.verify(d.origin == Origin.READ);
+ msoDrawingRecord = d.msoDrawingRecord;
+ objRecord = d.objRecord;
+ initialized = false;
+ origin = Origin.READ;
+ drawingData = d.drawingData;
+ drawingGroup = dg;
+ drawingNumber = d.drawingNumber;
+ drawingGroup.addDrawing(this);
+ workbookSettings = ws;
+ }
+
+ /**
+ * Constructor invoked when writing images
+ */
+ public ComboBox()
+ {
+ initialized = true;
+ origin = Origin.WRITE;
+ referenceCount = 1;
+ type = ShapeType.HOST_CONTROL;
+ }
+
+ /**
+ * Initializes the member variables from the Escher stream data
+ */
+ private void initialize()
+ {
+ readSpContainer = drawingData.getSpContainer(drawingNumber);
+ Assert.verify(readSpContainer != null);
+
+ EscherRecord[] children = readSpContainer.getChildren();
+
+ Sp sp = (Sp) readSpContainer.getChildren()[0];
+ objectId = objRecord.getObjectId();
+ shapeId = sp.getShapeId();
+ type = ShapeType.getType(sp.getShapeType());
+
+ if (type == ShapeType.UNKNOWN)
+ {
+ logger.warn("Unknown shape type");
+ }
+
+ ClientAnchor clientAnchor = null;
+ for (int i = 0; i < children.length && clientAnchor == null; i++)
+ {
+ if (children[i].getType() == EscherRecordType.CLIENT_ANCHOR)
+ {
+ clientAnchor = (ClientAnchor) children[i];
+ }
+ }
+
+ if (clientAnchor == null)
+ {
+ logger.warn("Client anchor not found");
+ }
+ else
+ {
+ column = (int) clientAnchor.getX1();
+ row = (int) clientAnchor.getY1();
+ }
+
+ initialized = true;
+ }
+
+
+ /**
+ * Sets the object id. Invoked by the drawing group when the object is
+ * added to id
+ *
+ * @param objid the object id
+ * @param bip the blip id
+ * @param sid the shape id
+ */
+ public final void setObjectId(int objid, int bip, int sid)
+ {
+ objectId = objid;
+ blipId = bip;
+ shapeId = sid;
+
+ if (origin == Origin.READ)
+ {
+ origin = Origin.READ_WRITE;
+ }
+ }
+
+ /**
+ * Accessor for the object id
+ *
+ * @return the object id
+ */
+ public final int getObjectId()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return objectId;
+ }
+
+ /**
+ * Accessor for the shape id
+ *
+ * @return the object id
+ */
+ public final int getShapeId()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return shapeId;
+ }
+
+ /**
+ * Accessor for the blip id
+ *
+ * @return the blip id
+ */
+ public final int getBlipId()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return blipId;
+ }
+
+ /**
+ * Gets the drawing record which was read in
+ *
+ * @return the drawing record
+ */
+ public MsoDrawingRecord getMsoDrawingRecord()
+ {
+ return msoDrawingRecord;
+ }
+
+ /**
+ * Creates the main Sp container for the drawing
+ *
+ * @return the SP container
+ */
+ public EscherContainer getSpContainer()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ if (origin == Origin.READ)
+ {
+ return getReadSpContainer();
+ }
+
+ SpContainer spc = new SpContainer();
+ Sp sp = new Sp(type, shapeId, 2560);
+ spc.add(sp);
+ Opt opt = new Opt();
+ opt.addProperty(127, false, false, 17039620);
+ opt.addProperty(191, false, false, 524296);
+ opt.addProperty(511, false, false, 524288);
+ opt.addProperty(959, false, false, 131072);
+ // opt.addProperty(260, true, false, blipId);
+ // opt.addProperty(261, false, false, 36);
+ spc.add(opt);
+
+ ClientAnchor clientAnchor = new ClientAnchor(column,
+ row,
+ column + 1,
+ row + 1,
+ 0x1);
+ spc.add(clientAnchor);
+ ClientData clientData = new ClientData();
+ spc.add(clientData);
+
+ return spc;
+ }
+
+ /**
+ * Sets the drawing group for this drawing. Called by the drawing group
+ * when this drawing is added to it
+ *
+ * @param dg the drawing group
+ */
+ public void setDrawingGroup(DrawingGroup dg)
+ {
+ drawingGroup = dg;
+ }
+
+ /**
+ * Accessor for the drawing group
+ *
+ * @return the drawing group
+ */
+ public DrawingGroup getDrawingGroup()
+ {
+ return drawingGroup;
+ }
+
+ /**
+ * Gets the origin of this drawing
+ *
+ * @return where this drawing came from
+ */
+ public Origin getOrigin()
+ {
+ return origin;
+ }
+
+ /**
+ * Accessor for the reference count on this drawing
+ *
+ * @return the reference count
+ */
+ public int getReferenceCount()
+ {
+ return referenceCount;
+ }
+
+ /**
+ * Sets the new reference count on the drawing
+ *
+ * @param r the new reference count
+ */
+ public void setReferenceCount(int r)
+ {
+ referenceCount = r;
+ }
+
+ /**
+ * Accessor for the column of this drawing
+ *
+ * @return the column
+ */
+ public double getX()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ return column;
+ }
+
+ /**
+ * Sets the column position of this drawing. Used when inserting/removing
+ * columns from the spreadsheet
+ *
+ * @param x the column
+ */
+ public void setX(double x)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ column = (int) x;
+ }
+
+ /**
+ * Accessor for the row of this drawing
+ *
+ * @return the row
+ */
+ public double getY()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return row;
+ }
+
+ /**
+ * Accessor for the row of the drawing
+ *
+ * @param y the row
+ */
+ public void setY(double y)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ row = (int) y;
+ }
+
+
+ /**
+ * Accessor for the width of this drawing
+ *
+ * @return the number of columns spanned by this image
+ */
+ public double getWidth()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return width;
+ }
+
+ /**
+ * Accessor for the width
+ *
+ * @param w the number of columns to span
+ */
+ public void setWidth(double w)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ width = w;
+ }
+
+ /**
+ * Accessor for the height of this drawing
+ *
+ * @return the number of rows spanned by this image
+ */
+ public double getHeight()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return height;
+ }
+
+ /**
+ * Accessor for the height of this drawing
+ *
+ * @param h the number of rows spanned by this image
+ */
+ public void setHeight(double h)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ height = h;
+ }
+
+
+ /**
+ * Gets the SpContainer that was read in
+ *
+ * @return the read sp container
+ */
+ private EscherContainer getReadSpContainer()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return readSpContainer;
+ }
+
+ /**
+ * Accessor for the image data
+ *
+ * @return the image data
+ */
+ public byte[] getImageData()
+ {
+ Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE);
+
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return drawingGroup.getImageData(blipId);
+ }
+
+ /**
+ * Accessor for the type
+ *
+ * @return the type
+ */
+ public ShapeType getType()
+ {
+ return type;
+ }
+
+ /**
+ * Accessor for the image data
+ *
+ * @return the image data
+ */
+ public byte[] getImageBytes()
+ {
+ Assert.verify(false);
+ return null;
+ }
+
+ /**
+ * Accessor for the image file path. Normally this is the absolute path
+ * of a file on the directory system, but if this drawing was constructed
+ * using an byte[] then the blip id is returned
+ *
+ * @return the image file path, or the blip id
+ */
+ public String getImageFilePath()
+ {
+ Assert.verify(false);
+ return null;
+ }
+
+ /**
+ * Writes out the additional records for a combo box
+ *
+ * @param outputFile the output file
+ * @exception IOException
+ */
+ public void writeAdditionalRecords(File outputFile) throws IOException
+ {
+ if (origin == Origin.READ)
+ {
+ outputFile.write(objRecord);
+ return;
+ }
+
+ // Create the obj record
+ ObjRecord objrec = new ObjRecord(objectId,
+ ObjRecord.COMBOBOX);
+
+ outputFile.write(objrec);
+ }
+
+ /**
+ * Writes any records that need to be written after all the drawing group
+ * objects have been written
+ * Writes out all the note records
+ *
+ * @param outputFile the output file
+ */
+ public void writeTailRecords(File outputFile)
+ {
+ }
+
+ /**
+ * Accessor for the row
+ *
+ * @return the row
+ */
+ public int getRow()
+ {
+ return 0;
+ }
+
+ /**
+ * Accessor for the column
+ *
+ * @return the column
+ */
+ public int getColumn()
+ {
+ return 0;
+ }
+
+ /**
+ * Hashing algorithm
+ *
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ return getClass().getName().hashCode();
+ }
+
+ /**
+ * Accessor for the first drawing on the sheet. This is used when
+ * copying unmodified sheets to indicate that this drawing contains
+ * the first time Escher gubbins
+ *
+ * @return TRUE if this MSORecord is the first drawing on the sheet
+ */
+ public boolean isFirst()
+ {
+ return msoDrawingRecord.isFirst();
+ }
+
+ /**
+ * Queries whether this object is a form object. Form objects have their
+ * drawings records spread over TXO and CONTINUE records and
+ * require special handling
+ *
+ * @return TRUE if this is a form object, FALSE otherwise
+ */
+ public boolean isFormObject()
+ {
+ return false;
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/Comment.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/Comment.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/Comment.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,910 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.io.IOException;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.ContinueRecord;
+import jxl.biff.IntegerHelper;
+import jxl.biff.StringHelper;
+import jxl.write.biff.File;
+
+/**
+ * Contains the various biff records used to insert a cell note into a
+ * worksheet
+ */
+public class Comment implements DrawingGroupObject
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(Comment.class);
+
+ /**
+ * The spContainer that was read in
+ */
+ private EscherContainer readSpContainer;
+
+ /**
+ * The spContainer that was generated
+ */
+ private EscherContainer spContainer;
+
+ /**
+ * The MsoDrawingRecord associated with the drawing
+ */
+ private MsoDrawingRecord msoDrawingRecord;
+
+ /**
+ * The ObjRecord associated with the drawing
+ */
+ private ObjRecord objRecord;
+
+ /**
+ * Initialized flag
+ */
+ private boolean initialized = false;
+
+ /**
+ * The object id, assigned by the drawing group
+ */
+ private int objectId;
+
+ /**
+ * The blip id
+ */
+ private int blipId;
+
+ /**
+ * The shape id
+ */
+ private int shapeId;
+
+ /**
+ * The column
+ */
+ private int column;
+
+ /**
+ * The row position of the image
+ */
+ private int row;
+
+ /**
+ * The width of the image in cells
+ */
+ private double width;
+
+ /**
+ * The height of the image in cells
+ */
+ private double height;
+
+ /**
+ * The number of places this drawing is referenced
+ */
+ private int referenceCount;
+
+ /**
+ * The top level escher container
+ */
+ private EscherContainer escherData;
+
+ /**
+ * Where this image came from (read, written or a copy)
+ */
+ private Origin origin;
+
+ /**
+ * The drawing group for all the images
+ */
+ private DrawingGroup drawingGroup;
+
+ /**
+ * The drawing data
+ */
+ private DrawingData drawingData;
+
+ /**
+ * The type of this drawing object
+ */
+ private ShapeType type;
+
+ /**
+ * The drawing position on the sheet
+ */
+ private int drawingNumber;
+
+ /**
+ * An mso drawing record, which sometimes appears
+ */
+ private MsoDrawingRecord mso;
+
+ /**
+ * The text object record
+ */
+ private TextObjectRecord txo;
+
+ /**
+ * The note record
+ */
+ private NoteRecord note;
+
+ /**
+ * Text data from the first continue record
+ */
+ private ContinueRecord text;
+
+ /**
+ * Formatting data from the second continue record
+ */
+ private ContinueRecord formatting;
+
+ /**
+ * The comment text
+ */
+ private String commentText;
+
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings workbookSettings;
+
+ /**
+ * Constructor used when reading images
+ *
+ * @param msorec the drawing record
+ * @param obj the object record
+ * @param dd the drawing data for all drawings on this sheet
+ * @param dg the drawing group
+ * @param ws the workbook settings
+ */
+ public Comment(MsoDrawingRecord msorec, ObjRecord obj, DrawingData dd,
+ DrawingGroup dg, WorkbookSettings ws)
+ {
+ drawingGroup = dg;
+ msoDrawingRecord = msorec;
+ drawingData = dd;
+ objRecord = obj;
+ initialized = false;
+ workbookSettings = ws;
+ origin = Origin.READ;
+ drawingData.addData(msoDrawingRecord.getData());
+ drawingNumber = drawingData.getNumDrawings() - 1;
+ drawingGroup.addDrawing(this);
+
+ Assert.verify(msoDrawingRecord != null && objRecord != null);
+
+ if (!initialized)
+ {
+ initialize();
+ }
+ }
+
+ /**
+ * Copy constructor used to copy drawings from read to write
+ *
+ * @param dgo the drawing group object
+ * @param dg the drawing group
+ * @param ws the workbook settings
+ */
+ /*protected*/ public Comment(DrawingGroupObject dgo,
+ DrawingGroup dg,
+ WorkbookSettings ws)
+ {
+ Comment d = (Comment) dgo;
+ Assert.verify(d.origin == Origin.READ);
+ msoDrawingRecord = d.msoDrawingRecord;
+ objRecord = d.objRecord;
+ initialized = false;
+ origin = Origin.READ;
+ drawingData = d.drawingData;
+ drawingGroup = dg;
+ drawingNumber = d.drawingNumber;
+ drawingGroup.addDrawing(this);
+ mso = d.mso;
+ txo = d.txo;
+ text = d.text;
+ formatting = d.formatting;
+ note = d.note;
+ width = d.width;
+ height = d.height;
+ workbookSettings = ws;
+ }
+
+ /**
+ * Constructor invoked when writing the images
+ *
+ * @param txt the comment text
+ * @param c the column
+ * @param r the row
+ */
+ public Comment(String txt, int c, int r)
+ {
+ initialized = true;
+ origin = Origin.WRITE;
+ column = c;
+ row = r;
+ referenceCount = 1;
+ type = ShapeType.TEXT_BOX;
+ commentText = txt;
+ width = 3;
+ height = 4;
+ }
+
+ /**
+ * Initializes the member variables from the Escher stream data
+ */
+ private void initialize()
+ {
+ readSpContainer = drawingData.getSpContainer(drawingNumber);
+ Assert.verify(readSpContainer != null);
+
+ EscherRecord[] children = readSpContainer.getChildren();
+
+ Sp sp = (Sp) readSpContainer.getChildren()[0];
+ objectId = objRecord.getObjectId();
+ shapeId = sp.getShapeId();
+ type = ShapeType.getType(sp.getShapeType());
+
+ if (type == ShapeType.UNKNOWN)
+ {
+ logger.warn("Unknown shape type");
+ }
+
+ ClientAnchor clientAnchor = null;
+ for (int i = 0; i < children.length && clientAnchor == null; i++)
+ {
+ if (children[i].getType() == EscherRecordType.CLIENT_ANCHOR)
+ {
+ clientAnchor = (ClientAnchor) children[i];
+ }
+ }
+
+ if (clientAnchor == null)
+ {
+ logger.warn("client anchor not found");
+ }
+ else
+ {
+ column = (int) clientAnchor.getX1() - 1;
+ row = (int) clientAnchor.getY1() + 1;
+ width = clientAnchor.getX2() - clientAnchor.getX1();
+ height = clientAnchor.getY2() - clientAnchor.getY1();
+ }
+
+ initialized = true;
+ }
+
+
+ /**
+ * Sets the object id. Invoked by the drawing group when the object is
+ * added to id
+ *
+ * @param objid the object id
+ * @param bip the blip id
+ * @param sid the shape id
+ */
+ public final void setObjectId(int objid, int bip, int sid)
+ {
+ objectId = objid;
+ blipId = bip;
+ shapeId = sid;
+
+ if (origin == Origin.READ)
+ {
+ origin = Origin.READ_WRITE;
+ }
+ }
+
+ /**
+ * Accessor for the object id
+ *
+ * @return the object id
+ */
+ public final int getObjectId()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return objectId;
+ }
+
+ /**
+ * Accessor for the shape id
+ *
+ * @return the object id
+ */
+ public final int getShapeId()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return shapeId;
+ }
+
+ /**
+ * Accessor for the blip id
+ *
+ * @return the blip id
+ */
+ public final int getBlipId()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return blipId;
+ }
+
+ /**
+ * Gets the drawing record which was read in
+ *
+ * @return the drawing record
+ */
+ public MsoDrawingRecord getMsoDrawingRecord()
+ {
+ return msoDrawingRecord;
+ }
+
+ /**
+ * Creates the main Sp container for the drawing
+ *
+ * @return the SP container
+ */
+ public EscherContainer getSpContainer()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ if (origin == Origin.READ)
+ {
+ return getReadSpContainer();
+ }
+
+ if (spContainer == null)
+ {
+ spContainer = new SpContainer();
+ Sp sp = new Sp(type, shapeId, 2560);
+ spContainer.add(sp);
+ Opt opt = new Opt();
+ opt.addProperty(344, false, false, 0); // ?
+ opt.addProperty(385, false, false, 134217808); // fill colour
+ opt.addProperty(387, false, false, 134217808); // background colour
+ opt.addProperty(959, false, false, 131074); // hide
+ spContainer.add(opt);
+
+ ClientAnchor clientAnchor = new ClientAnchor(column + 1.3,
+ Math.max(0, row - 0.6),
+ column + 1.3 + width,
+ row + height,
+ 0x1);
+
+ spContainer.add(clientAnchor);
+
+ ClientData clientData = new ClientData();
+ spContainer.add(clientData);
+
+ ClientTextBox clientTextBox = new ClientTextBox();
+ spContainer.add(clientTextBox);
+ }
+
+ return spContainer;
+ }
+
+ /**
+ * Sets the drawing group for this drawing. Called by the drawing group
+ * when this drawing is added to it
+ *
+ * @param dg the drawing group
+ */
+ public void setDrawingGroup(DrawingGroup dg)
+ {
+ drawingGroup = dg;
+ }
+
+ /**
+ * Accessor for the drawing group
+ *
+ * @return the drawing group
+ */
+ public DrawingGroup getDrawingGroup()
+ {
+ return drawingGroup;
+ }
+
+ /**
+ * Gets the origin of this drawing
+ *
+ * @return where this drawing came from
+ */
+ public Origin getOrigin()
+ {
+ return origin;
+ }
+
+ /**
+ * Accessor for the reference count on this drawing
+ *
+ * @return the reference count
+ */
+ public int getReferenceCount()
+ {
+ return referenceCount;
+ }
+
+ /**
+ * Sets the new reference count on the drawing
+ *
+ * @param r the new reference count
+ */
+ public void setReferenceCount(int r)
+ {
+ referenceCount = r;
+ }
+
+ /**
+ * Accessor for the column of this drawing
+ *
+ * @return the column
+ */
+ public double getX()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ return column;
+ }
+
+ /**
+ * Sets the column position of this drawing. Used when inserting/removing
+ * columns from the spreadsheet
+ *
+ * @param x the column
+ */
+ public void setX(double x)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ column = (int) x;
+ }
+
+ /**
+ * Accessor for the row of this drawing
+ *
+ * @return the row
+ */
+ public double getY()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return row;
+ }
+
+ /**
+ * Accessor for the row of the drawing
+ *
+ * @param y the row
+ */
+ public void setY(double y)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ row = (int) y;
+ }
+
+
+ /**
+ * Accessor for the width of this drawing
+ *
+ * @return the number of columns spanned by this image
+ */
+ public double getWidth()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return width;
+ }
+
+ /**
+ * Accessor for the width
+ *
+ * @param w the number of columns to span
+ */
+ public void setWidth(double w)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ width = w;
+ }
+
+ /**
+ * Accessor for the height of this drawing
+ *
+ * @return the number of rows spanned by this image
+ */
+ public double getHeight()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return height;
+ }
+
+ /**
+ * Accessor for the height of this drawing
+ *
+ * @param h the number of rows spanned by this image
+ */
+ public void setHeight(double h)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ height = h;
+ }
+
+
+ /**
+ * Gets the SpContainer that was read in
+ *
+ * @return the read sp container
+ */
+ private EscherContainer getReadSpContainer()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return readSpContainer;
+ }
+
+ /**
+ * Accessor for the image data
+ *
+ * @return the image data
+ */
+ public byte[] getImageData()
+ {
+ Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE);
+
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return drawingGroup.getImageData(blipId);
+ }
+
+ /**
+ * Accessor for the type
+ *
+ * @return the type
+ */
+ public ShapeType getType()
+ {
+ return type;
+ }
+
+ /**
+ * Sets the text object
+ *
+ * @param t the text object
+ */
+ public void setTextObject(TextObjectRecord t)
+ {
+ txo = t;
+ }
+
+ /**
+ * Sets the note object
+ *
+ * @param t the note record
+ */
+ public void setNote(NoteRecord t)
+ {
+ note = t;
+ }
+
+ /**
+ * Sets the text data
+ *
+ * @param t the text data
+ */
+ public void setText(ContinueRecord t)
+ {
+ text = t;
+ }
+
+ /**
+ * Sets the formatting
+ *
+ * @param t the formatting record
+ */
+ public void setFormatting(ContinueRecord t)
+ {
+ formatting = t;
+ }
+
+ /**
+ * Accessor for the image data
+ *
+ * @return the image data
+ */
+ public byte[] getImageBytes()
+ {
+ Assert.verify(false);
+ return null;
+ }
+
+ /**
+ * Accessor for the image file path. Normally this is the absolute path
+ * of a file on the directory system, but if this drawing was constructed
+ * using an byte[] then the blip id is returned
+ *
+ * @return the image file path, or the blip id
+ */
+ public String getImageFilePath()
+ {
+ Assert.verify(false);
+ return null;
+ }
+
+ /**
+ * Adds an mso record to this object
+ *
+ * @param d the mso record
+ */
+ public void addMso(MsoDrawingRecord d)
+ {
+ mso = d;
+ drawingData.addRawData(mso.getData());
+ }
+
+ /**
+ * Writes out the additional comment records
+ *
+ * @param outputFile the output file
+ * @exception IOException
+ */
+ public void writeAdditionalRecords(File outputFile) throws IOException
+ {
+ if (origin == Origin.READ)
+ {
+ outputFile.write(objRecord);
+
+ if (mso != null)
+ {
+ outputFile.write(mso);
+ }
+ outputFile.write(txo);
+ outputFile.write(text);
+ if (formatting != null)
+ {
+ outputFile.write(formatting);
+ }
+ return;
+ }
+
+ // Create the obj record
+ ObjRecord objrec = new ObjRecord(objectId,
+ ObjRecord.EXCELNOTE);
+
+ outputFile.write(objrec);
+
+ // Create the mso data record. Write the text box record again,
+ // although it is already included in the SpContainer
+ ClientTextBox textBox = new ClientTextBox();
+ MsoDrawingRecord msod = new MsoDrawingRecord(textBox.getData());
+ outputFile.write(msod);
+
+ TextObjectRecord txorec = new TextObjectRecord(getText());
+ outputFile.write(txorec);
+
+ // Data for the first continue record
+ byte[] textData = new byte[commentText.length() * 2 + 1];
+ textData[0] = 0x1; // unicode indicator
+ StringHelper.getUnicodeBytes(commentText, textData, 1);
+ //StringHelper.getBytes(commentText, textData, 1);
+ ContinueRecord textContinue = new ContinueRecord(textData);
+ outputFile.write(textContinue);
+
+ // Data for the formatting runs
+
+ byte[] frData = new byte[16];
+
+ // First txo run (the user)
+ IntegerHelper.getTwoBytes(0, frData, 0); // index to the first character
+ IntegerHelper.getTwoBytes(0, frData, 2); // index to the font(default)
+ // Mandatory last txo run
+ IntegerHelper.getTwoBytes(commentText.length(), frData, 8);
+ IntegerHelper.getTwoBytes(0, frData, 10); // index to the font(default)
+
+ ContinueRecord frContinue = new ContinueRecord(frData);
+ outputFile.write(frContinue);
+ }
+
+ /**
+ * Writes any records that need to be written after all the drawing group
+ * objects have been written
+ * Writes out all the note records
+ *
+ * @param outputFile the output file
+ * @exception IOException
+ */
+ public void writeTailRecords(File outputFile) throws IOException
+ {
+ if (origin == Origin.READ)
+ {
+ outputFile.write(note);
+ return;
+ }
+
+ // The note record
+ NoteRecord noteRecord = new NoteRecord(column, row, objectId);
+ outputFile.write(noteRecord);
+ }
+
+ /**
+ * Accessor for the row
+ *
+ * @return the row
+ */
+ public int getRow()
+ {
+ return note.getRow();
+ }
+
+ /**
+ * Accessor for the column
+ *
+ * @return the column
+ */
+ public int getColumn()
+ {
+ return note.getColumn();
+ }
+
+ /**
+ * Accessor for the comment text
+ *
+ * @return the comment text
+ */
+ public String getText()
+ {
+ if (commentText == null)
+ {
+ Assert.verify(text != null);
+
+ byte[] td = text.getData();
+ if (td[0] == 0)
+ {
+ commentText = StringHelper.getString
+ (td, td.length - 1, 1, workbookSettings);
+ }
+ else
+ {
+ commentText = StringHelper.getUnicodeString
+ (td, (td.length - 1) / 2, 1);
+ }
+ }
+
+ return commentText;
+ }
+
+ /**
+ * Hashing algorithm
+ *
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ return commentText.hashCode();
+ }
+
+ /**
+ * Called when the comment text is changed during the sheet copy process
+ *
+ * @param t the new text
+ */
+ public void setCommentText(String t)
+ {
+ commentText = t;
+
+ if (origin == Origin.READ)
+ {
+ origin = Origin.READ_WRITE;
+ }
+ }
+
+ /**
+ * Accessor for the first drawing on the sheet. This is used when
+ * copying unmodified sheets to indicate that this drawing contains
+ * the first time Escher gubbins
+ *
+ * @return TRUE if this MSORecord is the first drawing on the sheet
+ */
+ public boolean isFirst()
+ {
+ return msoDrawingRecord.isFirst();
+ }
+
+ /**
+ * Queries whether this object is a form object. Form objects have their
+ * drawings records spread over several records and require special handling
+ *
+ * @return TRUE if this is a form object, FALSE otherwise
+ */
+ public boolean isFormObject()
+ {
+ return true;
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/Dg.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/Dg.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/Dg.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,101 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import jxl.biff.IntegerHelper;
+
+/**
+ * The Drawing Group
+ */
+class Dg extends EscherAtom
+{
+ /**
+ * The data
+ */
+ private byte[] data;
+
+ /**
+ * The id of this drawing
+ */
+ private int drawingId;
+
+ /**
+ * The number of shapes
+ */
+ private int shapeCount;
+
+ /**
+ * The seed for drawing ids
+ */
+ private int seed;
+
+ /**
+ * Constructor invoked when reading in an escher stream
+ *
+ * @param erd the escher record
+ */
+ public Dg(EscherRecordData erd)
+ {
+ super(erd);
+ drawingId = getInstance();
+
+ byte[] bytes = getBytes();
+ shapeCount = IntegerHelper.getInt(bytes[0], bytes[1], bytes[2], bytes[3]);
+ seed = IntegerHelper.getInt(bytes[4], bytes[5], bytes[6], bytes[7]);
+ }
+
+ /**
+ * Constructor invoked when writing out an escher stream
+ *
+ * @param numDrawings the number of drawings
+ */
+ public Dg(int numDrawings)
+ {
+ super(EscherRecordType.DG);
+ drawingId = 1;
+ shapeCount = numDrawings + 1;
+ seed = 1024 + shapeCount + 1;
+ setInstance(drawingId);
+ }
+
+ /**
+ * Gets the drawing id
+ *
+ * @return the drawing id
+ */
+ public int getDrawingId()
+ {
+ return drawingId;
+ }
+
+ /**
+ * Used to generate the drawing data
+ *
+ * @return the data
+ */
+ byte[] getData()
+ {
+ data = new byte[8];
+ IntegerHelper.getFourBytes(shapeCount, data, 0);
+ IntegerHelper.getFourBytes(seed, data, 4);
+
+ return setHeaderData(data);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/DgContainer.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/DgContainer.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/DgContainer.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,34 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+/**
+ * A Dg Container
+ */
+class DgContainer extends EscherContainer
+{
+ /**
+ * Constructor
+ */
+ public DgContainer()
+ {
+ super(EscherRecordType.DG_CONTAINER);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/Dgg.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/Dgg.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/Dgg.java 17 Aug 2012 14:51:21 -0000 1.1
@@ -0,0 +1,217 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.util.ArrayList;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+
+/**
+ * Dgg record
+ */
+class Dgg extends EscherAtom
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(Dgg.class);
+
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * The number of clusters
+ */
+ private int numClusters;
+
+ /**
+ * The maximum shape id
+ */
+ private int maxShapeId;
+
+ /**
+ * The number of shapes saved
+ */
+ private int shapesSaved;
+
+ /**
+ * The number of drawings saved
+ */
+ private int drawingsSaved;
+
+ /**
+ * The clusters
+ */
+ private ArrayList clusters;
+
+ /**
+ * The cluster structure
+ */
+ static final class Cluster
+ {
+ /**
+ * The drawing group id
+ */
+ int drawingGroupId;
+
+ /**
+ * The something or other
+ */
+ int shapeIdsUsed;
+
+ /**
+ * Constructor
+ *
+ * @param dgId the drawing group id
+ * @param sids the sids
+ */
+ Cluster(int dgId, int sids)
+ {
+ drawingGroupId = dgId;
+ shapeIdsUsed = sids;
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param erd the read in data
+ */
+ public Dgg(EscherRecordData erd)
+ {
+ super(erd);
+ clusters = new ArrayList();
+ byte[] bytes = getBytes();
+ maxShapeId = IntegerHelper.getInt
+ (bytes[0], bytes[1], bytes[2], bytes[3]);
+ numClusters = IntegerHelper.getInt
+ (bytes[4], bytes[5], bytes[6], bytes[7]);
+ shapesSaved = IntegerHelper.getInt
+ (bytes[8], bytes[9], bytes[10], bytes[11]);
+ drawingsSaved = IntegerHelper.getInt
+ (bytes[12], bytes[13], bytes[14], bytes[15]);
+
+ int pos = 16;
+ for (int i = 0; i < numClusters; i++)
+ {
+ int dgId = IntegerHelper.getInt(bytes[pos], bytes[pos + 1]);
+ int sids = IntegerHelper.getInt(bytes[pos + 2], bytes[pos + 3]);
+ Cluster c = new Cluster(dgId, sids);
+ clusters.add(c);
+ pos += 4;
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param numShapes the number of shapes
+ * @param numDrawings the number of drawings
+ */
+ public Dgg(int numShapes, int numDrawings)
+ {
+ super(EscherRecordType.DGG);
+ shapesSaved = numShapes;
+ drawingsSaved = numDrawings;
+ clusters = new ArrayList();
+ }
+
+ /**
+ * Adds a cluster to this record
+ *
+ * @param dgid the id
+ * @param sids the sid
+ */
+ void addCluster(int dgid, int sids)
+ {
+ Cluster c = new Cluster(dgid, sids);
+ clusters.add(c);
+ }
+
+ /**
+ * Gets the data for writing out
+ *
+ * @return the binary data
+ */
+ byte[] getData()
+ {
+ numClusters = clusters.size();
+ data = new byte[16 + numClusters * 4];
+
+ // The max shape id
+ IntegerHelper.getFourBytes(1024 + shapesSaved, data, 0);
+
+ // The number of clusters
+ IntegerHelper.getFourBytes(numClusters, data, 4);
+
+ // The number of shapes saved
+ IntegerHelper.getFourBytes(shapesSaved, data, 8);
+
+ // The number of drawings saved
+ // IntegerHelper.getFourBytes(drawingsSaved, data, 12);
+ IntegerHelper.getFourBytes(1, data, 12);
+
+ int pos = 16;
+ for (int i = 0; i < numClusters; i++)
+ {
+ Cluster c = (Cluster) clusters.get(i);
+ IntegerHelper.getTwoBytes(c.drawingGroupId, data, pos);
+ IntegerHelper.getTwoBytes(c.shapeIdsUsed, data, pos + 2);
+ pos += 4;
+ }
+
+ return setHeaderData(data);
+ }
+
+ /**
+ * Accessor for the number of shapes saved
+ *
+ * @return the number of shapes saved
+ */
+ int getShapesSaved()
+ {
+ return shapesSaved;
+ }
+
+ /**
+ * Accessor for the number of drawings saved
+ *
+ * @return the number of drawings saved
+ */
+ int getDrawingsSaved()
+ {
+ return drawingsSaved;
+ }
+
+ /**
+ * Accessor for a particular cluster
+ *
+ * @param i the cluster number
+ * @return the cluster
+ */
+ Cluster getCluster(int i)
+ {
+ return (Cluster) clusters.get(i);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/DggContainer.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/DggContainer.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/DggContainer.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,34 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+/**
+ * Container for Dgg objects
+ */
+class DggContainer extends EscherContainer
+{
+ /**
+ * Constructor
+ */
+ public DggContainer()
+ {
+ super(EscherRecordType.DGG_CONTAINER);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/Drawing.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/Drawing.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/Drawing.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,1130 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import common.Assert;
+import common.Logger;
+import common.LengthUnit;
+import common.LengthConverter;
+
+import jxl.Image;
+import jxl.Sheet;
+import jxl.CellView;
+import jxl.write.biff.File;
+
+
+/**
+ * Contains the various biff records used to insert a drawing into a
+ * worksheet
+ */
+public class Drawing implements DrawingGroupObject, Image
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(Drawing.class);
+
+ /**
+ * The spContainer that was read in
+ */
+ private EscherContainer readSpContainer;
+
+ /**
+ * The MsoDrawingRecord associated with the drawing
+ */
+ private MsoDrawingRecord msoDrawingRecord;
+
+ /**
+ * The ObjRecord associated with the drawing
+ */
+ private ObjRecord objRecord;
+
+ /**
+ * Initialized flag
+ */
+ private boolean initialized = false;
+
+ /**
+ * The file containing the image
+ */
+ private java.io.File imageFile;
+
+ /**
+ * The raw image data, used instead of an image file
+ */
+ private byte[] imageData;
+
+ /**
+ * The object id, assigned by the drawing group
+ */
+ private int objectId;
+
+ /**
+ * The blip id
+ */
+ private int blipId;
+
+ /**
+ * The column position of the image
+ */
+ private double x;
+
+ /**
+ * The row position of the image
+ */
+ private double y;
+
+ /**
+ * The width of the image in cells
+ */
+ private double width;
+
+ /**
+ * The height of the image in cells
+ */
+ private double height;
+
+ /**
+ * The number of places this drawing is referenced
+ */
+ private int referenceCount;
+
+ /**
+ * The top level escher container
+ */
+ private EscherContainer escherData;
+
+ /**
+ * Where this image came from (read, written or a copy)
+ */
+ private Origin origin;
+
+ /**
+ * The drawing group for all the images
+ */
+ private DrawingGroup drawingGroup;
+
+ /**
+ * The drawing data
+ */
+ private DrawingData drawingData;
+
+ /**
+ * The type of this drawing object
+ */
+ private ShapeType type;
+
+ /**
+ * The shape id
+ */
+ private int shapeId;
+
+ /**
+ * The drawing position on the sheet
+ */
+ private int drawingNumber;
+
+ /**
+ * A reference to the sheet containing this drawing. Used to calculate
+ * the drawing dimensions in pixels
+ */
+ private Sheet sheet;
+
+ /**
+ * Reader for the raw image data
+ */
+ private PNGReader pngReader;
+
+ /**
+ * The client anchor properties
+ */
+ private ImageAnchorProperties imageAnchorProperties;
+
+ // Enumeration type for the image anchor properties
+ protected static class ImageAnchorProperties
+ {
+ private int value;
+ private static ImageAnchorProperties[] o = new ImageAnchorProperties[0];
+
+ ImageAnchorProperties(int v)
+ {
+ value = v;
+
+ ImageAnchorProperties[] oldArray = o;
+ o = new ImageAnchorProperties[oldArray.length + 1];
+ System.arraycopy(oldArray, 0, o, 0, oldArray.length);
+ o[oldArray.length] = this;
+ }
+
+ int getValue()
+ {
+ return value;
+ }
+
+ static ImageAnchorProperties getImageAnchorProperties(int val)
+ {
+ ImageAnchorProperties iap = MOVE_AND_SIZE_WITH_CELLS;
+ int pos = 0;
+ while (pos < o.length)
+ {
+ if (o[pos].getValue()== val)
+ {
+ iap = o[pos];
+ break;
+ }
+ else
+ {
+ pos++;
+ }
+ }
+ return iap;
+ }
+ }
+
+ // The image anchor properties
+ public static ImageAnchorProperties MOVE_AND_SIZE_WITH_CELLS =
+ new ImageAnchorProperties(1);
+ public static ImageAnchorProperties MOVE_WITH_CELLS =
+ new ImageAnchorProperties(2);
+ public static ImageAnchorProperties NO_MOVE_OR_SIZE_WITH_CELLS =
+ new ImageAnchorProperties(3);
+
+ /**
+ * The default font size for columns
+ */
+ private static final double DEFAULT_FONT_SIZE = 10;
+
+ /**
+ * Constructor used when reading images
+ *
+ * @param mso the drawing record
+ * @param obj the object record
+ * @param dd the drawing data for all drawings on this sheet
+ * @param dg the drawing group
+ */
+ public Drawing(MsoDrawingRecord mso,
+ ObjRecord obj,
+ DrawingData dd,
+ DrawingGroup dg,
+ Sheet s)
+ {
+ drawingGroup = dg;
+ msoDrawingRecord = mso;
+ drawingData = dd;
+ objRecord = obj;
+ sheet = s;
+ initialized = false;
+ origin = Origin.READ;
+ drawingData.addData(msoDrawingRecord.getData());
+ drawingNumber = drawingData.getNumDrawings() - 1;
+ drawingGroup.addDrawing(this);
+
+ Assert.verify(mso != null && obj != null);
+
+ initialize();
+ }
+
+ /**
+ * Copy constructor used to copy drawings from read to write
+ *
+ * @param dgo the drawing group object
+ * @param dg the drawing group
+ */
+ protected Drawing(DrawingGroupObject dgo, DrawingGroup dg)
+ {
+ Drawing d = (Drawing) dgo;
+ Assert.verify(d.origin == Origin.READ);
+ msoDrawingRecord = d.msoDrawingRecord;
+ objRecord = d.objRecord;
+ initialized = false;
+ origin = Origin.READ;
+ drawingData = d.drawingData;
+ drawingGroup = dg;
+ drawingNumber = d.drawingNumber;
+ drawingGroup.addDrawing(this);
+ }
+
+ /**
+ * Constructor invoked when writing the images
+ *
+ * @param x the column
+ * @param y the row
+ * @param w the width in cells
+ * @param h the height in cells
+ * @param image the image file
+ */
+ public Drawing(double x,
+ double y,
+ double w,
+ double h,
+ java.io.File image)
+ {
+ imageFile = image;
+ initialized = true;
+ origin = Origin.WRITE;
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ referenceCount = 1;
+ imageAnchorProperties = MOVE_WITH_CELLS;
+ type = ShapeType.PICTURE_FRAME;
+ }
+
+ /**
+ * Constructor invoked when writing the images
+ *
+ * @param x the column
+ * @param y the row
+ * @param w the width in cells
+ * @param h the height in cells
+ * @param image the image data
+ */
+ public Drawing(double x,
+ double y,
+ double w,
+ double h,
+ byte[] image)
+ {
+ imageData = image;
+ initialized = true;
+ origin = Origin.WRITE;
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ referenceCount = 1;
+ imageAnchorProperties = MOVE_WITH_CELLS;
+ type = ShapeType.PICTURE_FRAME;
+ }
+
+ /**
+ * Initializes the member variables from the Escher stream data
+ */
+ private void initialize()
+ {
+ readSpContainer = drawingData.getSpContainer(drawingNumber);
+ Assert.verify(readSpContainer != null);
+
+ EscherRecord[] children = readSpContainer.getChildren();
+
+ Sp sp = (Sp) readSpContainer.getChildren()[0];
+ shapeId = sp.getShapeId();
+ objectId = objRecord.getObjectId();
+ type = ShapeType.getType(sp.getShapeType());
+
+ if (type == ShapeType.UNKNOWN)
+ {
+ logger.warn("Unknown shape type");
+ }
+
+ Opt opt = (Opt) readSpContainer.getChildren()[1];
+
+ if (opt.getProperty(260) != null)
+ {
+ blipId = opt.getProperty(260).value;
+ }
+
+ if (opt.getProperty(261) != null)
+ {
+ imageFile = new java.io.File(opt.getProperty(261).stringValue);
+ }
+ else
+ {
+ if (type == ShapeType.PICTURE_FRAME)
+ {
+ logger.warn("no filename property for drawing");
+ imageFile = new java.io.File(Integer.toString(blipId));
+ }
+ }
+
+ ClientAnchor clientAnchor = null;
+ for (int i = 0; i < children.length && clientAnchor == null; i++)
+ {
+ if (children[i].getType() == EscherRecordType.CLIENT_ANCHOR)
+ {
+ clientAnchor = (ClientAnchor) children[i];
+ }
+ }
+
+ if (clientAnchor == null)
+ {
+ logger.warn("client anchor not found");
+ }
+ else
+ {
+ x = clientAnchor.getX1();
+ y = clientAnchor.getY1();
+ width = clientAnchor.getX2() - x;
+ height = clientAnchor.getY2() - y;
+ imageAnchorProperties = ImageAnchorProperties.getImageAnchorProperties
+ (clientAnchor.getProperties());
+ }
+
+ if (blipId == 0)
+ {
+ logger.warn("linked drawings are not supported");
+ }
+
+ initialized = true;
+ }
+
+ /**
+ * Accessor for the image file
+ *
+ * @return the image file
+ */
+ public java.io.File getImageFile()
+ {
+ return imageFile;
+ }
+
+ /**
+ * Accessor for the image file path. Normally this is the absolute path
+ * of a file on the directory system, but if this drawing was constructed
+ * using an byte[] then the blip id is returned
+ *
+ * @return the image file path, or the blip id
+ */
+ public String getImageFilePath()
+ {
+ if (imageFile == null)
+ {
+ // return the blip id, if it exists
+ return blipId != 0 ? Integer.toString(blipId) : "__new__image__";
+ }
+
+ return imageFile.getPath();
+ }
+
+ /**
+ * Sets the object id. Invoked by the drawing group when the object is
+ * added to id
+ *
+ * @param objid the object id
+ * @param bip the blip id
+ * @param sid the shape id
+ */
+ public final void setObjectId(int objid, int bip, int sid)
+ {
+ objectId = objid;
+ blipId = bip;
+ shapeId = sid;
+
+ if (origin == Origin.READ)
+ {
+ origin = Origin.READ_WRITE;
+ }
+ }
+
+ /**
+ * Accessor for the object id
+ *
+ * @return the object id
+ */
+ public final int getObjectId()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return objectId;
+ }
+
+ /**
+ * Accessor for the shape id
+ *
+ * @return the shape id
+ */
+ public int getShapeId()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return shapeId;
+ }
+
+ /**
+ * Accessor for the blip id
+ *
+ * @return the blip id
+ */
+ public final int getBlipId()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return blipId;
+ }
+
+ /**
+ * Gets the drawing record which was read in
+ *
+ * @return the drawing record
+ */
+ public MsoDrawingRecord getMsoDrawingRecord()
+ {
+ return msoDrawingRecord;
+ }
+
+ /**
+ * Creates the main Sp container for the drawing
+ *
+ * @return the SP container
+ */
+ public EscherContainer getSpContainer()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ if (origin == Origin.READ)
+ {
+ return getReadSpContainer();
+ }
+
+ SpContainer spContainer = new SpContainer();
+ Sp sp = new Sp(type, shapeId, 2560);
+ spContainer.add(sp);
+ Opt opt = new Opt();
+ opt.addProperty(260, true, false, blipId);
+
+ if (type == ShapeType.PICTURE_FRAME)
+ {
+ String filePath = imageFile != null ? imageFile.getPath() : "";
+ opt.addProperty(261, true, true, filePath.length() * 2, filePath);
+ opt.addProperty(447, false, false, 65536);
+ opt.addProperty(959, false, false, 524288);
+ spContainer.add(opt);
+ }
+
+ ClientAnchor clientAnchor = new ClientAnchor
+ (x, y, x + width, y + height,
+ imageAnchorProperties.getValue());
+ spContainer.add(clientAnchor);
+ ClientData clientData = new ClientData();
+ spContainer.add(clientData);
+
+ return spContainer;
+ }
+
+ /**
+ * Sets the drawing group for this drawing. Called by the drawing group
+ * when this drawing is added to it
+ *
+ * @param dg the drawing group
+ */
+ public void setDrawingGroup(DrawingGroup dg)
+ {
+ drawingGroup = dg;
+ }
+
+ /**
+ * Accessor for the drawing group
+ *
+ * @return the drawing group
+ */
+ public DrawingGroup getDrawingGroup()
+ {
+ return drawingGroup;
+ }
+
+ /**
+ * Gets the origin of this drawing
+ *
+ * @return where this drawing came from
+ */
+ public Origin getOrigin()
+ {
+ return origin;
+ }
+
+ /**
+ * Accessor for the reference count on this drawing
+ *
+ * @return the reference count
+ */
+ public int getReferenceCount()
+ {
+ return referenceCount;
+ }
+
+ /**
+ * Sets the new reference count on the drawing
+ *
+ * @param r the new reference count
+ */
+ public void setReferenceCount(int r)
+ {
+ referenceCount = r;
+ }
+
+ /**
+ * Accessor for the column of this drawing
+ *
+ * @return the column
+ */
+ public double getX()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ return x;
+ }
+
+ /**
+ * Sets the column position of this drawing
+ *
+ * @param x the column
+ */
+ public void setX(double x)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ this.x = x;
+ }
+
+ /**
+ * Accessor for the row of this drawing
+ *
+ * @return the row
+ */
+ public double getY()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return y;
+ }
+
+ /**
+ * Accessor for the row of the drawing
+ *
+ * @param y the row
+ */
+ public void setY(double y)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ this.y = y;
+ }
+
+
+ /**
+ * Accessor for the width of this drawing
+ *
+ * @return the number of columns spanned by this image
+ */
+ public double getWidth()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return width;
+ }
+
+ /**
+ * Accessor for the width
+ *
+ * @param w the number of columns to span
+ */
+ public void setWidth(double w)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ width = w;
+ }
+
+ /**
+ * Accessor for the height of this drawing
+ *
+ * @return the number of rows spanned by this image
+ */
+ public double getHeight()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return height;
+ }
+
+ /**
+ * Accessor for the height of this drawing
+ *
+ * @param h the number of rows spanned by this image
+ */
+ public void setHeight(double h)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ height = h;
+ }
+
+
+ /**
+ * Gets the SpContainer that was read in
+ *
+ * @return the read sp container
+ */
+ private EscherContainer getReadSpContainer()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return readSpContainer;
+ }
+
+ /**
+ * Accessor for the image data
+ *
+ * @return the image data
+ */
+ public byte[] getImageData()
+ {
+ Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE);
+
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return drawingGroup.getImageData(blipId);
+ }
+
+ /**
+ * Accessor for the image data
+ *
+ * @return the image data
+ */
+ public byte[] getImageBytes() throws IOException
+ {
+ if (origin == Origin.READ || origin == Origin.READ_WRITE)
+ {
+ return getImageData();
+ }
+
+ Assert.verify(origin == Origin.WRITE);
+
+ if (imageFile == null)
+ {
+ Assert.verify(imageData != null);
+ return imageData;
+ }
+
+ byte[] data = new byte[(int) imageFile.length()];
+ FileInputStream fis = new FileInputStream(imageFile);
+ fis.read(data, 0, data.length);
+ fis.close();
+ return data;
+ }
+
+ /**
+ * Accessor for the type
+ *
+ * @return the type
+ */
+ public ShapeType getType()
+ {
+ return type;
+ }
+
+ /**
+ * Writes any other records associated with this drawing group object
+ *
+ * @param outputFile the output file
+ * @exception IOException
+ */
+ public void writeAdditionalRecords(File outputFile) throws IOException
+ {
+ if (origin == Origin.READ)
+ {
+ outputFile.write(objRecord);
+ return;
+ }
+
+ // Create the obj record
+ ObjRecord objrec = new ObjRecord(objectId,
+ ObjRecord.PICTURE);
+ outputFile.write(objrec);
+ }
+
+ /**
+ * Writes any records that need to be written after all the drawing group
+ * objects have been written
+ * Does nothing here
+ *
+ * @param outputFile the output file
+ */
+ public void writeTailRecords(File outputFile) throws IOException
+ {
+ // does nothing
+ }
+
+ /**
+ * Interface method
+ *
+ * @return the column number at which the image is positioned
+ */
+ public double getColumn()
+ {
+ return getX();
+ }
+
+ /**
+ * Interface method
+ *
+ * @return the row number at which the image is positions
+ */
+ public double getRow()
+ {
+ return getY();
+ }
+
+ /**
+ * Accessor for the first drawing on the sheet. This is used when
+ * copying unmodified sheets to indicate that this drawing contains
+ * the first time Escher gubbins
+ *
+ * @return TRUE if this MSORecord is the first drawing on the sheet
+ */
+ public boolean isFirst()
+ {
+ return msoDrawingRecord.isFirst();
+ }
+
+ /**
+ * Queries whether this object is a form object. Form objects have their
+ * drawings records spread over TXO and CONTINUE records and
+ * require special handling
+ *
+ * @return TRUE if this is a form object, FALSE otherwise
+ */
+ public boolean isFormObject()
+ {
+ return false;
+ }
+
+ /**
+ * Removes a row
+ *
+ * @param r the row to be removed
+ */
+ public void removeRow(int r)
+ {
+ if (y > r)
+ {
+ setY(r);
+ }
+ }
+
+ /**
+ * Accessor for the image dimensions. See technotes for Bill's explanation
+ * of the calculation logic
+ *
+ * @return approximate drawing size in pixels
+ */
+ private double getWidthInPoints()
+ {
+ if (sheet == null)
+ {
+ logger.warn("calculating image width: sheet is null");
+ return 0;
+ }
+
+ // The start and end row numbers
+ int firstCol = (int) x;
+ int lastCol = (int) Math.ceil(x + width) - 1;
+
+ // **** MAGIC NUMBER ALERT ***
+ // multiply the point size of the font by 0.59 to give the point size
+ // I know of no explanation for this yet, other than that it seems to
+ // give the right answer
+
+ // Get the width of the image within the first col, allowing for
+ // fractional offsets
+ CellView cellView = sheet.getColumnView(firstCol);
+ int firstColWidth = cellView.getSize();
+ double firstColImageWidth = (1 - (x - firstCol)) * firstColWidth;
+ double pointSize = (cellView.getFormat() != null) ?
+ cellView.getFormat().getFont().getPointSize() : DEFAULT_FONT_SIZE;
+ double firstColWidthInPoints = firstColImageWidth * 0.59 * pointSize / 256;
+
+ // Get the height of the image within the last row, allowing for
+ // fractional offsets
+ int lastColWidth = 0;
+ double lastColImageWidth = 0;
+ double lastColWidthInPoints = 0;
+ if (lastCol != firstCol)
+ {
+ cellView = sheet.getColumnView(lastCol);
+ lastColWidth = cellView.getSize();
+ lastColImageWidth = (x + width - lastCol) * lastColWidth;
+ pointSize = (cellView.getFormat() != null) ?
+ cellView.getFormat().getFont().getPointSize() : DEFAULT_FONT_SIZE;
+ lastColWidthInPoints = lastColImageWidth * 0.59 * pointSize / 256;
+ }
+
+ // Now get all the columns in between
+ double width = 0;
+ for (int i = 0 ; i < lastCol - firstCol - 1 ; i++)
+ {
+ cellView = sheet.getColumnView(firstCol + 1 +i);
+ pointSize = (cellView.getFormat() != null) ?
+ cellView.getFormat().getFont().getPointSize() : DEFAULT_FONT_SIZE;
+ width += cellView.getSize() * 0.59 * pointSize / 256;
+ }
+
+ // Add on the first and last row contributions to get the height in twips
+ double widthInPoints = width +
+ firstColWidthInPoints + lastColWidthInPoints;
+
+ return widthInPoints;
+ }
+
+ /**
+ * Accessor for the image dimensions. See technotes for Bill's explanation
+ * of the calculation logic
+ *
+ * @return approximate drawing size in pixels
+ */
+ private double getHeightInPoints()
+ {
+ if (sheet == null)
+ {
+ logger.warn("calculating image height: sheet is null");
+ return 0;
+ }
+
+ // The start and end row numbers
+ int firstRow = (int) y;
+ int lastRow = (int) Math.ceil(y + height) - 1;
+
+ // Get the height of the image within the first row, allowing for
+ // fractional offsets
+ int firstRowHeight = sheet.getRowView(firstRow).getSize();
+ double firstRowImageHeight = (1 - (y - firstRow)) * firstRowHeight;
+
+ // Get the height of the image within the last row, allowing for
+ // fractional offsets
+ int lastRowHeight = 0;
+ double lastRowImageHeight = 0;
+ if (lastRow != firstRow)
+ {
+ lastRowHeight = sheet.getRowView(lastRow).getSize();
+ lastRowImageHeight = (y + height - lastRow) * lastRowHeight;
+ }
+
+ // Now get all the rows in between
+ double height = 0;
+ for (int i = 0 ; i < lastRow - firstRow - 1 ; i++)
+ {
+ height += sheet.getRowView(firstRow + 1 + i).getSize();
+ }
+
+ // Add on the first and last row contributions to get the height in twips
+ double heightInTwips = height + firstRowHeight + lastRowHeight;
+
+ // Now divide by the magic number to converts twips into pixels and
+ // return the value
+ double heightInPoints = heightInTwips / 20.0;
+
+ return heightInPoints;
+ }
+
+ /**
+ * Get the width of this image as rendered within Excel
+ *
+ * @param unit the unit of measurement
+ * @return the width of the image within Excel
+ */
+ public double getWidth(LengthUnit unit)
+ {
+ double widthInPoints = getWidthInPoints();
+ return widthInPoints * LengthConverter.getConversionFactor
+ (LengthUnit.POINTS, unit);
+ }
+
+ /**
+ * Get the height of this image as rendered within Excel
+ *
+ * @param unit the unit of measurement
+ * @return the height of the image within Excel
+ */
+ public double getHeight(LengthUnit unit)
+ {
+ double heightInPoints = getHeightInPoints();
+ return heightInPoints * LengthConverter.getConversionFactor
+ (LengthUnit.POINTS, unit);
+ }
+
+ /**
+ * Gets the width of the image. Note that this is the width of the
+ * underlying image, and does not take into account any size manipulations
+ * that may have occurred when the image was added into Excel
+ *
+ * @return the image width in pixels
+ */
+ public int getImageWidth()
+ {
+ return getPngReader().getWidth();
+ }
+
+ /**
+ * Gets the height of the image. Note that this is the height of the
+ * underlying image, and does not take into account any size manipulations
+ * that may have occurred when the image was added into Excel
+ *
+ * @return the image width in pixels
+ */
+ public int getImageHeight()
+ {
+ return getPngReader().getHeight();
+ }
+
+
+ /**
+ * Gets the horizontal resolution of the image, if that information
+ * is available.
+ *
+ * @return the number of dots per unit specified, if available, 0 otherwise
+ */
+ public double getHorizontalResolution(LengthUnit unit)
+ {
+ int res = getPngReader().getHorizontalResolution();
+ return res / LengthConverter.getConversionFactor(LengthUnit.METRES, unit);
+ }
+
+ /**
+ * Gets the vertical resolution of the image, if that information
+ * is available.
+ *
+ * @return the number of dots per unit specified, if available, 0 otherwise
+ */
+ public double getVerticalResolution(LengthUnit unit)
+ {
+ int res = getPngReader().getVerticalResolution();
+ return res / LengthConverter.getConversionFactor(LengthUnit.METRES, unit);
+ }
+
+ private PNGReader getPngReader()
+ {
+ if (pngReader != null)
+ {
+ return pngReader;
+ }
+
+ byte[] imdata = null;
+ if (origin == Origin.READ || origin == Origin.READ_WRITE)
+ {
+ imdata = getImageData();
+ }
+ else
+ {
+ try
+ {
+ imdata = getImageBytes();
+ }
+ catch (IOException e)
+ {
+ logger.warn("Could not read image file");
+ imdata = new byte[0];
+ }
+ }
+
+ pngReader = new PNGReader(imdata);
+ pngReader.read();
+ return pngReader;
+ }
+
+ /**
+ * Accessor for the anchor properties
+ */
+ protected void setImageAnchor(ImageAnchorProperties iap)
+ {
+ imageAnchorProperties = iap;
+
+ if (origin == Origin.READ)
+ {
+ origin = Origin.READ_WRITE;
+ }
+ }
+
+ /**
+ * Accessor for the anchor properties
+ */
+ protected ImageAnchorProperties getImageAnchor()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return imageAnchorProperties;
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/Drawing2.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/Drawing2.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/Drawing2.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,690 @@
+/*********************************************************************
+*
+* Copyright (C) 2006 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.write.biff.File;
+
+
+/**
+ * Contains the various biff records used to insert a drawing into a
+ * worksheet. This type of image does not have an associated object
+ * record
+ */
+public class Drawing2 implements DrawingGroupObject
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(Drawing.class);
+
+ /**
+ * The spContainer that was read in
+ */
+ private EscherContainer readSpContainer;
+
+ /**
+ * The MsoDrawingRecord associated with the drawing
+ */
+ private MsoDrawingRecord msoDrawingRecord;
+
+ /**
+ * Initialized flag
+ */
+ private boolean initialized = false;
+
+ /**
+ * The file containing the image
+ */
+ private java.io.File imageFile;
+
+ /**
+ * The raw image data, used instead of an image file
+ */
+ private byte[] imageData;
+
+ /**
+ * The object id, assigned by the drawing group
+ */
+ private int objectId;
+
+ /**
+ * The blip id
+ */
+ private int blipId;
+
+ /**
+ * The column position of the image
+ */
+ private double x;
+
+ /**
+ * The row position of the image
+ */
+ private double y;
+
+ /**
+ * The width of the image in cells
+ */
+ private double width;
+
+ /**
+ * The height of the image in cells
+ */
+ private double height;
+
+ /**
+ * The number of places this drawing is referenced
+ */
+ private int referenceCount;
+
+ /**
+ * The top level escher container
+ */
+ private EscherContainer escherData;
+
+ /**
+ * Where this image came from (read, written or a copy)
+ */
+ private Origin origin;
+
+ /**
+ * The drawing group for all the images
+ */
+ private DrawingGroup drawingGroup;
+
+ /**
+ * The drawing data
+ */
+ private DrawingData drawingData;
+
+ /**
+ * The type of this drawing object
+ */
+ private ShapeType type;
+
+ /**
+ * The shape id
+ */
+ private int shapeId;
+
+ /**
+ * The drawing position on the sheet
+ */
+ private int drawingNumber;
+
+
+ /**
+ * Constructor used when reading images
+ *
+ * @param mso the drawing record
+ * @param dd the drawing data for all drawings on this sheet
+ * @param dg the drawing group
+ */
+ public Drawing2(MsoDrawingRecord mso,
+ DrawingData dd,
+ DrawingGroup dg)
+ {
+ drawingGroup = dg;
+ msoDrawingRecord = mso;
+ drawingData = dd;
+ initialized = false;
+ origin = Origin.READ;
+ // there is no drawing number associated with this drawing
+ drawingData.addRawData(msoDrawingRecord.getData());
+ drawingGroup.addDrawing(this);
+
+ Assert.verify(mso != null);
+
+ initialize();
+ }
+
+ /**
+ * Copy constructor used to copy drawings from read to write
+ *
+ * @param dgo the drawing group object
+ * @param dg the drawing group
+ */
+ protected Drawing2(DrawingGroupObject dgo, DrawingGroup dg)
+ {
+ Drawing2 d = (Drawing2) dgo;
+ Assert.verify(d.origin == Origin.READ);
+ msoDrawingRecord = d.msoDrawingRecord;
+ initialized = false;
+ origin = Origin.READ;
+ drawingData = d.drawingData;
+ drawingGroup = dg;
+ drawingNumber = d.drawingNumber;
+ drawingGroup.addDrawing(this);
+ }
+
+ /**
+ * Constructor invoked when writing the images
+ *
+ * @param x the column
+ * @param y the row
+ * @param w the width in cells
+ * @param h the height in cells
+ * @param image the image file
+ */
+ public Drawing2(double x,
+ double y,
+ double w,
+ double h,
+ java.io.File image)
+ {
+ imageFile = image;
+ initialized = true;
+ origin = Origin.WRITE;
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ referenceCount = 1;
+ type = ShapeType.PICTURE_FRAME;
+ }
+
+ /**
+ * Constructor invoked when writing the images
+ *
+ * @param x the column
+ * @param y the row
+ * @param w the width in cells
+ * @param h the height in cells
+ * @param image the image data
+ */
+ public Drawing2(double x,
+ double y,
+ double w,
+ double h,
+ byte[] image)
+ {
+ imageData = image;
+ initialized = true;
+ origin = Origin.WRITE;
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ referenceCount = 1;
+ type = ShapeType.PICTURE_FRAME;
+ }
+
+ /**
+ * Initializes the member variables from the Escher stream data
+ */
+ private void initialize()
+ {
+ initialized = true;
+ }
+
+ /**
+ * Sets the object id. Invoked by the drawing group when the object is
+ * added to id
+ *
+ * @param objid the object id
+ * @param bip the blip id
+ * @param sid the shape id
+ */
+ public final void setObjectId(int objid, int bip, int sid)
+ {
+ objectId = objid;
+ blipId = bip;
+ shapeId = sid;
+
+ if (origin == Origin.READ)
+ {
+ origin = Origin.READ_WRITE;
+ }
+ }
+
+ /**
+ * Accessor for the object id
+ *
+ * @return the object id
+ */
+ public final int getObjectId()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return objectId;
+ }
+
+ /**
+ * Accessor for the shape id
+ *
+ * @return the shape id
+ */
+ public int getShapeId()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return shapeId;
+ }
+
+ /**
+ * Accessor for the blip id
+ *
+ * @return the blip id
+ */
+ public final int getBlipId()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return blipId;
+ }
+
+ /**
+ * Gets the drawing record which was read in
+ *
+ * @return the drawing record
+ */
+ public MsoDrawingRecord getMsoDrawingRecord()
+ {
+ return msoDrawingRecord;
+ }
+
+ /**
+ * Creates the main Sp container for the drawing
+ *
+ * @return the SP container
+ */
+ public EscherContainer getSpContainer()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ Assert.verify(origin == Origin.READ);
+
+ return getReadSpContainer();
+ }
+
+ /**
+ * Sets the drawing group for this drawing. Called by the drawing group
+ * when this drawing is added to it
+ *
+ * @param dg the drawing group
+ */
+ public void setDrawingGroup(DrawingGroup dg)
+ {
+ drawingGroup = dg;
+ }
+
+ /**
+ * Accessor for the drawing group
+ *
+ * @return the drawing group
+ */
+ public DrawingGroup getDrawingGroup()
+ {
+ return drawingGroup;
+ }
+
+ /**
+ * Gets the origin of this drawing
+ *
+ * @return where this drawing came from
+ */
+ public Origin getOrigin()
+ {
+ return origin;
+ }
+
+ /**
+ * Accessor for the reference count on this drawing
+ *
+ * @return the reference count
+ */
+ public int getReferenceCount()
+ {
+ return referenceCount;
+ }
+
+ /**
+ * Sets the new reference count on the drawing
+ *
+ * @param r the new reference count
+ */
+ public void setReferenceCount(int r)
+ {
+ referenceCount = r;
+ }
+
+ /**
+ * Accessor for the column of this drawing
+ *
+ * @return the column
+ */
+ public double getX()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ return x;
+ }
+
+ /**
+ * Sets the column position of this drawing
+ *
+ * @param x the column
+ */
+ public void setX(double x)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ this.x = x;
+ }
+
+ /**
+ * Accessor for the row of this drawing
+ *
+ * @return the row
+ */
+ public double getY()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return y;
+ }
+
+ /**
+ * Accessor for the row of the drawing
+ *
+ * @param y the row
+ */
+ public void setY(double y)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ this.y = y;
+ }
+
+
+ /**
+ * Accessor for the width of this drawing
+ *
+ * @return the number of columns spanned by this image
+ */
+ public double getWidth()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return width;
+ }
+
+ /**
+ * Accessor for the width
+ *
+ * @param w the number of columns to span
+ */
+ public void setWidth(double w)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ width = w;
+ }
+
+ /**
+ * Accessor for the height of this drawing
+ *
+ * @return the number of rows spanned by this image
+ */
+ public double getHeight()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return height;
+ }
+
+ /**
+ * Accessor for the height of this drawing
+ *
+ * @param h the number of rows spanned by this image
+ */
+ public void setHeight(double h)
+ {
+ if (origin == Origin.READ)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+ origin = Origin.READ_WRITE;
+ }
+
+ height = h;
+ }
+
+
+ /**
+ * Gets the SpContainer that was read in
+ *
+ * @return the read sp container
+ */
+ private EscherContainer getReadSpContainer()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return readSpContainer;
+ }
+
+ /**
+ * Accessor for the image data
+ *
+ * @return the image data
+ */
+ public byte[] getImageData()
+ {
+ Assert.verify(false);
+ Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE);
+
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ return drawingGroup.getImageData(blipId);
+ }
+
+ /**
+ * Accessor for the image data
+ *
+ * @return the image data
+ */
+ public byte[] getImageBytes() throws IOException
+ {
+ Assert.verify(false);
+ if (origin == Origin.READ || origin == Origin.READ_WRITE)
+ {
+ return getImageData();
+ }
+
+ Assert.verify(origin == Origin.WRITE);
+
+ if (imageFile == null)
+ {
+ Assert.verify(imageData != null);
+ return imageData;
+ }
+
+ byte[] data = new byte[(int) imageFile.length()];
+ FileInputStream fis = new FileInputStream(imageFile);
+ fis.read(data, 0, data.length);
+ fis.close();
+ return data;
+ }
+
+ /**
+ * Accessor for the type
+ *
+ * @return the type
+ */
+ public ShapeType getType()
+ {
+ return type;
+ }
+
+ /**
+ * Writes any other records associated with this drawing group object
+ *
+ * @param outputFile the output file
+ * @exception IOException
+ */
+ public void writeAdditionalRecords(File outputFile) throws IOException
+ {
+ // no records to write
+ }
+
+ /**
+ * Writes any records that need to be written after all the drawing group
+ * objects have been written
+ * Does nothing here
+ *
+ * @param outputFile the output file
+ * @exception IOException
+ */
+ public void writeTailRecords(File outputFile) throws IOException
+ {
+ // does nothing
+ }
+
+ /**
+ * Interface method
+ *
+ * @return the column number at which the image is positioned
+ */
+ public double getColumn()
+ {
+ return getX();
+ }
+
+ /**
+ * Interface method
+ *
+ * @return the row number at which the image is positions
+ */
+ public double getRow()
+ {
+ return getY();
+ }
+
+ /**
+ * Accessor for the first drawing on the sheet. This is used when
+ * copying unmodified sheets to indicate that this drawing contains
+ * the first time Escher gubbins
+ *
+ * @return TRUE if this MSORecord is the first drawing on the sheet
+ */
+ public boolean isFirst()
+ {
+ return msoDrawingRecord.isFirst();
+ }
+
+ /**
+ * Queries whether this object is a form object. Form objects have their
+ * drawings records spread over TXO and CONTINUE records and
+ * require special handling
+ *
+ * @return TRUE if this is a form object, FALSE otherwise
+ */
+ public boolean isFormObject()
+ {
+ return false;
+ }
+
+ /**
+ * Removes a row
+ *
+ * @param r the row to be removed
+ */
+ public void removeRow(int r)
+ {
+ if (y > r)
+ {
+ setY(r);
+ }
+ }
+
+ /**
+ * Accessor for the image file path. Normally this is the absolute path
+ * of a file on the directory system, but if this drawing was constructed
+ * using an byte[] then the blip id is returned
+ *
+ * @return the image file path, or the blip id
+ */
+ public String getImageFilePath()
+ {
+ Assert.verify(false);
+ return null;
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/DrawingData.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/DrawingData.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/DrawingData.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,232 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.util.ArrayList;
+
+import common.Assert;
+import common.Logger;
+
+/**
+ * Class used to concatenate all the data for the various drawing objects
+ * into one continuous stream
+ */
+public class DrawingData implements EscherStream
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(DrawingData.class);
+
+ /**
+ * The drawing data
+ */
+ private byte[] drawingData;
+
+ /**
+ * The number of drawings
+ */
+ private int numDrawings;
+
+ /**
+ * Initialized flag
+ */
+ private boolean initialized;
+
+ /**
+ * The spgr container. The contains the SpContainer for each drawing
+ */
+ private EscherRecord[] spContainers;
+
+ /**
+ * Constructor
+ */
+ public DrawingData()
+ {
+ numDrawings = 0;
+ drawingData = null;
+ initialized = false;
+ }
+
+ /**
+ * Initialization
+ */
+ private void initialize()
+ {
+ EscherRecordData er = new EscherRecordData(this, 0);
+ Assert.verify(er.isContainer());
+
+ EscherContainer dgContainer = new EscherContainer(er);
+ EscherRecord[] children = dgContainer.getChildren();
+
+ children = dgContainer.getChildren();
+ // Dg dg = (Dg) children[0];
+
+ EscherContainer spgrContainer = null;
+
+ for (int i = 0; i < children.length && spgrContainer == null; i++)
+ {
+ EscherRecord child = children[i];
+ if (child.getType() == EscherRecordType.SPGR_CONTAINER)
+ {
+ spgrContainer = (EscherContainer) child;
+ }
+ }
+ Assert.verify(spgrContainer != null);
+
+ EscherRecord[] spgrChildren = spgrContainer.getChildren();
+
+ // See if any of the spgrChildren are SpgrContainer
+ boolean nestedContainers = false;
+ for (int i = 0; i < spgrChildren.length && !nestedContainers; i++)
+ {
+ if (spgrChildren[i].getType() == EscherRecordType.SPGR_CONTAINER)
+ {
+ nestedContainers = true;
+ }
+ }
+
+ // If there are no nested containers, simply set the spContainer list
+ // to be the list of children
+ if (!nestedContainers)
+ {
+ spContainers = spgrChildren;
+ }
+ else
+ {
+ // Go through the hierarchy and dig out all the Sp containers
+ ArrayList sps = new ArrayList();
+ getSpContainers(spgrContainer, sps);
+ spContainers = new EscherRecord[sps.size()];
+ spContainers = (EscherRecord[]) sps.toArray(spContainers);
+ }
+
+ initialized = true;
+ }
+
+ /**
+ * Gets the sp container from the internal data
+ *
+ * @param spgrContainer the spgr container
+ * @param sps the list of sp records
+ */
+ private void getSpContainers(EscherContainer spgrContainer, ArrayList sps)
+ {
+ EscherRecord[] spgrChildren = spgrContainer.getChildren();
+ for (int i = 0; i < spgrChildren.length; i++)
+ {
+ if (spgrChildren[i].getType() == EscherRecordType.SP_CONTAINER)
+ {
+ sps.add(spgrChildren[i]);
+ }
+ else if (spgrChildren[i].getType() == EscherRecordType.SPGR_CONTAINER)
+ {
+ getSpContainers((EscherContainer) spgrChildren[i], sps);
+ }
+ else
+ {
+ logger.warn("Spgr Containers contains a record other than Sp/Spgr " +
+ "containers");
+ }
+ }
+ }
+
+ /**
+ * Adds the byte stream to the drawing data
+ *
+ * @param data the data to add
+ */
+ public void addData(byte[] data)
+ {
+ addRawData(data);
+ numDrawings++;
+ }
+
+ /**
+ * Adds the data to the array without incrementing the drawing number.
+ * This is used by comments, which for some bizarre and inexplicable
+ * reason split out the data
+ *
+ * @param data the data to add
+ */
+ public void addRawData(byte[] data)
+ {
+ if (drawingData == null)
+ {
+ drawingData = data;
+ return;
+ }
+
+ // Resize the array
+ byte[] newArray = new byte[drawingData.length + data.length];
+ System.arraycopy(drawingData, 0, newArray, 0, drawingData.length);
+ System.arraycopy(data, 0, newArray, drawingData.length, data.length);
+ drawingData = newArray;
+
+ // Dirty up this object
+ initialized = false;
+ }
+
+ /**
+ * Accessor for the number of drawings
+ *
+ * @return the current count of drawings
+ */
+ final int getNumDrawings()
+ {
+ return numDrawings;
+ }
+
+ /**
+ * Gets the sp container for the specified drawing number
+ *
+ * @param drawingNum the drawing number for which to return the spContainer
+ * @return the spcontainer
+ */
+ EscherContainer getSpContainer(int drawingNum)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ if ( (drawingNum + 1) >= spContainers.length)
+ {
+ throw new DrawingDataException();
+ }
+
+ EscherContainer spContainer =
+ (EscherContainer) spContainers[drawingNum + 1];
+
+ Assert.verify(spContainer != null);
+
+ return spContainer;
+ }
+
+ /**
+ * Gets the data which was read in for the drawings
+ *
+ * @return the drawing data
+ */
+ public byte[] getData()
+ {
+ return drawingData;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/DrawingDataException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/DrawingDataException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/DrawingDataException.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,37 @@
+/*********************************************************************
+*
+* Copyright (C) 2006 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+/**
+ * Checked exception thrown when the drawing data is corrupt eg. when
+ * the drawing number exceeds the number of SpContainers. This exception
+ * is handled within the drawing package, and usually causes drawings to be
+ * disabled for the remainder of the workbook
+ */
+public class DrawingDataException extends RuntimeException
+{
+ private static String message =
+ "Drawing number exceeds available SpContainers";
+
+ DrawingDataException()
+ {
+ super(message);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/DrawingGroup.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/DrawingGroup.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/DrawingGroup.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,584 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.read.biff.Record;
+import jxl.write.biff.File;
+
+/**
+ * This class contains the Excel picture data in Escher format for the
+ * entire workbook
+ */
+public class DrawingGroup implements EscherStream
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(DrawingGroup.class);
+
+ /**
+ * The escher data read in from file
+ */
+ private byte[] drawingData;
+
+ /**
+ * The top level escher container
+ */
+ private EscherContainer escherData;
+
+ /**
+ * The Bstore container, which contains all the drawing data
+ */
+ private BStoreContainer bstoreContainer;
+
+ /**
+ * The initialized flag
+ */
+ private boolean initialized;
+
+ /**
+ * The list of user added drawings
+ */
+ private ArrayList drawings;
+
+ /**
+ * The number of blips
+ */
+ private int numBlips;
+
+ /**
+ * The number of charts
+ */
+ private int numCharts;
+
+ /**
+ * The number of shape ids used on the second Dgg cluster
+ */
+ private int drawingGroupId;
+
+ /**
+ * Flag which indicates that at least one of the drawings has been omitted
+ * from the worksheet
+ */
+ private boolean drawingsOmitted;
+
+ /**
+ * The origin of this drawing group
+ */
+ private Origin origin;
+
+ /**
+ * A hash map of images keyed on the file path, containing the
+ * reference count
+ */
+ private HashMap imageFiles;
+
+ /**
+ * A count of the next available object id
+ */
+ private int maxObjectId;
+
+ /**
+ * The maximum shape id so far encountered
+ */
+ private int maxShapeId;
+
+ /**
+ * Constructor
+ *
+ * @param o the origin of this drawing group
+ */
+ public DrawingGroup(Origin o)
+ {
+ origin = o;
+ initialized = o == Origin.WRITE ? true : false;
+ drawings = new ArrayList();
+ imageFiles = new HashMap();
+ drawingsOmitted = false;
+ maxObjectId = 1;
+ maxShapeId = 1024;
+ }
+
+ /**
+ * Copy constructor
+ * Uses a shallow copy for most things, since as soon as anything
+ * is changed, the drawing group is invalidated and all the data blocks
+ * regenerated
+ *
+ * @param dg the drawing group to copy
+ */
+ public DrawingGroup(DrawingGroup dg)
+ {
+ drawingData = dg.drawingData;
+ escherData = dg.escherData;
+ bstoreContainer = dg.bstoreContainer;
+ initialized = dg.initialized;
+ drawingData = dg.drawingData;
+ escherData = dg.escherData;
+ bstoreContainer = dg.bstoreContainer;
+ numBlips = dg.numBlips;
+ numCharts = dg.numCharts;
+ drawingGroupId = dg.drawingGroupId;
+ drawingsOmitted = dg.drawingsOmitted;
+ origin = dg.origin;
+ imageFiles = (HashMap) dg.imageFiles.clone();
+ maxObjectId = dg.maxObjectId;
+ maxShapeId = dg.maxShapeId;
+
+ // Create this as empty, because all drawings will get added later
+ // as part of the sheet copy process
+ drawings = new ArrayList();
+ }
+
+ /**
+
+ /**
+ * Adds in a drawing group record to this drawing group. The binary
+ * data is extracted from the drawing group and added to a single
+ * byte array
+ *
+ * @param mso the drawing group record to add
+ */
+ public void add(MsoDrawingGroupRecord mso)
+ {
+ addData(mso.getData());
+ }
+
+ /**
+ * Adds a continue record to this drawing group. the binary data is
+ * extracted and appended to the byte array
+ *
+ * @param cont the continue record
+ */
+ public void add(Record cont)
+ {
+ addData(cont.getData());
+ }
+
+ /**
+ * Adds the mso record data to the drawing data
+ *
+ * @param msodata the raw mso data
+ */
+ private void addData(byte[] msodata)
+ {
+ if (drawingData == null)
+ {
+ drawingData = new byte[msodata.length];
+ System.arraycopy(msodata, 0, drawingData, 0, msodata.length);
+ return;
+ }
+
+ // Grow the array
+ byte[] newdata = new byte[drawingData.length + msodata.length];
+ System.arraycopy(drawingData, 0, newdata, 0, drawingData.length);
+ System.arraycopy(msodata, 0, newdata, drawingData.length, msodata.length);
+ drawingData = newdata;
+ }
+
+ /**
+ * Adds a drawing to the drawing group
+ *
+ * @param d the drawing to add
+ */
+ final void addDrawing(DrawingGroupObject d)
+ {
+ drawings.add(d);
+ maxObjectId = Math.max(maxObjectId, d.getObjectId());
+ maxShapeId = Math.max(maxShapeId, d.getShapeId());
+ }
+
+ /**
+ * Adds a chart to the drawing group
+ *
+ * @param c the chart
+ */
+ public void add(Chart c)
+ {
+ numCharts++;
+ }
+
+ /**
+ * Adds a drawing from the public, writable interface
+ *
+ * @param d the drawing to add
+ */
+ public void add(DrawingGroupObject d)
+ {
+ if (origin == Origin.READ)
+ {
+ origin = Origin.READ_WRITE;
+ BStoreContainer bsc = getBStoreContainer(); // force initialization
+ Dgg dgg = (Dgg) escherData.getChildren()[0];
+ drawingGroupId = dgg.getCluster(1).drawingGroupId - numBlips - 1;
+ numBlips = bsc != null ? bsc.getNumBlips() : 0;
+
+ if (bsc != null)
+ {
+ Assert.verify(numBlips == bsc.getNumBlips());
+ }
+ }
+
+ if (!(d instanceof Drawing))
+ {
+ // Assign a new object id and add it to the list
+ // drawings.add(d);
+ maxObjectId++;
+ maxShapeId++;
+ d.setDrawingGroup(this);
+ d.setObjectId(maxObjectId, numBlips + 1, maxShapeId);
+ if (drawings.size() > maxObjectId)
+ {
+ logger.warn("drawings length " + drawings.size() +
+ " exceeds the max object id " + maxObjectId);
+ }
+ // numBlips++;
+ return;
+ }
+
+ Drawing drawing = (Drawing) d;
+
+ // See if this is referenced elsewhere
+ Drawing refImage =
+ (Drawing) imageFiles.get(d.getImageFilePath());
+
+ if (refImage == null)
+ {
+ // There are no other references to this drawing, so assign
+ // a new object id and put it on the hash map
+ maxObjectId++;
+ maxShapeId++;
+ drawings.add(drawing);
+ drawing.setDrawingGroup(this);
+ drawing.setObjectId(maxObjectId, numBlips + 1, maxShapeId);
+ numBlips++;
+ imageFiles.put(drawing.getImageFilePath(), drawing);
+ }
+ else
+ {
+ // This drawing is used elsewhere in the workbook. Increment the
+ // reference count on the drawing, and set the object id of the drawing
+ // passed in
+ refImage.setReferenceCount(refImage.getReferenceCount() + 1);
+ drawing.setDrawingGroup(this);
+ drawing.setObjectId(refImage.getObjectId(),
+ refImage.getBlipId(),
+ refImage.getShapeId());
+ }
+ }
+
+ /**
+ * Interface method to remove a drawing from the group
+ *
+ * @param d the drawing to remove
+ */
+ public void remove(DrawingGroupObject d)
+ {
+ // Unless there are real images or some such, it is possible that
+ // a BStoreContainer will not be present. In that case simply return
+ if (getBStoreContainer() == null)
+ {
+ return;
+ }
+
+ if (origin == Origin.READ)
+ {
+ origin = Origin.READ_WRITE;
+ numBlips = getBStoreContainer().getNumBlips();
+ Dgg dgg = (Dgg) escherData.getChildren()[0];
+ drawingGroupId = dgg.getCluster(1).drawingGroupId - numBlips - 1;
+ }
+
+ // Get the blip
+ EscherRecord[] children = getBStoreContainer().getChildren();
+ BlipStoreEntry bse = (BlipStoreEntry) children[d.getBlipId() - 1];
+
+ bse.dereference();
+
+ if (bse.getReferenceCount() == 0)
+ {
+ // Remove the blip
+ getBStoreContainer().remove(bse);
+
+ // Adjust blipId on the other blips
+ for (Iterator i = drawings.iterator(); i.hasNext();)
+ {
+ DrawingGroupObject drawing = (DrawingGroupObject) i.next();
+
+ if (drawing.getBlipId() > d.getBlipId())
+ {
+ drawing.setObjectId(drawing.getObjectId(),
+ drawing.getBlipId() - 1,
+ drawing.getShapeId());
+ }
+ }
+
+ numBlips--;
+ }
+ }
+
+
+ /**
+ * Initializes the drawing data from the escher record read in
+ */
+ private void initialize()
+ {
+ EscherRecordData er = new EscherRecordData(this, 0);
+
+ Assert.verify(er.isContainer());
+
+ escherData = new EscherContainer(er);
+
+ Assert.verify(escherData.getLength() == drawingData.length);
+ Assert.verify(escherData.getType() == EscherRecordType.DGG_CONTAINER);
+
+ initialized = true;
+ }
+
+ /**
+ * Gets hold of the BStore container from the Escher data
+ *
+ * @return the BStore container
+ */
+ private BStoreContainer getBStoreContainer()
+ {
+ if (bstoreContainer == null)
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ EscherRecord[] children = escherData.getChildren();
+ if (children.length > 1 &&
+ children[1].getType() == EscherRecordType.BSTORE_CONTAINER)
+ {
+ bstoreContainer = (BStoreContainer) children[1];
+ }
+ }
+
+ return bstoreContainer;
+ }
+
+ /**
+ * Gets hold of the binary data
+ *
+ * @return the data
+ */
+ public byte[] getData()
+ {
+ return drawingData;
+ }
+
+ /**
+ * Writes the drawing group to the output file
+ *
+ * @param outputFile the file to write to
+ * @exception IOException
+ */
+ public void write(File outputFile) throws IOException
+ {
+ if (origin == Origin.WRITE)
+ {
+ DggContainer dggContainer = new DggContainer();
+
+ Dgg dgg = new Dgg(numBlips + numCharts + 1, numBlips);
+
+ dgg.addCluster(1, 0);
+ dgg.addCluster(numBlips + 1, 0);
+
+ dggContainer.add(dgg);
+
+ int drawingsAdded = 0;
+ BStoreContainer bstoreCont = new BStoreContainer();
+
+ // Create a blip entry for each drawing
+ for (Iterator i = drawings.iterator(); i.hasNext();)
+ {
+ Object o = i.next();
+ if (o instanceof Drawing)
+ {
+ Drawing d = (Drawing) o;
+ BlipStoreEntry bse = new BlipStoreEntry(d);
+
+ bstoreCont.add(bse);
+ drawingsAdded++;
+ }
+ }
+ if (drawingsAdded > 0)
+ {
+ bstoreCont.setNumBlips(drawingsAdded);
+ dggContainer.add(bstoreCont);
+ }
+
+ Opt opt = new Opt();
+
+ dggContainer.add(opt);
+
+ SplitMenuColors splitMenuColors = new SplitMenuColors();
+ dggContainer.add(splitMenuColors);
+
+ drawingData = dggContainer.getData();
+ }
+ else if (origin == Origin.READ_WRITE)
+ {
+ DggContainer dggContainer = new DggContainer();
+
+ Dgg dgg = new Dgg(numBlips + numCharts + 1, numBlips);
+
+ dgg.addCluster(1, 0);
+ dgg.addCluster(drawingGroupId + numBlips + 1, 0);
+
+ dggContainer.add(dgg);
+
+ BStoreContainer bstoreCont = new BStoreContainer();
+ bstoreCont.setNumBlips(numBlips);
+
+ // Create a blip entry for each drawing that was read in
+ BStoreContainer readBStoreContainer = getBStoreContainer();
+
+ if (readBStoreContainer != null)
+ {
+ EscherRecord[] children = readBStoreContainer.getChildren();
+ for (int i = 0; i < children.length; i++)
+ {
+ BlipStoreEntry bse = (BlipStoreEntry) children[i];
+ bstoreCont.add(bse);
+ }
+ }
+
+ // Create a blip entry for each drawing that has been added
+ for (Iterator i = drawings.iterator(); i.hasNext();)
+ {
+ DrawingGroupObject dgo = (DrawingGroupObject) i.next();
+ if (dgo instanceof Drawing)
+ {
+ Drawing d = (Drawing) dgo;
+ if (d.getOrigin() == Origin.WRITE)
+ {
+ BlipStoreEntry bse = new BlipStoreEntry(d);
+ bstoreCont.add(bse);
+ }
+ }
+ }
+
+ dggContainer.add(bstoreCont);
+
+ Opt opt = new Opt();
+
+ opt.addProperty(191, false, false, 524296);
+ opt.addProperty(385, false, false, 134217737);
+ opt.addProperty(448, false, false, 134217792);
+
+ dggContainer.add(opt);
+
+ SplitMenuColors splitMenuColors = new SplitMenuColors();
+ dggContainer.add(splitMenuColors);
+
+ drawingData = dggContainer.getData();
+ }
+
+ MsoDrawingGroupRecord msodg = new MsoDrawingGroupRecord(drawingData);
+ outputFile.write(msodg);
+ }
+
+ /**
+ * Accessor for the number of blips in the drawing group
+ *
+ * @return the number of blips
+ */
+ final int getNumberOfBlips()
+ {
+ return numBlips;
+ }
+
+ /**
+ * Gets the drawing data for the given blip id. Called by the Drawing
+ * object
+ *
+ * @param blipId the blipId
+ * @return the drawing data
+ */
+ byte[] getImageData(int blipId)
+ {
+ numBlips = getBStoreContainer().getNumBlips();
+
+ Assert.verify(blipId <= numBlips);
+ Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE);
+
+ // Get the blip
+ EscherRecord[] children = getBStoreContainer().getChildren();
+ BlipStoreEntry bse = (BlipStoreEntry) children[blipId - 1];
+
+ return bse.getImageData();
+ }
+
+ /**
+ * Indicates that at least one of the drawings has been omitted from
+ * the worksheet
+
+ * @param mso the mso record
+ * @param obj the obj record
+ */
+ public void setDrawingsOmitted(MsoDrawingRecord mso, ObjRecord obj)
+ {
+ drawingsOmitted = true;
+
+ if (obj != null)
+ {
+ maxObjectId = Math.max(maxObjectId, obj.getObjectId());
+ }
+ }
+
+ /**
+ * Accessor for the drawingsOmitted flag
+ *
+ * @return TRUE if a drawing has been omitted, FALSE otherwise
+ */
+ public boolean hasDrawingsOmitted()
+ {
+ return drawingsOmitted;
+ }
+
+ /**
+ * Updates this with the appropriate data from the drawing group passed in
+ * This is called during the copy process: this is first initialised as
+ * an empty object, but during the copy, the source DrawingGroup may
+ * change. After the copy process, this method is then called to update
+ * the relevant fields. Unfortunately, the copy process required the
+ * presence of a drawing group
+ *
+ * @param dg the drawing group containing the updated data
+ */
+ public void updateData(DrawingGroup dg)
+ {
+ drawingsOmitted = dg.drawingsOmitted;
+ maxObjectId = dg.maxObjectId;
+ maxShapeId = dg.maxShapeId;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/DrawingGroupObject.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/DrawingGroupObject.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/DrawingGroupObject.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,233 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.io.IOException;
+
+import jxl.write.biff.File;
+
+/**
+ * Interface for the various object types that can be added to a drawing
+ * group
+ */
+public interface DrawingGroupObject
+{
+ /**
+ * Sets the object id. Invoked by the drawing group when the object is
+ * added to id
+ *
+ * @param objid the object id
+ * @param bip the blip id
+ * @param sid the shape id
+ */
+ void setObjectId(int objid, int bip, int sid);
+
+ /**
+ * Accessor for the object id
+ *
+ * @return the object id
+ */
+ int getObjectId();
+
+ /**
+ * Accessor for the blip id
+ *
+ * @return the blip id
+ */
+ int getBlipId();
+
+ /**
+ * Accessor for the shape id
+ *
+ * @return the shape id
+ */
+ public int getShapeId();
+
+
+ /**
+ * Gets the drawing record which was read in
+ *
+ * @return the drawing record
+ */
+ MsoDrawingRecord getMsoDrawingRecord();
+
+ /**
+ * Creates the main Sp container for the drawing
+ *
+ * @return the SP container
+ */
+ public EscherContainer getSpContainer();
+
+ /**
+ * Sets the drawing group for this drawing. Called by the drawing group
+ * when this drawing is added to it
+ *
+ * @param dg the drawing group
+ */
+ void setDrawingGroup(DrawingGroup dg);
+
+ /**
+ * Accessor for the drawing group
+ *
+ * @return the drawing group
+ */
+ DrawingGroup getDrawingGroup();
+
+ /**
+ * Gets the origin of this drawing
+ *
+ * @return where this drawing came from
+ */
+ Origin getOrigin();
+
+ /**
+ * Accessor for the reference count on this drawing
+ *
+ * @return the reference count
+ */
+ int getReferenceCount();
+
+ /**
+ * Sets the new reference count on the drawing
+ *
+ * @param r the new reference count
+ */
+ void setReferenceCount(int r);
+
+ /**
+ * Accessor for the column of this drawing
+ *
+ * @return the column
+ */
+ public double getX();
+
+ /**
+ * Sets the column position of this drawing
+ *
+ * @param x the column
+ */
+ public void setX(double x);
+
+ /**
+ * Accessor for the row of this drawing
+ *
+ * @return the row
+ */
+ public double getY();
+
+ /**
+ * Accessor for the row of the drawing
+ *
+ * @param y the row
+ */
+ public void setY(double y);
+
+ /**
+ * Accessor for the width of this drawing
+ *
+ * @return the number of columns spanned by this image
+ */
+ public double getWidth();
+
+ /**
+ * Accessor for the width
+ *
+ * @param w the number of columns to span
+ */
+ public void setWidth(double w);
+
+ /**
+ * Accessor for the height of this drawing
+ *
+ * @return the number of rows spanned by this image
+ */
+ public double getHeight();
+
+ /**
+ * Accessor for the height of this drawing
+ *
+ * @param h the number of rows spanned by this image
+ */
+ public void setHeight(double h);
+
+
+ /**
+ * Accessor for the type
+ *
+ * @return the type
+ */
+ ShapeType getType();
+
+ /**
+ * Accessor for the image data
+ *
+ * @return the image data
+ */
+ public byte[] getImageData();
+
+ /**
+ * Accessor for the image data
+ *
+ * @return the image data
+ */
+ public byte[] getImageBytes() throws IOException;
+
+ /**
+ * Accessor for the image file path. Normally this is the absolute path
+ * of a file on the directory system, but if this drawing was constructed
+ * using an byte[] then the blip id is returned
+ *
+ * @return the image file path, or the blip id
+ */
+ String getImageFilePath();
+
+ /**
+ * Writes any other records associated with this drawing group object
+ */
+ public void writeAdditionalRecords(File outputFile) throws IOException;
+
+ /**
+ * Writes any records that need to be written after all the drawing group
+ * objects have been written
+ */
+ public void writeTailRecords(File outputFile) throws IOException;
+
+ /**
+ * Accessor for the first drawing on the sheet. This is used when
+ * copying unmodified sheets to indicate that this drawing contains
+ * the first time Escher gubbins
+ *
+ * @return TRUE if this MSORecord is the first drawing on the sheet
+ */
+ public boolean isFirst();
+
+ /**
+ * Queries whether this object is a form object. Form objects have their
+ * drawings records spread over TXO and CONTINUE records and
+ * require special handling
+ *
+ * @return TRUE if this is a form object, FALSE otherwise
+ */
+ public boolean isFormObject();
+
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherAtom.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherAtom.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherAtom.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,67 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import common.Logger;
+
+/**
+ * Class for atoms. This may be instantiated as is for unknown/uncared about
+ * atoms, or subclassed if we have some semantic interest in the contents
+ */
+class EscherAtom extends EscherRecord
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(EscherAtom.class);
+
+ /**
+ * Constructor
+ *
+ * @param erd the escher record data
+ */
+ public EscherAtom(EscherRecordData erd)
+ {
+ super(erd);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param type the type
+ */
+ protected EscherAtom(EscherRecordType type)
+ {
+ super(type);
+ }
+
+ /**
+ * Gets the data for writing
+ *
+ * @return the data
+ */
+ byte[] getData()
+ {
+ logger.warn("escher atom getData called on object of type " +
+ getClass().getName() + " code " +
+ Integer.toString(getType().getValue(), 16));
+ return null;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherContainer.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherContainer.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherContainer.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,218 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import common.Logger;
+
+/**
+ * An escher container. This record may contain other escher containers or
+ * atoms
+ */
+class EscherContainer extends EscherRecord
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(EscherContainer.class);
+
+ /**
+ * Initialized flag
+ */
+ private boolean initialized;
+
+
+ /**
+ * The children of this container
+ */
+ private ArrayList children;
+
+ /**
+ * Constructor
+ *
+ * @param erd the raw data
+ */
+ public EscherContainer(EscherRecordData erd)
+ {
+ super(erd);
+ initialized = false;
+ children = new ArrayList();
+ }
+
+ /**
+ * Constructor used when writing out escher data
+ *
+ * @param type the type
+ */
+ protected EscherContainer(EscherRecordType type)
+ {
+ super(type);
+ setContainer(true);
+ children = new ArrayList();
+ }
+
+ /**
+ * Accessor for the children of this container
+ *
+ * @return the children
+ */
+ public EscherRecord[] getChildren()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ Object[] ca = children.toArray(new EscherRecord[children.size()]);
+
+ return (EscherRecord[]) ca;
+ }
+
+ /**
+ * Adds a child to this container
+ *
+ * @param child the item to add
+ */
+ public void add(EscherRecord child)
+ {
+ children.add(child);
+ }
+
+ /**
+ * Removes a child from this container
+ *
+ * @param child the item to remove
+ */
+ public void remove(EscherRecord child)
+ {
+ boolean result = children.remove(child);
+ }
+
+ /**
+ * Initialization
+ */
+ private void initialize()
+ {
+ int curpos = getPos() + HEADER_LENGTH;
+ int endpos = Math.min(getPos() + getLength(), getStreamLength());
+
+ EscherRecord newRecord = null;
+
+ while (curpos < endpos)
+ {
+ EscherRecordData erd = new EscherRecordData(getEscherStream(), curpos);
+
+ EscherRecordType type = erd.getType();
+ if (type == EscherRecordType.DGG)
+ {
+ newRecord = new Dgg(erd);
+ }
+ else if (type == EscherRecordType.DG)
+ {
+ newRecord = new Dg(erd);
+ }
+ else if (type == EscherRecordType.BSTORE_CONTAINER)
+ {
+ newRecord = new BStoreContainer(erd);
+ }
+ else if (type == EscherRecordType.SPGR_CONTAINER)
+ {
+ newRecord = new SpgrContainer(erd);
+ }
+ else if (type == EscherRecordType.SP_CONTAINER)
+ {
+ newRecord = new SpContainer(erd);
+ }
+ else if (type == EscherRecordType.SPGR)
+ {
+ newRecord = new Spgr(erd);
+ }
+ else if (type == EscherRecordType.SP)
+ {
+ newRecord = new Sp(erd);
+ }
+ else if (type == EscherRecordType.CLIENT_ANCHOR)
+ {
+ newRecord = new ClientAnchor(erd);
+ }
+ else if (type == EscherRecordType.CLIENT_DATA)
+ {
+ newRecord = new ClientData(erd);
+ }
+ else if (type == EscherRecordType.BSE)
+ {
+ newRecord = new BlipStoreEntry(erd);
+ }
+ else if (type == EscherRecordType.OPT)
+ {
+ newRecord = new Opt(erd);
+ }
+ else if (type == EscherRecordType.SPLIT_MENU_COLORS)
+ {
+ newRecord = new SplitMenuColors(erd);
+ }
+ else if (type == EscherRecordType.CLIENT_TEXT_BOX)
+ {
+ newRecord = new ClientTextBox(erd);
+ }
+ else
+ {
+ newRecord = new EscherAtom(erd);
+ }
+
+ children.add(newRecord);
+ curpos += newRecord.getLength();
+ }
+
+ initialized = true;
+ }
+
+ /**
+ * Gets the data for this container (and all of its children recursively
+ *
+ * @return the binary data
+ */
+ byte[] getData()
+ {
+ if (!initialized)
+ {
+ initialize();
+ }
+
+ byte[] data = new byte[0];
+ for (Iterator i = children.iterator(); i.hasNext();)
+ {
+ EscherRecord er = (EscherRecord) i.next();
+ byte[] childData = er.getData();
+
+ if (childData != null)
+ {
+ byte[] newData = new byte[data.length + childData.length];
+ System.arraycopy(data, 0, newData, 0, data.length);
+ System.arraycopy(childData, 0, newData, data.length, childData.length);
+ data = newData;
+ }
+ }
+
+ return setHeaderData(data);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherDisplay.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherDisplay.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherDisplay.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,212 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+
+/**
+ * Class used to display a complete hierarchically organized Escher stream
+ * The whole thing is dumped to System.out
+ *
+ * This class is only used as a debugging tool
+ */
+public class EscherDisplay
+{
+ /**
+ * The escher stream
+ */
+ private EscherStream stream;
+
+ /**
+ * The writer
+ */
+ private BufferedWriter writer;
+
+ /**
+ * Constructor
+ *
+ * @param s the stream
+ * @param bw the writer
+ */
+ public EscherDisplay(EscherStream s, BufferedWriter bw)
+ {
+ stream = s;
+ writer = bw;
+ }
+
+ /**
+ * Display the formatted escher stream
+ *
+ * @exception IOException
+ */
+ public void display() throws IOException
+ {
+ EscherRecordData er = new EscherRecordData(stream, 0);
+ EscherContainer ec = new EscherContainer(er);
+ displayContainer(ec, 0);
+ }
+
+ /**
+ * Displays the escher container as text
+ *
+ * @param ec the escher container
+ * @param level the indent level
+ * @exception IOException
+ */
+ private void displayContainer(EscherContainer ec, int level)
+ throws IOException
+ {
+ displayRecord(ec, level);
+
+ // Display the contents of the container
+ level++;
+
+ EscherRecord[] children = ec.getChildren();
+
+ for (int i = 0; i < children.length; i++)
+ {
+ EscherRecord er = children[i];
+ if (er.getEscherData().isContainer())
+ {
+ displayContainer((EscherContainer) er, level);
+ }
+ else
+ {
+ displayRecord(er, level);
+ }
+ }
+ }
+
+ /**
+ * Displays an escher record
+ *
+ * @param er the record to display
+ * @param level the amount of indentation
+ * @exception IOException
+ */
+ private void displayRecord(EscherRecord er, int level)
+ throws IOException
+ {
+ indent(level);
+
+ EscherRecordType type = er.getType();
+
+ // Display the code
+ writer.write(Integer.toString(type.getValue(), 16));
+ writer.write(" - ");
+
+ // Display the name
+ if (type == EscherRecordType.DGG_CONTAINER)
+ {
+ writer.write("Dgg Container");
+ writer.newLine();
+ }
+ else if (type == EscherRecordType.BSTORE_CONTAINER)
+ {
+ writer.write("BStore Container");
+ writer.newLine();
+ }
+ else if (type == EscherRecordType.DG_CONTAINER)
+ {
+ writer.write("Dg Container");
+ writer.newLine();
+ }
+ else if (type == EscherRecordType.SPGR_CONTAINER)
+ {
+ writer.write("Spgr Container");
+ writer.newLine();
+ }
+ else if (type == EscherRecordType.SP_CONTAINER)
+ {
+ writer.write("Sp Container");
+ writer.newLine();
+ }
+ else if (type == EscherRecordType.DGG)
+ {
+ writer.write("Dgg");
+ writer.newLine();
+ }
+ else if (type == EscherRecordType.BSE)
+ {
+ writer.write("Bse");
+ writer.newLine();
+ }
+ else if (type == EscherRecordType.DG)
+ {
+ writer.write("Dg");
+ writer.newLine();
+ }
+ else if (type == EscherRecordType.SPGR)
+ {
+ writer.write("Spgr");
+ writer.newLine();
+ }
+ else if (type == EscherRecordType.SP)
+ {
+ writer.write("Sp");
+ writer.newLine();
+ }
+ else if (type == EscherRecordType.OPT)
+ {
+ writer.write("Opt");
+ writer.newLine();
+ }
+ else if (type == EscherRecordType.CLIENT_ANCHOR)
+ {
+ writer.write("Client Anchor");
+ writer.newLine();
+ }
+ else if (type == EscherRecordType.CLIENT_DATA)
+ {
+ writer.write("Client Data");
+ writer.newLine();
+ }
+ else if (type == EscherRecordType.CLIENT_TEXT_BOX)
+ {
+ writer.write("Client Text Box");
+ writer.newLine();
+ }
+ else if (type == EscherRecordType.SPLIT_MENU_COLORS)
+ {
+ writer.write("Split Menu Colors");
+ writer.newLine();
+ }
+ else
+ {
+ writer.write("???");
+ writer.newLine();
+ }
+ }
+
+ /**
+ * Indents to the amount specified by the level
+ *
+ * @param level the level
+ * @exception IOException
+ */
+ private void indent(int level) throws IOException
+ {
+ for (int i = 0; i < level * 2; i++)
+ {
+ writer.write(' ');
+ }
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherRecord.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,196 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import common.Logger;
+
+/**
+ * The base class for all escher records. This class contains
+ * the common header data and is basically a wrapper for the EscherRecordData
+ * object
+ */
+abstract class EscherRecord
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(EscherRecord.class);
+
+ /**
+ * The escher data
+ */
+ private EscherRecordData data;
+ //protected EscherRecordData data;
+
+ /**
+ * The length of the escher header on all records
+ */
+ protected static final int HEADER_LENGTH = 8;
+
+ /**
+ * Constructor
+ *
+ * @param erd the data
+ */
+ protected EscherRecord(EscherRecordData erd)
+ {
+ data = erd;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param type the type
+ */
+ protected EscherRecord(EscherRecordType type)
+ {
+ data = new EscherRecordData(type);
+ }
+
+ /**
+ * Identifies whether this item is a container
+ *
+ * @param cont TRUE if this is a container, FALSE otherwise
+ */
+ protected void setContainer(boolean cont)
+ {
+ data.setContainer(cont);
+ }
+
+ /**
+ * Gets the entire length of the record, including the header
+ *
+ * @return the length of the record, including the header data
+ */
+ public int getLength()
+ {
+ return data.getLength() + HEADER_LENGTH;
+ }
+
+ /**
+ * Accessor for the escher stream
+ *
+ * @return the escher stream
+ */
+ protected final EscherStream getEscherStream()
+ {
+ return data.getEscherStream();
+ }
+
+ /**
+ * The position of this escher record in the stream
+ *
+ * @return the position
+ */
+ protected final int getPos()
+ {
+ return data.getPos();
+ }
+
+ /**
+ * Accessor for the instance
+ *
+ * @return the instance
+ */
+ protected final int getInstance()
+ {
+ return data.getInstance();
+ }
+
+ /**
+ * Sets the instance number when writing out the escher data
+ *
+ * @param i the instance
+ */
+ protected final void setInstance(int i)
+ {
+ data.setInstance(i);
+ }
+
+ /**
+ * Sets the version when writing out the escher data
+ *
+ * @param v the version
+ */
+ protected final void setVersion (int v)
+ {
+ data.setVersion(v);
+ }
+
+ /**
+ * Accessor for the escher type
+ *
+ * @return the type
+ */
+ public EscherRecordType getType()
+ {
+ return data.getType();
+ }
+
+ /**
+ * Abstract method used to retrieve the generated escher data when writing
+ * out image information
+ *
+ * @return the escher data
+ */
+ abstract byte[] getData();
+
+ /**
+ * Prepends the standard header data to the first eight bytes of the array
+ * and returns it
+ *
+ * @param d the data
+ * @return the binary data
+ */
+ final byte[] setHeaderData(byte[] d)
+ {
+ return data.setHeaderData(d);
+ }
+
+ /**
+ * Gets the data that was read in, excluding the header data
+ *
+ * @return the bytes read in, excluding the header data
+ */
+ byte[] getBytes()
+ {
+ return data.getBytes();
+ }
+
+ /**
+ * Accessor for the stream length
+ *
+ * @return the stream length
+ */
+ protected int getStreamLength()
+ {
+ return data.getStreamLength();
+ }
+
+ /**
+ * Used by the EscherDisplay class to retrieve the data
+ *
+ * @return the data
+ */
+ protected EscherRecordData getEscherData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherRecordData.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherRecordData.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherRecordData.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,313 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+
+
+/**
+ * A single record from an Escher stream. Basically this a container for
+ * the header data for each Escher record
+ */
+final class EscherRecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(EscherRecordData.class);
+
+ /**
+ * The byte position of this record in the escher stream
+ */
+ private int pos;
+
+ /**
+ * The instance value
+ */
+ private int instance;
+
+ /**
+ * The version value
+ */
+ private int version;
+
+ /**
+ * The record id
+ */
+ private int recordId;
+
+ /**
+ * The length of the record, excluding the 8 byte header
+ */
+ private int length;
+
+ /**
+ * The length of the stream
+ */
+ private int streamLength;
+
+ /**
+ * Indicates whether this record is a container
+ */
+ private boolean container;
+
+ /**
+ * The type of this record
+ */
+ private EscherRecordType type;
+
+ /**
+ * A handle back to the drawing group, which contains the entire escher
+ * stream byte data
+ */
+ private EscherStream escherStream;
+
+ /**
+ * Constructor
+ *
+ * @param dg the escher stream data
+ * @param p the current position in the stream
+ */
+ public EscherRecordData(EscherStream dg, int p)
+ {
+ escherStream = dg;
+ pos = p;
+ byte[] data = escherStream.getData();
+
+ streamLength = data.length;
+
+ // First two bytes contain instance and version
+ int value = IntegerHelper.getInt(data[pos], data[pos + 1]);
+
+ // Instance value is the first 12 bits
+ instance = (value & 0xfff0) >> 4;
+
+ // Version is the last four bits
+ version = value & 0xf;
+
+ // Bytes 2 and 3 are the record id
+ recordId = IntegerHelper.getInt(data[pos + 2], data[pos + 3]);
+
+ // Length is bytes 4,5,6 and 7
+ length = IntegerHelper.getInt(data[pos + 4], data[pos + 5],
+ data[pos + 6], data[pos + 7]);
+
+ if (version == 0x0f)
+ {
+ container = true;
+ }
+ else
+ {
+ container = false;
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param t the type of the escher record
+ */
+ public EscherRecordData(EscherRecordType t)
+ {
+ type = t;
+ recordId = type.getValue();
+ }
+
+ /**
+ * Determines whether this record is a container
+ *
+ * @return TRUE if this is a container, FALSE otherwise
+ */
+ public boolean isContainer()
+ {
+ return container;
+ }
+
+ /**
+ * Accessor for the length, excluding the 8 byte header
+ *
+ * @return the length excluding the 8 byte header
+ */
+ public int getLength()
+ {
+ return length;
+ }
+
+ /**
+ * Accessor for the record id
+ *
+ * @return the record id
+ */
+ public int getRecordId()
+ {
+ return recordId;
+ }
+
+ /**
+ * Accessor for the drawing group stream
+ *
+ * @return the drawing group stream
+ */
+ EscherStream getDrawingGroup()
+ {
+ return escherStream;
+ }
+
+ /**
+ * Gets the position in the stream
+ *
+ * @return the position in the stream
+ */
+ int getPos()
+ {
+ return pos;
+ }
+
+ /**
+ * Gets the escher type of this record
+ *
+ * @return the escher type
+ */
+ EscherRecordType getType()
+ {
+ if (type == null)
+ {
+ type = EscherRecordType.getType(recordId);
+ }
+
+ return type;
+ }
+
+ /**
+ * Gets the instance value
+ *
+ * @return the instance value
+ */
+ int getInstance()
+ {
+ return instance;
+ }
+
+ /**
+ * Sets whether or not this is a container - called when writing
+ * out an escher stream
+ *
+ * @param c TRUE if this is a container, FALSE otherwise
+ */
+ void setContainer(boolean c)
+ {
+ container = c;
+ }
+
+ /**
+ * Called from the subclass when writing to set the instance value
+ *
+ * @param inst the instance
+ */
+ void setInstance(int inst)
+ {
+ instance = inst;
+ }
+
+ /**
+ * Called when writing to set the length of this record
+ *
+ * @param l the length
+ */
+ void setLength(int l)
+ {
+ length = l;
+ }
+
+ /**
+ * Called when writing to set the version of this record
+ *
+ * @param v the version
+ */
+ void setVersion(int v)
+ {
+ version = v;
+ }
+
+ /**
+ * Adds the 8 byte header data on the value data passed in, returning
+ * the modified data
+ *
+ * @param d the value data
+ * @return the value data with the header information
+ */
+ byte[] setHeaderData(byte[] d)
+ {
+ byte[] data = new byte[d.length + 8];
+ System.arraycopy(d, 0, data, 8, d.length);
+
+ if (container)
+ {
+ version = 0x0f;
+ }
+
+ // First two bytes contain instance and version
+ int value = instance << 4;
+ value |= version;
+ IntegerHelper.getTwoBytes(value, data, 0);
+
+ // Bytes 2 and 3 are the record id
+ IntegerHelper.getTwoBytes(recordId, data, 2);
+
+ // Length is bytes 4,5,6 and 7
+ IntegerHelper.getFourBytes(d.length, data, 4);
+
+ return data;
+ }
+
+ /**
+ * Accessor for the header stream
+ *
+ * @return the escher stream
+ */
+ EscherStream getEscherStream()
+ {
+ return escherStream;
+ }
+
+ /**
+ * Gets the data that was read in, excluding the header data
+ *
+ * @return the value data that was read in
+ */
+ byte[] getBytes()
+ {
+ byte[] d = new byte[length];
+ System.arraycopy(escherStream.getData(), pos + 8, d, 0, length);
+ return d;
+ }
+
+ /**
+ * Accessor for the stream length
+ *
+ * @return the stream length
+ */
+ int getStreamLength()
+ {
+ return streamLength;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherRecordType.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherRecordType.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherRecordType.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,111 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+/**
+ * Enumeration class for Escher record types
+ */
+final class EscherRecordType
+{
+ /**
+ * The code of the item within the escher stream
+ */
+ private int value;
+
+ /**
+ * All escher types
+ */
+ private static EscherRecordType[] types = new EscherRecordType[0];
+
+ /**
+ * Constructor
+ *
+ * @param val the escher record value
+ */
+ private EscherRecordType(int val)
+ {
+ value = val;
+
+ EscherRecordType[] newtypes = new EscherRecordType[types.length + 1];
+ System.arraycopy(types, 0, newtypes, 0, types.length);
+ newtypes[types.length] = this;
+ types = newtypes;
+ }
+
+ /**
+ * Accessor for the escher record value
+ *
+ * @return the escher record value
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Accessor to get the item from a particular value
+ *
+ * @param val the escher record value
+ * @return the type corresponding to val, or UNKNOWN if a match could not
+ * be found
+ */
+ public static EscherRecordType getType(int val)
+ {
+ EscherRecordType type = UNKNOWN;
+
+ for (int i = 0; i < types.length; i++)
+ {
+ if (val == types[i].value)
+ {
+ type = types[i];
+ break;
+ }
+ }
+
+ return type;
+ }
+
+ public static final EscherRecordType UNKNOWN = new EscherRecordType(0x0);
+ public static final EscherRecordType DGG_CONTAINER =
+ new EscherRecordType(0xf000);
+ public static final EscherRecordType BSTORE_CONTAINER =
+ new EscherRecordType(0xf001);
+ public static final EscherRecordType DG_CONTAINER =
+ new EscherRecordType(0xf002);
+ public static final EscherRecordType SPGR_CONTAINER =
+ new EscherRecordType(0xf003);
+ public static final EscherRecordType SP_CONTAINER =
+ new EscherRecordType(0xf004);
+
+ public static final EscherRecordType DGG = new EscherRecordType(0xf006);
+ public static final EscherRecordType BSE = new EscherRecordType(0xf007);
+ public static final EscherRecordType DG = new EscherRecordType(0xf008);
+ public static final EscherRecordType SPGR = new EscherRecordType(0xf009);
+ public static final EscherRecordType SP = new EscherRecordType(0xf00a);
+ public static final EscherRecordType OPT = new EscherRecordType(0xf00b);
+ public static final EscherRecordType CLIENT_ANCHOR =
+ new EscherRecordType(0xf010);
+ public static final EscherRecordType CLIENT_DATA =
+ new EscherRecordType(0xf011);
+ public static final EscherRecordType CLIENT_TEXT_BOX =
+ new EscherRecordType(0xf00d);
+ public static final EscherRecordType SPLIT_MENU_COLORS =
+ new EscherRecordType(0xf11e);
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherStream.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherStream.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/EscherStream.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,33 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+/**
+ * Interface implemented by records which contain escher byte streams
+ */
+interface EscherStream
+{
+ /**
+ * Method to access the escher data
+ *
+ * @return the escher data
+ */
+ byte[] getData();
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/MsoDrawingGroupRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/MsoDrawingGroupRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/MsoDrawingGroupRecord.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,72 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+import jxl.read.biff.Record;
+
+/**
+ * A record which merely holds the MSODRAWINGGROUP data. Used when copying
+ * files which contain images
+ */
+public class MsoDrawingGroupRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ */
+ public MsoDrawingGroupRecord(Record t)
+ {
+ super(t);
+ data = t.getData();
+ }
+
+ /**
+ * Constructor
+ *
+ * @param d the data
+ */
+ MsoDrawingGroupRecord(byte[] d)
+ {
+ super(Type.MSODRAWINGGROUP);
+ data = d;
+ }
+
+ /**
+ * Expose the protected function to the SheetImpl in this package
+ *
+ * @return the raw record data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/MsoDrawingRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/MsoDrawingRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/MsoDrawingRecord.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,116 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import common.Logger;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+import jxl.read.biff.Record;
+
+/**
+ * A record which merely holds the MSODRAWING data. Used when copying files
+ * which contain images
+ */
+public class MsoDrawingRecord extends WritableRecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(MsoDrawingRecord.class);
+
+ /**
+ * Flag to indicate whether this is the first drawing on the sheet
+ * - needed for copying
+ */
+ private boolean first;
+ /**
+ * The raw drawing data which was read in
+ */
+ private byte[] data;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ */
+ public MsoDrawingRecord(Record t)
+ {
+ super(t);
+ data = getRecord().getData();
+ first = false;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param d the drawing data
+ */
+ public MsoDrawingRecord(byte[] d)
+ {
+ super(Type.MSODRAWING);
+ data = d;
+ first = false;
+ }
+
+ /**
+ * Expose the protected function
+ *
+ * @return the raw record data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+
+ /**
+ * Expose the protected function to the SheetImpl in this package
+ *
+ * @return the raw record data
+ */
+ public Record getRecord()
+ {
+ return super.getRecord();
+ }
+
+ /**
+ * Sets the flag to indicate that this is the first drawing on the sheet
+ */
+ public void setFirst()
+ {
+ first = true;
+ }
+
+ /**
+ * Accessor for the first drawing on the sheet. This is used when
+ * copying unmodified sheets to indicate that this drawing contains
+ * the first time Escher gubbins
+ *
+ * @return TRUE if this MSORecord is the first drawing on the sheet
+ */
+ public boolean isFirst()
+ {
+ return first;
+ }
+}
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/NoteRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/NoteRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/NoteRecord.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,167 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+import jxl.read.biff.Record;
+
+/**
+ * A Note (TXO) record which contains the information for comments
+ */
+public class NoteRecord extends WritableRecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(NoteRecord.class);
+
+ /**
+ * The raw drawing data which was read in
+ */
+ private byte[] data;
+
+ /**
+ * The row
+ */
+ private int row;
+
+ /**
+ * The column
+ */
+ private int column;
+
+ /**
+ * The object id
+ */
+ private int objectId;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ */
+ public NoteRecord(Record t)
+ {
+ super(t);
+ data = getRecord().getData();
+ row = IntegerHelper.getInt(data[0], data[1]);
+ column = IntegerHelper.getInt(data[2], data[3]);
+ objectId = IntegerHelper.getInt(data[6], data[7]);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param d the drawing data
+ */
+ public NoteRecord(byte[] d)
+ {
+ super(Type.NOTE);
+ data = d;
+ }
+
+ /**
+ * Constructor used when writing a Note
+ *
+ * @param c the column
+ * @param r the row
+ * @param id the object id
+ */
+ public NoteRecord(int c, int r, int id)
+ {
+ super(Type.NOTE);
+ row = r;
+ column = c;
+ objectId = id;
+ }
+
+ /**
+ * Expose the protected function to the SheetImpl in this package
+ *
+ * @return the raw record data
+ */
+ public byte[] getData()
+ {
+ if (data != null)
+ {
+ return data;
+ }
+
+ String author = "";
+ data = new byte[8 + author.length() + 4];
+
+ // the row
+ IntegerHelper.getTwoBytes(row, data, 0);
+
+ // the column
+ IntegerHelper.getTwoBytes(column, data, 2);
+
+ // the object id
+ IntegerHelper.getTwoBytes(objectId, data, 6);
+
+ // the length of the string
+ IntegerHelper.getTwoBytes(author.length(), data, 8);
+
+ // the string
+ // StringHelper.getBytes(author, data, 11);
+
+ // data[data.length-1]=(byte)0x24;
+
+ return data;
+ }
+
+ /**
+ * Accessor for the row
+ *
+ * @return the row
+ */
+ int getRow()
+ {
+ return row;
+ }
+
+ /**
+ * Accessor for the column
+ *
+ * @return the column
+ */
+ int getColumn()
+ {
+ return column;
+ }
+
+ /**
+ * Accessor for the object id
+ *
+ * @return the object id
+ */
+ public int getObjectId()
+ {
+ return objectId;
+ }
+}
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/ObjRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/ObjRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/ObjRecord.java 17 Aug 2012 14:51:21 -0000 1.1
@@ -0,0 +1,411 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+import jxl.read.biff.Record;
+
+/**
+ * A record which merely holds the OBJ data. Used when copying files which
+ * contain images
+ */
+public class ObjRecord extends WritableRecordData
+{
+ /**
+ * The logger
+ */
+ private static final Logger logger = Logger.getLogger(ObjRecord.class);
+
+ /**
+ * The object type
+ */
+ private ObjType type;
+
+ /**
+ * Indicates whether this record was read in
+ */
+ private boolean read;
+
+ /**
+ * The object id
+ */
+ private int objectId;
+
+ /**
+ * Object type enumeration
+ */
+ private static final class ObjType
+ {
+ public int value;
+ public String desc;
+
+ private static ObjType[] types = new ObjType[0];
+
+ ObjType(int v, String d)
+ {
+ value = v;
+ desc = d;
+
+ ObjType[] oldtypes = types;
+ types = new ObjType[types.length + 1];
+ System.arraycopy(oldtypes, 0, types, 0, oldtypes.length);
+ types[oldtypes.length] = this;
+ }
+
+ public String toString()
+ {
+ return desc;
+ }
+
+ public static ObjType getType(int val)
+ {
+ ObjType retval = UNKNOWN;
+ for (int i = 0; i < types.length && retval == UNKNOWN; i++)
+ {
+ if (types[i].value == val)
+ {
+ retval = types[i];
+ }
+ }
+ return retval;
+ }
+ }
+
+ // The object types
+ public static final ObjType TBD2 = new ObjType(0x01, "TBD2");
+ public static final ObjType TBD = new ObjType(0x02, "TBD");
+ public static final ObjType CHART = new ObjType(0x05, "Chart");
+ public static final ObjType TEXT = new ObjType(0x06, "Text");
+ public static final ObjType BUTTON = new ObjType(0x07, "Button");
+ public static final ObjType PICTURE = new ObjType(0x08, "Picture");
+ public static final ObjType CHECKBOX = new ObjType(0x0e, "Checkbox");
+ public static final ObjType OPTION = new ObjType(0x0c, "Option");
+ public static final ObjType EDITBOX = new ObjType(0x0d, "Edit Box");
+ public static final ObjType LABEL = new ObjType(0x0e, "Label");
+ public static final ObjType DIALOGUEBOX = new ObjType(0x0f, "Dialogue Box");
+ public static final ObjType LISTBOX = new ObjType(0x12, "List Box");
+ public static final ObjType GROUPBOX = new ObjType(0x13, "Group Box");
+ public static final ObjType COMBOBOX = new ObjType(0x14, "Combo Box");
+ public static final ObjType MSOFFICEDRAWING = new ObjType
+ (0x1e, "MS Office Drawing");
+ public static final ObjType FORMCONTROL =
+ new ObjType (0x14, "Form Combo Box");
+ public static final ObjType EXCELNOTE =
+ new ObjType (0x19, "Excel Note");
+
+ public static final ObjType UNKNOWN = new ObjType(0xff, "Unknown");
+
+ // Field sub records
+ private static final int COMMON_DATA_LENGTH = 22;
+ private static final int CLIPBOARD_FORMAT_LENGTH = 6;
+ private static final int PICTURE_OPTION_LENGTH = 6;
+ private static final int NOTE_STRUCTURE_LENGTH = 26;
+ private static final int COMBOBOX_STRUCTURE_LENGTH = 44;
+ private static final int END_LENGTH = 4;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ */
+ public ObjRecord(Record t)
+ {
+ super(t);
+ byte[] data = t.getData();
+ int objtype = IntegerHelper.getInt(data[4], data[5]);
+ read = true;
+ type = ObjType.getType(objtype);
+
+ if (type == UNKNOWN)
+ {
+ logger.warn("unknown object type code " + objtype);
+ }
+
+ objectId = IntegerHelper.getInt(data[6], data[7]);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param objId the object id
+ * @param t the object type
+ */
+ ObjRecord(int objId, ObjType t)
+ {
+ super(Type.OBJ);
+ objectId = objId;
+ type = t;
+ }
+
+ /**
+ * Expose the protected function to the SheetImpl in this package
+ *
+ * @return the raw record data
+ */
+ public byte[] getData()
+ {
+ if (read)
+ {
+ return getRecord().getData();
+ }
+
+ if (type == PICTURE || type == CHART)
+ {
+ return getPictureData();
+ }
+ else if (type == EXCELNOTE)
+ {
+ return getNoteData();
+ }
+ else if (type == COMBOBOX)
+ {
+ return getComboBoxData();
+ }
+ else
+ {
+ Assert.verify(false);
+ }
+ return null;
+ }
+
+ /**
+ * Gets the ObjRecord subrecords for a picture
+ *
+ * @return the binary data for the picture
+ */
+ private byte[] getPictureData()
+ {
+ int dataLength = COMMON_DATA_LENGTH +
+ CLIPBOARD_FORMAT_LENGTH +
+ PICTURE_OPTION_LENGTH +
+ END_LENGTH;
+ int pos = 0;
+ byte[] data = new byte[dataLength];
+
+ // The common data
+ // record id
+ IntegerHelper.getTwoBytes(0x15, data, pos);
+
+ // record length
+ IntegerHelper.getTwoBytes(COMMON_DATA_LENGTH - 4, data, pos + 2);
+
+ // object type
+ IntegerHelper.getTwoBytes(type.value, data, pos + 4);
+
+ // object id
+ IntegerHelper.getTwoBytes(objectId, data, pos + 6);
+
+ // the options
+ IntegerHelper.getTwoBytes(0x6011, data, pos + 8);
+ pos += COMMON_DATA_LENGTH;
+
+ // The clipboard format
+ // record id
+ IntegerHelper.getTwoBytes(0x7, data, pos);
+
+ // record length
+ IntegerHelper.getTwoBytes(CLIPBOARD_FORMAT_LENGTH - 4, data, pos + 2);
+
+ // the data
+ IntegerHelper.getTwoBytes(0xffff, data, pos + 4);
+ pos += CLIPBOARD_FORMAT_LENGTH;
+
+ // Picture option flags
+ // record id
+ IntegerHelper.getTwoBytes(0x8, data, pos);
+
+ // record length
+ IntegerHelper.getTwoBytes(PICTURE_OPTION_LENGTH - 4, data, pos + 2);
+
+ // the data
+ IntegerHelper.getTwoBytes(0x1, data, pos + 4);
+ pos += CLIPBOARD_FORMAT_LENGTH;
+
+ // End record id
+ IntegerHelper.getTwoBytes(0x0, data, pos);
+
+ // record length
+ IntegerHelper.getTwoBytes(END_LENGTH - 4, data, pos + 2);
+
+ // the data
+ pos += END_LENGTH;
+
+ return data;
+ }
+
+ /**
+ * Gets the ObjRecord subrecords for a note
+ *
+ * @return the note data
+ */
+ private byte[] getNoteData()
+ {
+ int dataLength = COMMON_DATA_LENGTH +
+ NOTE_STRUCTURE_LENGTH +
+ END_LENGTH;
+ int pos = 0;
+ byte[] data = new byte[dataLength];
+
+ // The common data
+ // record id
+ IntegerHelper.getTwoBytes(0x15, data, pos);
+
+ // record length
+ IntegerHelper.getTwoBytes(COMMON_DATA_LENGTH - 4, data, pos + 2);
+
+ // object type
+ IntegerHelper.getTwoBytes(type.value, data, pos + 4);
+
+ // object id
+ IntegerHelper.getTwoBytes(objectId, data, pos + 6);
+
+ // the options
+ IntegerHelper.getTwoBytes(0x4011, data, pos + 8);
+ pos += COMMON_DATA_LENGTH;
+
+ // The note structure
+ // record id
+ IntegerHelper.getTwoBytes(0xd, data, pos);
+
+ // record length
+ IntegerHelper.getTwoBytes(NOTE_STRUCTURE_LENGTH - 4, data, pos + 2);
+
+ // the data
+ pos += NOTE_STRUCTURE_LENGTH;
+
+ // End
+ // record id
+ IntegerHelper.getTwoBytes(0x0, data, pos);
+
+ // record length
+ IntegerHelper.getTwoBytes(END_LENGTH - 4, data, pos + 2);
+
+ // the data
+ pos += END_LENGTH;
+
+ return data;
+ }
+
+ /**
+ * Gets the ObjRecord subrecords for a combo box
+ *
+ * @return returns the binary data for a combo box
+ */
+ private byte[] getComboBoxData()
+ {
+ int dataLength = COMMON_DATA_LENGTH +
+ COMBOBOX_STRUCTURE_LENGTH +
+ END_LENGTH;
+ int pos = 0;
+ byte[] data = new byte[dataLength];
+
+ // The common data
+ // record id
+ IntegerHelper.getTwoBytes(0x15, data, pos);
+
+ // record length
+ IntegerHelper.getTwoBytes(COMMON_DATA_LENGTH - 4, data, pos + 2);
+
+ // object type
+ IntegerHelper.getTwoBytes(type.value, data, pos + 4);
+
+ // object id
+ IntegerHelper.getTwoBytes(objectId, data, pos + 6);
+
+ // the options
+ IntegerHelper.getTwoBytes(0x0, data, pos + 8);
+ pos += COMMON_DATA_LENGTH;
+
+ // The combo box structure
+ // record id
+ IntegerHelper.getTwoBytes(0xc, data, pos);
+
+ // record length
+ IntegerHelper.getTwoBytes(0x14, data, pos + 2);
+
+ // the data
+ data[pos + 14] = 0x01;
+ data[pos + 16] = 0x04;
+ data[pos + 20] = 0x10;
+ data[pos + 24] = 0x13;
+ data[pos + 26] = (byte) 0xee;
+ data[pos + 27] = 0x1f;
+ data[pos + 30] = 0x04;
+ data[pos + 34] = 0x01;
+ data[pos + 35] = 0x06;
+ data[pos + 38] = 0x02;
+ data[pos + 40] = 0x08;
+ data[pos + 42] = 0x40;
+
+ pos += COMBOBOX_STRUCTURE_LENGTH;
+
+ // End
+ // record id
+ IntegerHelper.getTwoBytes(0x0, data, pos);
+
+ // record length
+ IntegerHelper.getTwoBytes(END_LENGTH - 4, data, pos + 2);
+
+ // the data
+ pos += END_LENGTH;
+
+ return data;
+ }
+
+
+ /**
+ * Expose the protected function to the SheetImpl in this package
+ *
+ * @return the raw record data
+ */
+ public Record getRecord()
+ {
+ return super.getRecord();
+ }
+
+ /**
+ * Accessor for the object type
+ *
+ * @return the object type
+ */
+ public ObjType getType()
+ {
+ return type;
+ }
+
+ /**
+ * Accessor for the object id
+ *
+ * @return accessor for the object id
+ */
+ public int getObjectId()
+ {
+ return objectId;
+ }
+}
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/Opt.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/Opt.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/Opt.java 17 Aug 2012 14:51:21 -0000 1.1
@@ -0,0 +1,259 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.StringHelper;
+
+/**
+ * An options record in the escher stream
+ */
+class Opt extends EscherAtom
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(Opt.class);
+
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * The number of properties
+ */
+ private int numProperties;
+
+ /**
+ * The list of properties
+ */
+ private ArrayList properties;
+
+ /**
+ * Properties enumeration inner class
+ */
+ final static class Property
+ {
+ int id;
+ boolean blipId;
+ boolean complex;
+ int value;
+ String stringValue;
+
+ /**
+ * Constructor
+ *
+ * @param i the property id
+ * @param bl the blip id
+ * @param co complex flag
+ * @param v the value
+ */
+ public Property(int i, boolean bl, boolean co, int v)
+ {
+ id = i;
+ blipId = bl;
+ complex = co;
+ value = v;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param i the property id
+ * @param bl the blip id
+ * @param co complex flag
+ * @param v the value
+ * @param s the property string
+ */
+ public Property(int i, boolean bl, boolean co, int v, String s)
+ {
+ id = i;
+ blipId = bl;
+ complex = co;
+ value = v;
+ stringValue = s;
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param erd the escher record data
+ */
+ public Opt(EscherRecordData erd)
+ {
+ super(erd);
+ numProperties = getInstance();
+ readProperties();
+ }
+
+ /**
+ * Reads the properties
+ */
+ private void readProperties()
+ {
+ properties = new ArrayList();
+ int pos = 0;
+ byte[] bytes = getBytes();
+
+ for (int i = 0; i < numProperties; i++)
+ {
+ int val = IntegerHelper.getInt(bytes[pos], bytes[pos + 1]);
+ int id = val & 0x3fff;
+ int value = IntegerHelper.getInt(bytes[pos + 2], bytes[pos + 3],
+ bytes[pos + 4], bytes[pos + 5]);
+ Property p = new Property(id,
+ (val & 0x4000) != 0,
+ (val & 0x8000) != 0,
+ value);
+ pos += 6;
+ properties.add(p);
+ }
+
+ for (Iterator i = properties.iterator(); i.hasNext();)
+ {
+ Property p = (Property) i.next();
+ if (p.complex)
+ {
+ p.stringValue = StringHelper.getUnicodeString(bytes, p.value / 2,
+ pos);
+ pos += p.value;
+ }
+ }
+ }
+
+ /**
+ * Constructor
+ */
+ public Opt()
+ {
+ super(EscherRecordType.OPT);
+ properties = new ArrayList();
+ setVersion(3);
+ }
+
+ /**
+ * Accessor for the binary data
+ *
+ * @return the binary data
+ */
+ byte[] getData()
+ {
+ numProperties = properties.size();
+ setInstance(numProperties);
+
+ data = new byte[numProperties * 6];
+ int pos = 0;
+
+ // Add in the root data
+ for (Iterator i = properties.iterator(); i.hasNext();)
+ {
+ Property p = (Property) i.next();
+ int val = p.id & 0x3fff;
+
+ if (p.blipId)
+ {
+ val |= 0x4000;
+ }
+
+ if (p.complex)
+ {
+ val |= 0x8000;
+ }
+
+ IntegerHelper.getTwoBytes(val, data, pos);
+ IntegerHelper.getFourBytes(p.value, data, pos + 2);
+ pos += 6;
+ }
+
+ // Add in any complex data
+ for (Iterator i = properties.iterator(); i.hasNext();)
+ {
+ Property p = (Property) i.next();
+
+ if (p.complex && p.stringValue != null)
+ {
+ byte[] newData =
+ new byte[data.length + p.stringValue.length() * 2];
+ System.arraycopy(data, 0, newData, 0, data.length);
+ StringHelper.getUnicodeBytes(p.stringValue, newData, data.length);
+ data = newData;
+ }
+ }
+
+ return setHeaderData(data);
+ }
+
+ /**
+ * Adds a property into the options
+ *
+ * @param id the property id
+ * @param blip the blip id
+ * @param complex whether it's a complex property
+ * @param val the value
+ */
+ void addProperty(int id, boolean blip, boolean complex, int val)
+ {
+ Property p = new Property(id, blip, complex, val);
+ properties.add(p);
+ }
+
+ /**
+ * Adds a property into the options
+ *
+ * @param id the property id
+ * @param blip the blip id
+ * @param complex whether it's a complex property
+ * @param val the value
+ * @param s the value string
+ */
+ void addProperty(int id, boolean blip, boolean complex, int val, String s)
+ {
+ Property p = new Property(id, blip, complex, val, s);
+ properties.add(p);
+ }
+
+ /**
+ * Accessor for the property
+ *
+ * @param id the property id
+ * @return the property
+ */
+ Property getProperty(int id)
+ {
+ boolean found = false;
+ Property p = null;
+ for (Iterator i = properties.iterator(); i.hasNext() && !found;)
+ {
+ p = (Property) i.next();
+ if (p.id == id)
+ {
+ found = true;
+ }
+ }
+ return found ? p : null;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/Origin.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/Origin.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/Origin.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,37 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+/**
+ * Enumeration type for the origin of a drawing object
+ */
+public final class Origin
+{
+ /**
+ * Constructor
+ */
+ private Origin()
+ {
+ }
+
+ public static final Origin READ = new Origin();
+ public static final Origin WRITE = new Origin();
+ public static final Origin READ_WRITE = new Origin();
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/PNGReader.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/PNGReader.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/PNGReader.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,157 @@
+/*********************************************************************
+*
+* Copyright (C) 2006 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Arrays;
+
+public class PNGReader
+{
+ private byte[] pngData;
+
+ private Chunk ihdr;
+ private Chunk phys;
+
+ private int pixelWidth;
+ private int pixelHeight;
+ private int verticalResolution;
+ private int horizontalResolution;
+ private int resolutionUnit;
+
+ private static byte[] PNG_MAGIC_NUMBER = new byte[]
+ {(byte) 0x89, (byte) 0x50, (byte) 0x4e, (byte) 0x47,
+ (byte) 0x0d, (byte) 0x0a, (byte) 0x1a, (byte) 0x0a};
+
+ public PNGReader(byte[] data)
+ {
+ pngData = data;
+ }
+
+ void read()
+ {
+ // Verify the magic data
+ byte[] header = new byte[PNG_MAGIC_NUMBER.length];
+ System.arraycopy(pngData, 0, header, 0, header.length);
+ boolean pngFile = Arrays.equals(PNG_MAGIC_NUMBER, header);
+ if (!pngFile)
+ {
+ return;
+ }
+
+ int pos = 8;
+ while (pos < pngData.length)
+ {
+ int length = getInt(pngData[pos],
+ pngData[pos+1],
+ pngData[pos+2],
+ pngData[pos+3]);
+ ChunkType chunkType = ChunkType.getChunkType(pngData[pos+4],
+ pngData[pos+5],
+ pngData[pos+6],
+ pngData[pos+7]);
+
+ if (chunkType == ChunkType.IHDR)
+ {
+ ihdr = new Chunk(pos + 8, length, chunkType, pngData);
+ }
+ else if (chunkType == ChunkType.PHYS)
+ {
+ phys = new Chunk(pos + 8, length, chunkType, pngData);
+ }
+
+ pos += length + 12;
+ }
+
+ // Get the width and height from the ihdr
+ byte[] ihdrData = ihdr.getData();
+ pixelWidth = getInt(ihdrData[0], ihdrData[1], ihdrData[2], ihdrData[3]);
+ pixelHeight = getInt(ihdrData[4], ihdrData[5], ihdrData[6], ihdrData[7]);
+
+ if (phys != null)
+ {
+ byte[] physData = phys.getData();
+ resolutionUnit = physData[8];
+ horizontalResolution = getInt(physData[0], physData[1],
+ physData[2], physData[3]);
+ verticalResolution = getInt(physData[4], physData[5],
+ physData[6], physData[7]);
+ }
+ }
+
+ // Gets the big-Endian integer
+ private int getInt(byte d1, byte d2, byte d3, byte d4)
+ {
+ int i1 = d1 & 0xff;
+ int i2 = d2 & 0xff;
+ int i3 = d3 & 0xff;
+ int i4 = d4 & 0xff;
+
+ int val = i1 << 24 |
+ i2 << 16 |
+ i3 << 8 |
+ i4;
+
+ return val;
+ }
+
+ public int getHeight()
+ {
+ return pixelHeight;
+ }
+
+ public int getWidth()
+ {
+ return pixelWidth;
+ }
+
+ public int getHorizontalResolution()
+ {
+ // only return if the resolution unit is in metres
+ return resolutionUnit == 1 ? horizontalResolution : 0;
+ }
+
+ public int getVerticalResolution()
+ {
+ // only return if the resolution unit is in metres
+ return resolutionUnit == 1 ? verticalResolution : 0;
+ }
+
+ public static void main(String args[])
+ {
+ try
+ {
+ File f = new File(args[0]);
+ int size = (int) f.length();
+
+ byte[] data = new byte[size];
+
+ FileInputStream fis = new FileInputStream(f);
+ fis.read(data);
+ fis.close();
+ PNGReader reader = new PNGReader(data);
+ reader.read();
+ }
+ catch (Throwable t)
+ {
+ t.printStackTrace();
+ }
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/ShapeType.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/ShapeType.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/ShapeType.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,88 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+/**
+ * Enumerations for the shape type
+ */
+final class ShapeType
+{
+ /**
+ * The value
+ */
+ private int value;
+
+ /**
+ * The list of shape types
+ */
+ private static ShapeType[] types = new ShapeType[0];
+
+ /**
+ * Constructor
+ *
+ * @param v the value
+ */
+ ShapeType(int v)
+ {
+ value = v;
+
+ ShapeType[] old = types;
+ types = new ShapeType[types.length + 1];
+ System.arraycopy(old, 0, types, 0, old.length);
+ types[old.length] = this;
+ }
+
+ /**
+ * Gets the shape type given the value
+ *
+ * @param v the value
+ * @return the shape type for the value
+ */
+ static ShapeType getType(int v)
+ {
+ ShapeType st = UNKNOWN;
+ boolean found = false;
+ for (int i = 0; i < types.length && !found; i++)
+ {
+ if (types[i].value == v)
+ {
+ found = true;
+ st = types[i];
+ }
+ }
+ return st;
+ }
+
+ /**
+ * Accessor for the value
+ *
+ * @return the value
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ public static final ShapeType MIN = new ShapeType(0);
+ public static final ShapeType PICTURE_FRAME = new ShapeType(75);
+ public static final ShapeType HOST_CONTROL = new ShapeType(201);
+ public static final ShapeType TEXT_BOX = new ShapeType(202);
+ public static final ShapeType UNKNOWN = new ShapeType(-1);
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/SheetDrawingWriter.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/SheetDrawingWriter.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/SheetDrawingWriter.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,488 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.IntegerHelper;
+import jxl.write.biff.File;
+
+/**
+ * Handles the writing out of the different charts and images on a sheet.
+ * Called by the SheetWriter object
+ */
+public class SheetDrawingWriter
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(SheetDrawingWriter.class);
+
+ /**
+ * The drawings on the sheet
+ */
+ private ArrayList drawings;
+
+ /**
+ * Flag indicating whether the drawings on the sheet were modified
+ */
+ private boolean drawingsModified;
+
+ /**
+ * The charts on the sheet
+ */
+ private Chart[] charts;
+
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings workbookSettings;
+
+ /**
+ * Constructor
+ *
+ * @param ws the workbook settings
+ */
+ public SheetDrawingWriter(WorkbookSettings ws)
+ {
+ charts = new Chart[0];
+ }
+
+ /**
+ * The drawings on the sheet
+ *
+ * @param dr the list of drawings
+ * @param mod flag indicating whether the drawings have been tampered with
+ */
+ public void setDrawings(ArrayList dr, boolean mod)
+ {
+ drawings = dr;
+ drawingsModified = mod;
+ }
+
+ /**
+ * Writes out the MsoDrawing records and Obj records for each image
+ * and chart on the sheet
+ *
+ * @param outputFile the output file
+ * @exception IOException
+ */
+ public void write(File outputFile) throws IOException
+ {
+ // If there are no drawings or charts on this sheet then exit
+ if (drawings.size() == 0 && charts.length == 0)
+ {
+ return;
+ }
+
+ // See if any drawing has been modified
+ boolean modified = drawingsModified;
+ int numImages = drawings.size();
+
+ for (Iterator i = drawings.iterator(); i.hasNext() && !modified;)
+ {
+ DrawingGroupObject d = (DrawingGroupObject) i.next();
+ if (d.getOrigin() != Origin.READ)
+ {
+ modified = true;
+ }
+ }
+
+ // If the drawing order has been muddled at all, then we'll need
+ // to regenerate the Escher drawing data
+ if (numImages > 0 && !modified)
+ {
+ DrawingGroupObject d2 = (DrawingGroupObject) drawings.get(0);
+ if (!d2.isFirst())
+ {
+ modified = true;
+ }
+ }
+
+ // Check to see if this sheet consists of just a single chart. If so
+ // there is no MsoDrawingRecord, so write out the data and exit
+ if (numImages == 0 &&
+ charts.length == 1 &&
+ charts[0].getMsoDrawingRecord() == null)
+ {
+ modified = false; // this sheet has not been modified
+ }
+
+ // If no drawing has been modified, then simply write them straight out
+ // again and exit
+ if (!modified)
+ {
+ writeUnmodified(outputFile);
+ return;
+ }
+
+ Object[] spContainerData = new Object[numImages + charts.length];
+ int length = 0;
+ EscherContainer firstSpContainer = null;
+
+ // Get all the spContainer byte data from the drawings
+ // and store in an array
+ for (int i = 0; i < numImages; i++)
+ {
+ DrawingGroupObject drawing = (DrawingGroupObject) drawings.get(i);
+
+ EscherContainer spc = drawing.getSpContainer();
+
+ if (spc != null)
+ {
+ byte[] data = spc.getData();
+ spContainerData[i] = data;
+
+ if (i == 0)
+ {
+ firstSpContainer = spc;
+ }
+ else
+ {
+ length += data.length;
+ }
+ }
+ }
+
+ // Get all the spContainer bytes from the charts and add to the array
+ for (int i = 0; i < charts.length; i++)
+ {
+ EscherContainer spContainer = charts[i].getSpContainer();
+ byte[] data = spContainer.getBytes(); //use getBytes instead of getData
+ data = spContainer.setHeaderData(data);
+ spContainerData[i + numImages] = data;
+
+ if (i == 0 && numImages == 0)
+ {
+ firstSpContainer = spContainer;
+ }
+ else
+ {
+ length += data.length;
+ }
+ }
+
+ // Put the generalised stuff around the first item
+ DgContainer dgContainer = new DgContainer();
+ Dg dg = new Dg(numImages + charts.length);
+ dgContainer.add(dg);
+
+ SpgrContainer spgrContainer = new SpgrContainer();
+
+ SpContainer spContainer = new SpContainer();
+ Spgr spgr = new Spgr();
+ spContainer.add(spgr);
+ Sp sp = new Sp(ShapeType.MIN, 1024, 5);
+ spContainer.add(sp);
+ spgrContainer.add(spContainer);
+
+ spgrContainer.add(firstSpContainer);
+
+ dgContainer.add(spgrContainer);
+
+ byte[] firstMsoData = dgContainer.getData();
+
+ // Adjust the length of the DgContainer
+ int len = IntegerHelper.getInt(firstMsoData[4],
+ firstMsoData[5],
+ firstMsoData[6],
+ firstMsoData[7]);
+ IntegerHelper.getFourBytes(len + length, firstMsoData, 4);
+
+ // Adjust the length of the SpgrContainer
+ len = IntegerHelper.getInt(firstMsoData[28],
+ firstMsoData[29],
+ firstMsoData[30],
+ firstMsoData[31]);
+ IntegerHelper.getFourBytes(len + length, firstMsoData, 28);
+
+ // Now write out each MsoDrawing record
+
+ // First MsoRecord
+ // test hack for form objects, to remove the ClientTextBox record
+ // from the end of the SpContainer
+ if (numImages > 0 &&
+ ((DrawingGroupObject) drawings.get(0)).isFormObject())
+ {
+ byte[] msodata2 = new byte[firstMsoData.length - 8];
+ System.arraycopy(firstMsoData, 0, msodata2, 0, msodata2.length);
+ firstMsoData = msodata2;
+ }
+
+ MsoDrawingRecord msoDrawingRecord = new MsoDrawingRecord(firstMsoData);
+ outputFile.write(msoDrawingRecord);
+
+ if (numImages > 0)
+ {
+ DrawingGroupObject firstDrawing = (DrawingGroupObject) drawings.get(0);
+ firstDrawing.writeAdditionalRecords(outputFile);
+ }
+ else
+ {
+ // first image is a chart
+ Chart chart = charts[0];
+ ObjRecord objRecord = chart.getObjRecord();
+ outputFile.write(objRecord);
+ outputFile.write(chart);
+ }
+
+ // Now do all the others
+ for (int i = 1; i < spContainerData.length; i++)
+ {
+ byte[] bytes = (byte[]) spContainerData[i];
+
+ // test hack for form objects, to remove the ClientTextBox record
+ // from the end of the SpContainer
+ if (i < numImages &&
+ ((DrawingGroupObject) drawings.get(i)).isFormObject())
+ {
+ byte[] bytes2 = new byte[bytes.length - 8];
+ System.arraycopy(bytes, 0, bytes2, 0, bytes2.length);
+ bytes = bytes2;
+ }
+
+ msoDrawingRecord = new MsoDrawingRecord(bytes);
+ outputFile.write(msoDrawingRecord);
+
+ if (i < numImages)
+ {
+ // Write anything else the object needs
+ DrawingGroupObject d = (DrawingGroupObject) drawings.get(i);
+ d.writeAdditionalRecords(outputFile);
+ }
+ else
+ {
+ Chart chart = charts[i - numImages];
+ ObjRecord objRecord = chart.getObjRecord();
+ outputFile.write(objRecord);
+ outputFile.write(chart);
+ }
+ }
+
+ // Write any tail records that need to be written
+ for (Iterator i = drawings.iterator(); i.hasNext();)
+ {
+ DrawingGroupObject dgo2 = (DrawingGroupObject) i.next();
+ dgo2.writeTailRecords(outputFile);
+ }
+ }
+
+ /**
+ * Writes out the drawings and the charts if nothing has been modified
+ *
+ * @param outputFile the output file
+ * @exception IOException
+ */
+ private void writeUnmodified(File outputFile) throws IOException
+ {
+ if (charts.length == 0 && drawings.size() == 0)
+ {
+ // No drawings or charts
+ return;
+ }
+ else if (charts.length == 0 && drawings.size() != 0)
+ {
+ // If there are no charts, then write out the drawings and return
+ for (Iterator i = drawings.iterator(); i.hasNext();)
+ {
+ DrawingGroupObject d = (DrawingGroupObject) i.next();
+ outputFile.write(d.getMsoDrawingRecord());
+ d.writeAdditionalRecords(outputFile);
+ }
+
+ for (Iterator i = drawings.iterator(); i.hasNext();)
+ {
+ DrawingGroupObject d = (DrawingGroupObject) i.next();
+ d.writeTailRecords(outputFile);
+ }
+ return;
+ }
+ else if (drawings.size() == 0 && charts.length != 0)
+ {
+ // If there are no drawings, then write out the charts and return
+ Chart curChart = null;
+ for (int i = 0; i < charts.length; i++)
+ {
+ curChart = charts[i];
+ if (curChart.getMsoDrawingRecord() != null)
+ {
+ outputFile.write(curChart.getMsoDrawingRecord());
+ }
+
+ if (curChart.getObjRecord() != null)
+ {
+ outputFile.write(curChart.getObjRecord());
+ }
+
+ outputFile.write(curChart);
+ }
+
+ return;
+ }
+
+ // There are both charts and drawings - the output
+ // drawing group records will need
+ // to be re-jigged in order to write the drawings out first, then the
+ // charts
+ int numDrawings = drawings.size();
+ int length = 0;
+ EscherContainer[] spContainers =
+ new EscherContainer[numDrawings + charts.length];
+ boolean[] isFormObject = new boolean[numDrawings + charts.length];
+
+ for (int i = 0; i < numDrawings; i++)
+ {
+ DrawingGroupObject d = (DrawingGroupObject) drawings.get(i);
+ spContainers[i] = d.getSpContainer();
+
+ if (i > 0)
+ {
+ length += spContainers[i].getLength();
+ }
+
+ if (d.isFormObject())
+ {
+ isFormObject[i] = true;
+ }
+ }
+
+ for (int i = 0; i < charts.length; i++)
+ {
+ spContainers[i + numDrawings] = charts[i].getSpContainer();
+ length += spContainers[i + numDrawings].getLength();
+ }
+
+ // Put the generalised stuff around the first item
+ DgContainer dgContainer = new DgContainer();
+ Dg dg = new Dg(numDrawings + charts.length);
+ dgContainer.add(dg);
+
+ SpgrContainer spgrContainer = new SpgrContainer();
+
+ SpContainer spContainer = new SpContainer();
+ Spgr spgr = new Spgr();
+ spContainer.add(spgr);
+ Sp sp = new Sp(ShapeType.MIN, 1024, 5);
+ spContainer.add(sp);
+ spgrContainer.add(spContainer);
+
+ spgrContainer.add(spContainers[0]);
+
+ dgContainer.add(spgrContainer);
+
+ byte[] firstMsoData = dgContainer.getData();
+
+ // Adjust the length of the DgContainer
+ int len = IntegerHelper.getInt(firstMsoData[4],
+ firstMsoData[5],
+ firstMsoData[6],
+ firstMsoData[7]);
+ IntegerHelper.getFourBytes(len + length, firstMsoData, 4);
+
+ // Adjust the length of the SpgrContainer
+ len = IntegerHelper.getInt(firstMsoData[28],
+ firstMsoData[29],
+ firstMsoData[30],
+ firstMsoData[31]);
+ IntegerHelper.getFourBytes(len + length, firstMsoData, 28);
+
+ // Now write out each MsoDrawing record and object record
+
+ // Hack to remove the last eight bytes (text box escher record)
+ // from the container
+ if (isFormObject[0] == true)
+ {
+ byte[] cbytes = new byte[firstMsoData.length - 8];
+ System.arraycopy(firstMsoData, 0, cbytes, 0, cbytes.length);
+ firstMsoData = cbytes;
+ }
+
+ // First MsoRecord
+ MsoDrawingRecord msoDrawingRecord = new MsoDrawingRecord(firstMsoData);
+ outputFile.write(msoDrawingRecord);
+
+ DrawingGroupObject dgo = (DrawingGroupObject) drawings.get(0);
+ dgo.writeAdditionalRecords(outputFile);
+
+ // Now do all the others
+ for (int i = 1; i < spContainers.length; i++)
+ {
+ byte[] bytes = spContainers[i].getBytes();
+ byte[] bytes2 = spContainers[i].setHeaderData(bytes);
+
+ // Hack to remove the last eight bytes (text box escher record)
+ // from the container
+ if (isFormObject[i] == true)
+ {
+ byte[] cbytes = new byte[bytes2.length - 8];
+ System.arraycopy(bytes2, 0, cbytes, 0, cbytes.length);
+ bytes2 = cbytes;
+ }
+
+ msoDrawingRecord = new MsoDrawingRecord(bytes2);
+ outputFile.write(msoDrawingRecord);
+
+ if (i < numDrawings)
+ {
+ dgo = (DrawingGroupObject) drawings.get(i);
+ dgo.writeAdditionalRecords(outputFile);
+ }
+ else
+ {
+ Chart chart = charts[i - numDrawings];
+ ObjRecord objRecord = chart.getObjRecord();
+ outputFile.write(objRecord);
+ outputFile.write(chart);
+ }
+ }
+
+ // Write any tail records that need to be written
+ for (Iterator i = drawings.iterator(); i.hasNext();)
+ {
+ DrawingGroupObject dgo2 = (DrawingGroupObject) i.next();
+ dgo2.writeTailRecords(outputFile);
+ }
+ }
+
+ /**
+ * Sets the charts on the sheet
+ *
+ * @param ch the charts
+ */
+ public void setCharts(Chart[] ch)
+ {
+ charts = ch;
+ }
+
+ /**
+ * Accessor for the charts on the sheet
+ *
+ * @return the charts
+ */
+ public Chart[] getCharts()
+ {
+ return charts;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/Sp.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/Sp.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/Sp.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,120 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+
+/**
+ * The Sp escher atom
+ */
+class Sp extends EscherAtom
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(Sp.class);
+
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * The shape type
+ */
+ private int shapeType;
+
+ /**
+ * The shape id
+ */
+ private int shapeId;
+
+ /**
+ * The Sp persistence flags
+ */
+ private int persistenceFlags;
+
+ /**
+ * Constructor
+ *
+ * @param erd the entity record data
+ */
+ public Sp(EscherRecordData erd)
+ {
+ super(erd);
+ shapeType = getInstance();
+ byte[] bytes = getBytes();
+ shapeId = IntegerHelper.getInt(bytes[0], bytes[1], bytes[2], bytes[3]);
+ persistenceFlags = IntegerHelper.getInt(bytes[4], bytes[5],
+ bytes[6], bytes[7]);
+ }
+
+ /**
+ * Constructor - used when writing
+ *
+ * @param st the shape type
+ * @param sid the shape id
+ * @param p persistence flags
+ */
+ public Sp(ShapeType st, int sid, int p)
+ {
+ super(EscherRecordType.SP);
+ setVersion(2);
+ shapeType = st.getValue();
+ shapeId = sid;
+ persistenceFlags = p;
+ setInstance(shapeType);
+ }
+
+ /**
+ * Accessor for the shape id
+ *
+ * @return the shape id
+ */
+ int getShapeId()
+ {
+ return shapeId;
+ }
+
+ /**
+ * Accessor for the shape type
+ *
+ * @return the shape type
+ */
+ int getShapeType()
+ {
+ return shapeType;
+ }
+
+ /**
+ * Gets the data
+ *
+ * @return the binary data
+ */
+ byte[] getData()
+ {
+ data = new byte[8];
+ IntegerHelper.getFourBytes(shapeId, data, 0);
+ IntegerHelper.getFourBytes(persistenceFlags, data, 4);
+ return setHeaderData(data);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/SpContainer.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/SpContainer.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/SpContainer.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,44 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+/**
+ * Shape contianer - Contains the data for this particular shape
+ */
+class SpContainer extends EscherContainer
+{
+ /**
+ * Constructor
+ */
+ public SpContainer()
+ {
+ super(EscherRecordType.SP_CONTAINER);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param erd the escher record data
+ */
+ public SpContainer(EscherRecordData erd)
+ {
+ super(erd);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/Spgr.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/Spgr.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/Spgr.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,61 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+/**
+ * The SpGr escher atom
+ */
+class Spgr extends EscherAtom
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param erd the raw escher record data
+ */
+ public Spgr(EscherRecordData erd)
+ {
+ super(erd);
+ }
+
+ /**
+ * Constructor
+ */
+ public Spgr()
+ {
+ super(EscherRecordType.SPGR);
+ setVersion(1);
+ data = new byte[16];
+ }
+
+ /**
+ * Gets the binary data
+ *
+ * @return the binary data
+ */
+ byte[] getData()
+ {
+ return setHeaderData(data);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/SpgrContainer.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/SpgrContainer.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/SpgrContainer.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,51 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import common.Logger;
+
+/**
+ * An Spgr container record in an escher stream
+ */
+class SpgrContainer extends EscherContainer
+{
+ /**
+ * The logger
+ */
+ private static final Logger logger = Logger.getLogger(SpgrContainer.class);
+
+ /**
+ * Constructor used when writing
+ */
+ public SpgrContainer()
+ {
+ super(EscherRecordType.SPGR_CONTAINER);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param erd the escher record data read in
+ */
+ public SpgrContainer(EscherRecordData erd)
+ {
+ super(erd);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/SplitMenuColors.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/SplitMenuColors.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/SplitMenuColors.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,67 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+/**
+ * Split menu colours escher record
+ */
+class SplitMenuColors extends EscherAtom
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param erd escher record data
+ */
+ public SplitMenuColors(EscherRecordData erd)
+ {
+ super(erd);
+ }
+
+ /**
+ * Constructor
+ */
+ public SplitMenuColors()
+ {
+ super(EscherRecordType.SPLIT_MENU_COLORS);
+ setVersion(0);
+ setInstance(4);
+
+ data = new byte[]
+ {(byte) 0x0d, (byte) 0x00, (byte) 0x00, (byte) 0x08,
+ (byte) 0x0c, (byte) 0x00, (byte) 0x00, (byte) 0x08,
+ (byte) 0x17, (byte) 0x00, (byte) 0x00, (byte) 0x08,
+ (byte) 0xf7, (byte) 0x00, (byte) 0x00, (byte) 0x10};
+ }
+
+ /**
+ * The binary data
+ *
+ * @return the binary data
+ */
+ byte[] getData()
+ {
+ return setHeaderData(data);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/drawing/TextObjectRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/drawing/TextObjectRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/drawing/TextObjectRecord.java 17 Aug 2012 14:51:20 -0000 1.1
@@ -0,0 +1,120 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.drawing;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+import jxl.read.biff.Record;
+
+/**
+ * A TextObject (TXO) record which contains the information for comments
+ */
+public class TextObjectRecord extends WritableRecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(TextObjectRecord.class);
+
+ /**
+ * The raw drawing data which was read in
+ */
+ private byte[] data;
+
+ /**
+ * The text
+ */
+ private int textLength;
+
+ /**
+ * Constructor invoked when writing out this object
+ *
+ * @param t the text string
+ */
+ TextObjectRecord(String t)
+ {
+ super(Type.TXO);
+
+ textLength = t.length();
+ }
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ */
+ public TextObjectRecord(Record t)
+ {
+ super(t);
+ data = getRecord().getData();
+ textLength = IntegerHelper.getInt(data[10], data[11]);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param d the drawing data
+ */
+ public TextObjectRecord(byte[] d)
+ {
+ super(Type.TXO);
+ data = d;
+ }
+
+ /**
+ * Expose the protected function to the SheetImpl in this package
+ *
+ * @return the raw record data
+ */
+ public byte[] getData()
+ {
+ if (data != null)
+ {
+ return data;
+ }
+
+ data = new byte[18];
+
+ // the options
+ int options = 0;
+ options |= (0x1 << 1); // horizontal alignment - left
+ options |= (0x1 << 4); // vertical alignment - top
+ options |= (0x1 << 9); // lock text
+ IntegerHelper.getTwoBytes(options, data, 0);
+
+ // the rotation
+ // no rotation
+
+ // Length of text
+ IntegerHelper.getTwoBytes(textLength, data, 10);
+
+ // Length of formatting runs
+ IntegerHelper.getTwoBytes(0x10, data, 12);
+
+ return data;
+ }
+}
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Add.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Add.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Add.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,64 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A cell reference in a formula
+ */
+class Add extends BinaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public Add()
+ {
+ }
+
+ /**
+ * Gets the symbol for string displays
+ *
+ * @return the symbol
+ */
+ public String getSymbol()
+ {
+ return "+";
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.ADD;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 4;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Area.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Area.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Area.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,423 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.biff.CellReferenceHelper;
+import jxl.biff.IntegerHelper;
+
+/**
+ * A nested class to hold range information
+ */
+class Area extends Operand implements ParsedThing
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(Area.class);
+
+ /**
+ * The first column
+ */
+ private int columnFirst;
+
+ /**
+ * The first row
+ */
+ private int rowFirst;
+
+ /**
+ * The last column
+ */
+ private int columnLast;
+
+ /**
+ * The last row
+ */
+ private int rowLast;
+
+ /**
+ * Indicates whether the first column is a relative or absolute reference
+ */
+ private boolean columnFirstRelative;
+
+ /**
+ * Indicates whether the first row is a relative or absolute reference
+ */
+ private boolean rowFirstRelative;
+
+ /**
+ * Indicates whether the last column is a relative or absolute reference
+ */
+ private boolean columnLastRelative;
+
+ /**
+ * Indicates whether the last row is a relative or absolute reference
+ */
+ private boolean rowLastRelative;
+
+ /**
+ * Constructor
+ */
+ Area()
+ {
+ }
+
+ /**
+ * Constructor invoked when parsing a string formula
+ *
+ * @param s the string to parse
+ */
+ Area(String s)
+ {
+ int seppos = s.indexOf(":");
+ Assert.verify(seppos != -1);
+ String startcell = s.substring(0, seppos);
+ String endcell = s.substring(seppos + 1);
+
+ columnFirst = CellReferenceHelper.getColumn(startcell);
+ rowFirst = CellReferenceHelper.getRow(startcell);
+ columnLast = CellReferenceHelper.getColumn(endcell);
+ rowLast = CellReferenceHelper.getRow(endcell);
+
+ columnFirstRelative = CellReferenceHelper.isColumnRelative(startcell);
+ rowFirstRelative = CellReferenceHelper.isRowRelative(startcell);
+ columnLastRelative = CellReferenceHelper.isColumnRelative(endcell);
+ rowLastRelative = CellReferenceHelper.isRowRelative(endcell);
+ }
+
+ /**
+ * Accessor for the first column
+ *
+ * @return the first column
+ */
+ int getFirstColumn()
+ {
+ return columnFirst;
+ }
+
+ /**
+ * Accessor for the first row
+ *
+ * @return the first row
+ */
+ int getFirstRow()
+ {
+ return rowFirst;
+ }
+
+ /**
+ * Accessor for the last column
+ *
+ * @return the last column
+ */
+ int getLastColumn()
+ {
+ return columnLast;
+ }
+
+ /**
+ * Accessor for the last row
+ *
+ * @return the last row
+ */
+ int getLastRow()
+ {
+ return rowLast;
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ rowFirst = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ rowLast = IntegerHelper.getInt(data[pos + 2], data[pos + 3]);
+ int columnMask = IntegerHelper.getInt(data[pos + 4], data[pos + 5]);
+ columnFirst = columnMask & 0x00ff;
+ columnFirstRelative = ((columnMask & 0x4000) != 0);
+ rowFirstRelative = ((columnMask & 0x8000) != 0);
+ columnMask = IntegerHelper.getInt(data[pos + 6], data[pos + 7]);
+ columnLast = columnMask & 0x00ff;
+ columnLastRelative = ((columnMask & 0x4000) != 0);
+ rowLastRelative = ((columnMask & 0x8000) != 0);
+
+ return 8;
+ }
+
+ /**
+ * Gets the string representation of this item
+ *
+ * @param buf the string buffer
+ */
+ public void getString(StringBuffer buf)
+ {
+ CellReferenceHelper.getCellReference(columnFirst, rowFirst, buf);
+ buf.append(':');
+ CellReferenceHelper.getCellReference(columnLast, rowLast, buf);
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[9];
+ data[0] = !useAlternateCode() ? Token.AREA.getCode() :
+ Token.AREA.getCode2();
+
+ IntegerHelper.getTwoBytes(rowFirst, data, 1);
+ IntegerHelper.getTwoBytes(rowLast, data, 3);
+
+ int grcol = columnFirst;
+
+ // Set the row/column relative bits if applicable
+ if (rowFirstRelative)
+ {
+ grcol |= 0x8000;
+ }
+
+ if (columnFirstRelative)
+ {
+ grcol |= 0x4000;
+ }
+
+ IntegerHelper.getTwoBytes(grcol, data, 5);
+
+ grcol = columnLast;
+
+ // Set the row/column relative bits if applicable
+ if (rowLastRelative)
+ {
+ grcol |= 0x8000;
+ }
+
+ if (columnLastRelative)
+ {
+ grcol |= 0x4000;
+ }
+
+ IntegerHelper.getTwoBytes(grcol, data, 7);
+
+ return data;
+ }
+
+ /**
+ * Adjusts all the relative cell references in this formula by the
+ * amount specified. Used when copying formulas
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ if (columnFirstRelative)
+ {
+ columnFirst += colAdjust;
+ }
+
+ if (columnLastRelative)
+ {
+ columnLast += colAdjust;
+ }
+
+ if (rowFirstRelative)
+ {
+ rowFirst += rowAdjust;
+ }
+
+ if (rowLastRelative)
+ {
+ rowLast += rowAdjust;
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ if (!currentSheet)
+ {
+ return;
+ }
+
+ if (col <= columnFirst)
+ {
+ columnFirst++;
+ }
+
+ if (col <= columnLast)
+ {
+ columnLast++;
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ if (!currentSheet)
+ {
+ return;
+ }
+
+ if (col < columnFirst)
+ {
+ columnFirst--;
+ }
+
+ if (col <= columnLast)
+ {
+ columnLast--;
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was inserted
+ * @param row the row number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowInserted(int sheetIndex, int row, boolean currentSheet)
+ {
+ if (!currentSheet)
+ {
+ return;
+ }
+
+ if (rowLast == 0xffff)
+ {
+ // area applies to the whole column, so nothing to do
+ return;
+ }
+
+ if (row <= rowFirst)
+ {
+ rowFirst++;
+ }
+
+ if (row <= rowLast)
+ {
+ rowLast++;
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was removed
+ * @param row the row number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowRemoved(int sheetIndex, int row, boolean currentSheet)
+ {
+ if (!currentSheet)
+ {
+ return;
+ }
+
+ if (rowLast == 0xffff)
+ {
+ // area applies to the whole column, so nothing to do
+ return;
+ }
+
+ if (row < rowFirst)
+ {
+ rowFirst--;
+ }
+
+ if (row <= rowLast)
+ {
+ rowLast--;
+ }
+ }
+
+ /**
+ * Used by subclasses columns/row range to set the range information
+ *
+ * @param colFirst the first column
+ * @param colLast the last column
+ * @param rwFirst the first row
+ * @param rwLast the last row
+ * @param colFirstRel flag indicating whether the first column is relative
+ * @param colLastRel flag indicating whether the last column is relative
+ * @param rowFirstRel flag indicating whether the first row is relative
+ * @param rowLastRel flag indicating whether the last row is relative
+ */
+ protected void setRangeData(int colFirst,
+ int colLast,
+ int rwFirst,
+ int rwLast,
+ boolean colFirstRel,
+ boolean colLastRel,
+ boolean rowFirstRel,
+ boolean rowLastRel)
+ {
+ columnFirst = colFirst;
+ columnLast = colLast;
+ rowFirst = rwFirst;
+ rowLast = rwLast;
+ columnFirstRelative = colFirstRel;
+ columnLastRelative = colLastRel;
+ rowFirstRelative = rowFirstRel;
+ rowLastRelative = rowLastRel;
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing here
+ */
+ void handleImportedCellReferences()
+ {
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Area3d.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Area3d.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Area3d.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,475 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.biff.CellReferenceHelper;
+import jxl.biff.IntegerHelper;
+
+/**
+ * A nested class to hold range information
+ */
+class Area3d extends Operand implements ParsedThing
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(Area3d.class);
+
+ /**
+ * The sheet
+ */
+ private int sheet;
+
+ /**
+ * The first column
+ */
+ private int columnFirst;
+
+ /**
+ * The first row
+ */
+ private int rowFirst;
+
+ /**
+ * The last column
+ */
+ private int columnLast;
+
+ /**
+ * The last row
+ */
+ private int rowLast;
+
+ /**
+ * Indicates whether the first column is relative
+ */
+ private boolean columnFirstRelative;
+
+ /**
+ * Indicates whether the first row is relative
+ */
+ private boolean rowFirstRelative;
+
+ /**
+ * Indicates whether the last column is relative
+ */
+ private boolean columnLastRelative;
+
+ /**
+ * Indicates whether the last row is relative
+ */
+ private boolean rowLastRelative;
+
+ /**
+ * A handle to the workbook
+ */
+ private ExternalSheet workbook;
+
+ /**
+ * Constructor
+ *
+ * @param es the external sheet
+ */
+ Area3d(ExternalSheet es)
+ {
+ workbook = es;
+ }
+
+ /**
+ * Constructor invoked when parsing a string formula
+ *
+ * @param s the string to parse
+ * @param es the external sheet
+ * @exception FormulaException
+ */
+ Area3d(String s, ExternalSheet es) throws FormulaException
+ {
+ workbook = es;
+ int seppos = s.lastIndexOf(":");
+ Assert.verify(seppos != -1);
+ String endcell = s.substring(seppos + 1);
+
+ // Get the the start cell details
+ int sep = s.indexOf('!');
+ String cellString = s.substring(sep + 1, seppos);
+ columnFirst = CellReferenceHelper.getColumn(cellString);
+ rowFirst = CellReferenceHelper.getRow(cellString);
+
+ // Get the sheet index
+ String sheetName = s.substring(0, sep);
+
+ // Remove single quotes, if they exist
+ if (sheetName.charAt(0) == '\'' &&
+ sheetName.charAt(sheetName.length() - 1) == '\'')
+ {
+ sheetName = sheetName.substring(1, sheetName.length() - 1);
+ }
+
+ sheet = es.getExternalSheetIndex(sheetName);
+
+ if (sheet < 0)
+ {
+ throw new FormulaException(FormulaException.SHEET_REF_NOT_FOUND,
+ sheetName);
+ }
+
+ // Get the last cell index
+ columnLast = CellReferenceHelper.getColumn(endcell);
+ rowLast = CellReferenceHelper.getRow(endcell);
+
+ columnFirstRelative = true;
+ rowFirstRelative = true;
+ columnLastRelative = true;
+ rowLastRelative = true;
+ }
+
+ /**
+ * Accessor for the first column
+ *
+ * @return the first column
+ */
+ int getFirstColumn()
+ {
+ return columnFirst;
+ }
+
+ /**
+ * Accessor for the first row
+ *
+ * @return the first row
+ */
+ int getFirstRow()
+ {
+ return rowFirst;
+ }
+
+ /**
+ * Accessor for the last column
+ *
+ * @return the last column
+ */
+ int getLastColumn()
+ {
+ return columnLast;
+ }
+
+ /**
+ * Accessor for the last row
+ *
+ * @return the last row
+ */
+ int getLastRow()
+ {
+ return rowLast;
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ sheet = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ rowFirst = IntegerHelper.getInt(data[pos + 2], data[pos + 3]);
+ rowLast = IntegerHelper.getInt(data[pos + 4], data[pos + 5]);
+ int columnMask = IntegerHelper.getInt(data[pos + 6], data[pos + 7]);
+ columnFirst = columnMask & 0x00ff;
+ columnFirstRelative = ((columnMask & 0x4000) != 0);
+ rowFirstRelative = ((columnMask & 0x8000) != 0);
+ columnMask = IntegerHelper.getInt(data[pos + 8], data[pos + 9]);
+ columnLast = columnMask & 0x00ff;
+ columnLastRelative = ((columnMask & 0x4000) != 0);
+ rowLastRelative = ((columnMask & 0x8000) != 0);
+
+ return 10;
+ }
+
+ /**
+ * Gets the string version of this area
+ *
+ * @param buf the area to populate
+ */
+ public void getString(StringBuffer buf)
+ {
+ CellReferenceHelper.getCellReference
+ (sheet, columnFirst, rowFirst, workbook, buf);
+ buf.append(':');
+ CellReferenceHelper.getCellReference(columnLast, rowLast, buf);
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[11];
+ data[0] = Token.AREA3D.getCode();
+
+ IntegerHelper.getTwoBytes(sheet, data, 1);
+
+ IntegerHelper.getTwoBytes(rowFirst, data, 3);
+ IntegerHelper.getTwoBytes(rowLast, data, 5);
+
+ int grcol = columnFirst;
+
+ // Set the row/column relative bits if applicable
+ if (rowFirstRelative)
+ {
+ grcol |= 0x8000;
+ }
+
+ if (columnFirstRelative)
+ {
+ grcol |= 0x4000;
+ }
+
+ IntegerHelper.getTwoBytes(grcol, data, 7);
+
+ grcol = columnLast;
+
+ // Set the row/column relative bits if applicable
+ if (rowLastRelative)
+ {
+ grcol |= 0x8000;
+ }
+
+ if (columnLastRelative)
+ {
+ grcol |= 0x4000;
+ }
+
+ IntegerHelper.getTwoBytes(grcol, data, 9);
+
+ return data;
+ }
+
+ /**
+ * Adjusts all the relative cell references in this formula by the
+ * amount specified. Used when copying formulas
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ if (columnFirstRelative)
+ {
+ columnFirst += colAdjust;
+ }
+
+ if (columnLastRelative)
+ {
+ columnLast += colAdjust;
+ }
+
+ if (rowFirstRelative)
+ {
+ rowFirst += rowAdjust;
+ }
+
+ if (rowLastRelative)
+ {
+ rowLast += rowAdjust;
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ if (sheetIndex != sheet)
+ {
+ return;
+ }
+
+ if (columnFirst >= col)
+ {
+ columnFirst++;
+ }
+
+ if (columnLast >= col)
+ {
+ columnLast++;
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ if (sheetIndex != sheet)
+ {
+ return;
+ }
+
+ if (col < columnFirst)
+ {
+ columnFirst--;
+ }
+
+ if (col <= columnLast)
+ {
+ columnLast--;
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was inserted
+ * @param row the row number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowInserted(int sheetIndex, int row, boolean currentSheet)
+ {
+ if (sheetIndex != sheet)
+ {
+ return;
+ }
+
+ if (rowLast == 0xffff)
+ {
+ // area applies to the whole column, so nothing to do
+ return;
+ }
+
+ if (row <= rowFirst)
+ {
+ rowFirst++;
+ }
+
+ if (row <= rowLast)
+ {
+ rowLast++;
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was removed
+ * @param row the row number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowRemoved(int sheetIndex, int row, boolean currentSheet)
+ {
+ if (sheetIndex != sheet)
+ {
+ return;
+ }
+
+ if (rowLast == 0xffff)
+ {
+ // area applies to the whole column, so nothing to do
+ return;
+ }
+
+ if (row < rowFirst)
+ {
+ rowFirst--;
+ }
+
+ if (row <= rowLast)
+ {
+ rowLast--;
+ }
+ }
+
+ /**
+ * Used by subclasses columns/row range to set the range information
+ *
+ * @param sht the sheet containing the area
+ * @param colFirst the first column
+ * @param colLast the last column
+ * @param rwFirst the first row
+ * @param rwLast the last row
+ * @param colFirstRel flag indicating whether the first column is relative
+ * @param colLastRel flag indicating whether the last column is relative
+ * @param rowFirstRel flag indicating whether the first row is relative
+ * @param rowLastRel flag indicating whether the last row is relative
+ */
+ protected void setRangeData(int sht,
+ int colFirst,
+ int colLast,
+ int rwFirst,
+ int rwLast,
+ boolean colFirstRel,
+ boolean colLastRel,
+ boolean rowFirstRel,
+ boolean rowLastRel)
+ {
+ sheet = sht;
+ columnFirst = colFirst;
+ columnLast = colLast;
+ rowFirst = rwFirst;
+ rowLast = rwLast;
+ columnFirstRelative = colFirstRel;
+ columnLastRelative = colLastRel;
+ rowFirstRelative = rowFirstRel;
+ rowLastRelative = rowLastRel;
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ */
+ void handleImportedCellReferences()
+ {
+ setInvalid();
+ }
+}
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/ArgumentSeparator.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/ArgumentSeparator.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/ArgumentSeparator.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,34 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A dummy token used when parsing strings in order to indicate the
+ * separation of parameters
+ */
+class ArgumentSeparator extends StringParseItem
+{
+ /**
+ * Constructor
+ */
+ public ArgumentSeparator()
+ {
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Attribute.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Attribute.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Attribute.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,547 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import java.util.Stack;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.IntegerHelper;
+
+/**
+ * A special attribute control token - typically either a SUM function
+ * or an IF function
+ */
+class Attribute extends Operator implements ParsedThing
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(Attribute.class);
+
+ /**
+ * The options used by the attribute
+ */
+ private int options;
+
+ /**
+ * The word contained in this attribute
+ */
+ private int word;
+
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings settings;
+
+ private static final int SUM_MASK = 0x10;
+ private static final int IF_MASK = 0x02;
+ private static final int CHOOSE_MASK = 0x04;
+ private static final int GOTO_MASK = 0x08;
+
+ /**
+ * If this attribute is an IF functions, sets the associated if conditions
+ */
+ private VariableArgFunction ifConditions;
+
+ /**
+ * Constructor
+ *
+ * @param ws the workbook settings
+ */
+ public Attribute(WorkbookSettings ws)
+ {
+ settings = ws;
+ }
+
+ /**
+ * Constructor for use when this is called when parsing a string
+ *
+ * @param sf the built in function
+ * @param ws the workbook settings
+ */
+ public Attribute(StringFunction sf, WorkbookSettings ws)
+ {
+ settings = ws;
+
+ if (sf.getFunction(settings) == Function.SUM)
+ {
+ options |= SUM_MASK;
+ }
+ else if (sf.getFunction(settings) == Function.IF)
+ {
+ options |= IF_MASK;
+ }
+ }
+
+ /**
+ * Sets the if conditions for this attribute, if it represents an IF function
+ *
+ * @param vaf a VariableArgFunction
value
+ */
+ void setIfConditions(VariableArgFunction vaf)
+ {
+ ifConditions = vaf;
+
+ // Sometimes there is not Attribute token, so we need to create
+ // an attribute out of thin air. In that case, make sure the if mask
+ options |= IF_MASK;
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ options = data[pos];
+ word = IntegerHelper.getInt(data[pos + 1], data[pos + 2]);
+
+ if (!isChoose())
+ {
+ return 3;
+ }
+
+ // word contains the number of jumps by index.
+ // and there is an additional final jump to the choose function itself.
+ return 3 + (word + 1) * 2;
+ }
+
+ /**
+ * Queries whether this attribute is a function
+ *
+ * @return TRUE if this is a function, FALSE otherwise
+ */
+ public boolean isFunction()
+ {
+ return (options & (SUM_MASK | IF_MASK)) != 0;
+ }
+
+ /**
+ * Queries whether this attribute is a sum
+ *
+ * @return TRUE if this is SUM, FALSE otherwise
+ */
+ public boolean isSum()
+ {
+ return (options & SUM_MASK) != 0;
+ }
+
+ /**
+ * Queries whether this attribute is an IF
+ *
+ * @return TRUE if this is an IF, FALSE otherwise
+ */
+ public boolean isIf()
+ {
+ return (options & IF_MASK) != 0;
+ }
+
+ /**
+ * Queries whether this attribute is a goto
+ *
+ * @return TRUE if this is a goto, FALSE otherwise
+ */
+ public boolean isGoto()
+ {
+ return (options & GOTO_MASK) != 0;
+ }
+
+ /**
+ * Queries whether this attribute is a CHOOSE
+ *
+ * @return TRUE if this is a CHOOSE, FALSE otherwise
+ */
+ public boolean isChoose()
+ {
+ return (options & CHOOSE_MASK) != 0;
+ }
+
+ /**
+ * Gets the operands for this operator from the stack
+ *
+ * @param s the token stack
+ */
+ public void getOperands(Stack s)
+ {
+ if ((options & SUM_MASK) != 0)
+ {
+ ParseItem o1 = (ParseItem) s.pop();
+ add(o1);
+ }
+ else if ((options & IF_MASK) != 0)
+ {
+ ParseItem o1 = (ParseItem) s.pop();
+ add(o1);
+ }
+ }
+
+ /**
+ * Gets the string version of the attribute
+ *
+ * @param buf the buffer to populate
+ */
+ public void getString(StringBuffer buf)
+ {
+ if ((options & SUM_MASK) != 0)
+ {
+ ParseItem[] operands = getOperands();
+ buf.append(Function.SUM.getName(settings));
+ buf.append('(');
+ operands[0].getString(buf);
+ buf.append(')');
+ }
+ else if ((options & IF_MASK) != 0)
+ {
+ buf.append(Function.IF.getName(settings));
+ buf.append('(');
+
+ ParseItem[] operands = ifConditions.getOperands();
+
+ // Operands are in the correct order for IFs
+ for (int i = 0; i < operands.length - 1; i++)
+ {
+ operands[i].getString(buf);
+ buf.append(',');
+ }
+ operands[operands.length - 1].getString(buf);
+ buf.append(')');
+ }
+ }
+
+ /**
+ * Gets the token representation of this item in RPN. The Attribute
+ * token is a special case, which overrides anything useful we could do
+ * in the base class
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[0];
+ if (isSum())
+ {
+ // Get the data for the operands
+ ParseItem[] operands = getOperands();
+
+ // Get the operands in reverse order to get the RPN
+ for (int i = operands.length - 1; i >= 0; i--)
+ {
+ byte[] opdata = operands[i].getBytes();
+
+ // Grow the array
+ byte[] newdata = new byte[data.length + opdata.length];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ System.arraycopy(opdata, 0, newdata, data.length, opdata.length);
+ data = newdata;
+ }
+
+ // Add on the operator byte
+ byte[] newdata = new byte[data.length + 4];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ newdata[data.length] = Token.ATTRIBUTE.getCode();
+ newdata[data.length + 1] = SUM_MASK;
+ data = newdata;
+ }
+ else if (isIf())
+ {
+ return getIf();
+ }
+
+ return data;
+ }
+
+ /**
+ * Gets the associated if conditions with this attribute
+ *
+ * @return the associated if conditions
+ */
+ private byte[] getIf()
+ {
+ ParseItem[] operands = ifConditions.getOperands();
+
+ // The position of the offset to the false portion of the expression
+ int falseOffsetPos = 0;
+ int gotoEndPos = 0;
+ int numArgs = operands.length;
+
+ // First, write out the conditions
+ byte[] data = operands[0].getBytes();
+
+ // Grow the array by three and write out the optimized if attribute
+ int pos = data.length;
+ byte[] newdata = new byte[data.length + 4];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ data = newdata;
+ data[pos] = Token.ATTRIBUTE.getCode();
+ data[pos + 1] = 0x2;
+ falseOffsetPos = pos + 2;
+
+ // Get the true portion of the expression and add it to the array
+ byte[] truedata = operands[1].getBytes();
+ newdata = new byte[data.length + truedata.length];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ System.arraycopy(truedata, 0, newdata, data.length, truedata.length);
+ data = newdata;
+
+ // Grow the array by three and write out the goto end attribute
+ pos = data.length;
+ newdata = new byte[data.length + 4];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ data = newdata;
+ data[pos] = Token.ATTRIBUTE.getCode();
+ data[pos + 1] = 0x8;
+ gotoEndPos = pos + 2;
+
+ // If the false condition exists, then add that to the array
+ if (numArgs > 2)
+ {
+ // Set the offset to the false expression to be the current position
+ IntegerHelper.getTwoBytes(data.length - falseOffsetPos - 2,
+ data, falseOffsetPos);
+
+ // Copy in the false expression
+ byte[] falsedata = operands[numArgs - 1].getBytes();
+ newdata = new byte[data.length + falsedata.length];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ System.arraycopy(falsedata, 0, newdata, data.length, falsedata.length);
+ data = newdata;
+
+ // Write the goto to skip over the varargs token
+ pos = data.length;
+ newdata = new byte[data.length + 4];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ data = newdata;
+ data[pos] = Token.ATTRIBUTE.getCode();
+ data[pos + 1] = 0x8;
+ data[pos + 2] = 0x3;
+ }
+
+ // Grow the array and write out the varargs function
+ pos = data.length;
+ newdata = new byte[data.length + 4];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ data = newdata;
+ data[pos] = Token.FUNCTIONVARARG.getCode();
+ data[pos + 1] = (byte) numArgs;
+ data[pos + 2] = 1;
+ data[pos + 3] = 0; // indicates the end of the expression
+
+ // Position the final offsets
+ int endPos = data.length - 1;
+
+ if (numArgs < 3)
+ {
+ // Set the offset to the false expression to be the current position
+ IntegerHelper.getTwoBytes(endPos - falseOffsetPos - 5,
+ data, falseOffsetPos);
+ }
+
+ // Set the offset after the true expression
+ IntegerHelper.getTwoBytes(endPos - gotoEndPos - 2,
+ data, gotoEndPos);
+
+ return data;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 3;
+ }
+
+ /**
+ * Default behaviour is to do nothing
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ ParseItem[] operands = null;
+
+ if (isIf())
+ {
+ operands = ifConditions.getOperands();
+ }
+ else
+ {
+ operands = getOperands();
+ }
+
+ for (int i = 0; i < operands.length; i++)
+ {
+ operands[i].adjustRelativeCellReferences(colAdjust, rowAdjust);
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ ParseItem[] operands = null;
+
+ if (isIf())
+ {
+ operands = ifConditions.getOperands();
+ }
+ else
+ {
+ operands = getOperands();
+ }
+
+ for (int i = 0; i < operands.length; i++)
+ {
+ operands[i].columnInserted(sheetIndex, col, currentSheet);
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ ParseItem[] operands = null;
+
+ if (isIf())
+ {
+ operands = ifConditions.getOperands();
+ }
+ else
+ {
+ operands = getOperands();
+ }
+
+ for (int i = 0; i < operands.length; i++)
+ {
+ operands[i].columnRemoved(sheetIndex, col, currentSheet);
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was inserted
+ * @param row the row number which was inserted1
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowInserted(int sheetIndex, int row, boolean currentSheet)
+ {
+ ParseItem[] operands = null;
+
+ if (isIf())
+ {
+ operands = ifConditions.getOperands();
+ }
+ else
+ {
+ operands = getOperands();
+ }
+
+ for (int i = 0; i < operands.length; i++)
+ {
+ operands[i].rowInserted(sheetIndex, row, currentSheet);
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was removed
+ * @param row the row number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowRemoved(int sheetIndex, int row, boolean currentSheet)
+ {
+ ParseItem[] operands = null;
+
+ if (isIf())
+ {
+ operands = ifConditions.getOperands();
+ }
+ else
+ {
+ operands = getOperands();
+ }
+
+ for (int i = 0; i < operands.length; i++)
+ {
+ operands[i].rowRemoved(sheetIndex, row, currentSheet);
+ }
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing, as operators don't have cell references
+ */
+ void handleImportedCellReferences()
+ {
+ ParseItem[] operands = null;
+
+ if (isIf())
+ {
+ operands = ifConditions.getOperands();
+ }
+ else
+ {
+ operands = getOperands();
+ }
+
+ for (int i = 0; i < operands.length; i++)
+ {
+ operands[i].handleImportedCellReferences();
+ }
+ }
+}
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/BinaryOperator.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/BinaryOperator.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/BinaryOperator.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,224 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Logger;
+
+import java.util.Stack;
+
+/**
+ * A cell reference in a formula
+ */
+abstract class BinaryOperator extends Operator implements ParsedThing
+{
+ // The logger
+ private static final Logger logger = Logger.getLogger(BinaryOperator.class);
+
+ /**
+ * Constructor
+ */
+ public BinaryOperator()
+ {
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ return 0;
+ }
+
+ /**
+ * Gets the operands for this operator from the stack
+ *
+ * @param s the token stack
+ */
+ public void getOperands(Stack s)
+ {
+ ParseItem o1 = (ParseItem) s.pop();
+ ParseItem o2 = (ParseItem) s.pop();
+
+ add(o1);
+ add(o2);
+ }
+
+ /**
+ * Gets the string version of this binary operator
+ *
+ * @param buf a the string buffer
+ */
+ public void getString(StringBuffer buf)
+ {
+ ParseItem[] operands = getOperands();
+ operands[1].getString(buf);
+ buf.append(getSymbol());
+ operands[0].getString(buf);
+ }
+
+ /**
+ * Adjusts all the relative cell references in this formula by the
+ * amount specified. Used when copying formulas
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ ParseItem[] operands = getOperands();
+ operands[1].adjustRelativeCellReferences(colAdjust, rowAdjust);
+ operands[0].adjustRelativeCellReferences(colAdjust, rowAdjust);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ operands[1].columnInserted(sheetIndex, col, currentSheet);
+ operands[0].columnInserted(sheetIndex, col, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ operands[1].columnRemoved(sheetIndex, col, currentSheet);
+ operands[0].columnRemoved(sheetIndex, col, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was inserted
+ * @param row the row number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowInserted(int sheetIndex, int row, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ operands[1].rowInserted(sheetIndex, row, currentSheet);
+ operands[0].rowInserted(sheetIndex, row, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was removed
+ * @param row the row number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowRemoved(int sheetIndex, int row, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ operands[1].rowRemoved(sheetIndex, row, currentSheet);
+ operands[0].rowRemoved(sheetIndex, row, currentSheet);
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ // Get the data for the operands
+ ParseItem[] operands = getOperands();
+ byte[] data = new byte[0];
+
+ // Get the operands in reverse order to get the RPN
+ for (int i = operands.length - 1; i >= 0; i--)
+ {
+ byte[] opdata = operands[i].getBytes();
+
+ // Grow the array
+ byte[] newdata = new byte[data.length + opdata.length];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ System.arraycopy(opdata, 0, newdata, data.length, opdata.length);
+ data = newdata;
+ }
+
+ // Add on the operator byte
+ byte[] newdata = new byte[data.length + 1];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ newdata[data.length] = getToken().getCode();
+
+ return newdata;
+ }
+
+ /**
+ * Abstract method which gets the binary operator string symbol
+ *
+ * @return the string symbol for this token
+ */
+ abstract String getSymbol();
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ abstract Token getToken();
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing, as operators don't have cell references
+ */
+ void handleImportedCellReferences()
+ {
+ ParseItem[] operands = getOperands();
+ operands[0].handleImportedCellReferences();
+ operands[1].handleImportedCellReferences();
+ }
+
+}
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/BooleanValue.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/BooleanValue.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/BooleanValue.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,97 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A boolean operand in a formula
+ */
+class BooleanValue extends Operand implements ParsedThing
+{
+ /**
+ * The boolean value
+ */
+ private boolean value;
+
+ /**
+ * Constructor
+ */
+ public BooleanValue()
+ {
+ }
+
+ /**
+ * Constructor used when parsing a string formula
+ *
+ * @param s the string token, including quote marks
+ */
+ public BooleanValue(String s)
+ {
+ // remove the quotes
+ value = Boolean.valueOf(s).booleanValue();
+ }
+
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ value = data[pos] == 1 ? true : false;
+ return 1;
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[2];
+ data[0] = Token.BOOL.getCode();
+ data[1] = (byte) (value == true ? 1 : 0);
+
+ return data;
+ }
+
+ /**
+ * Abstract method implementation to get the string equivalent of this
+ * token
+ *
+ * @param buf the string to append to
+ */
+ public void getString(StringBuffer buf)
+ {
+ buf.append((new Boolean(value)).toString());
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing
+ */
+ void handleImportedCellReferences()
+ {
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/BuiltInFunction.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/BuiltInFunction.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/BuiltInFunction.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,289 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import java.util.Stack;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.IntegerHelper;
+
+/**
+ * A built in function in a formula
+ */
+class BuiltInFunction extends Operator implements ParsedThing
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(BuiltInFunction.class);
+
+ /**
+ * The function
+ */
+ private Function function;
+
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings settings;
+
+ /**
+ * Constructor
+ * @param ws the workbook settings
+ */
+ public BuiltInFunction(WorkbookSettings ws)
+ {
+ settings = ws;
+ }
+
+ /**
+ * Constructor used when parsing a formula from a string
+ *
+ * @param f the function
+ * @param ws the workbook settings
+ */
+ public BuiltInFunction(Function f, WorkbookSettings ws)
+ {
+ function = f;
+ settings = ws;
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ int index = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ function = Function.getFunction(index);
+ Assert.verify(function != Function.UNKNOWN, "function code " + index);
+ return 2;
+ }
+
+ /**
+ * Gets the operands for this operator from the stack
+ *
+ * @param s the token stack
+ */
+ public void getOperands(Stack s)
+ {
+ // parameters are in the correct order, god damn them
+ ParseItem[] items = new ParseItem[function.getNumArgs()];
+ // modified in 2.4.3
+ for (int i = function.getNumArgs() - 1; i >= 0; i--)
+ {
+ ParseItem pi = (ParseItem) s.pop();
+
+ items[i] = pi;
+ }
+
+ for (int i = 0; i < function.getNumArgs(); i++)
+ {
+ add(items[i]);
+ }
+ }
+
+ /**
+ * Gets the string for this functions
+ *
+ * @param buf the buffer to append
+ */
+ public void getString(StringBuffer buf)
+ {
+ buf.append(function.getName(settings));
+ buf.append('(');
+
+ int numArgs = function.getNumArgs();
+
+ if (numArgs > 0)
+ {
+ ParseItem[] operands = getOperands();
+
+ // arguments are in the same order they were specified
+ operands[0].getString(buf);
+
+ for (int i = 1; i < numArgs; i++)
+ {
+ buf.append(',');
+ operands[i].getString(buf);
+ }
+ }
+
+ buf.append(')');
+ }
+
+ /**
+ * Adjusts all the relative cell references in this formula by the
+ * amount specified. Used when copying formulas
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ ParseItem[] operands = getOperands();
+
+ for (int i = 0; i < operands.length; i++)
+ {
+ operands[i].adjustRelativeCellReferences(colAdjust, rowAdjust);
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ for (int i = 0; i < operands.length; i++)
+ {
+ operands[i].columnInserted(sheetIndex, col, currentSheet);
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ for (int i = 0; i < operands.length; i++)
+ {
+ operands[i].columnRemoved(sheetIndex, col, currentSheet);
+ }
+ }
+
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was inserted
+ * @param row the row number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowInserted(int sheetIndex, int row, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ for (int i = 0; i < operands.length; i++)
+ {
+ operands[i].rowInserted(sheetIndex, row, currentSheet);
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was removed
+ * @param row the row number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowRemoved(int sheetIndex, int row, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ for (int i = 0; i < operands.length; i++)
+ {
+ operands[i].rowRemoved(sheetIndex, row, currentSheet);
+ }
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing, as operators don't have cell references
+ */
+ void handleImportedCellReferences()
+ {
+ ParseItem[] operands = getOperands();
+ for (int i = 0 ; i < operands.length ; i++)
+ {
+ operands[i].handleImportedCellReferences();
+ }
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ // Get the data for the operands
+ ParseItem[] operands = getOperands();
+ byte[] data = new byte[0];
+
+ for (int i = 0; i < operands.length; i++)
+ {
+ byte[] opdata = operands[i].getBytes();
+
+ // Grow the array
+ byte[] newdata = new byte[data.length + opdata.length];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ System.arraycopy(opdata, 0, newdata, data.length, opdata.length);
+ data = newdata;
+ }
+
+ // Add on the operator byte
+ byte[] newdata = new byte[data.length + 3];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ newdata[data.length] = !useAlternateCode() ? Token.FUNCTION.getCode() :
+ Token.FUNCTION.getCode2();
+ IntegerHelper.getTwoBytes(function.getCode(), newdata, data.length + 1);
+
+ return newdata;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 3;
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/CellReference.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/CellReference.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/CellReference.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,296 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Logger;
+
+import jxl.Cell;
+import jxl.biff.CellReferenceHelper;
+import jxl.biff.IntegerHelper;
+
+/**
+ * A cell reference in a formula
+ */
+class CellReference extends Operand implements ParsedThing
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(CellReference.class);
+
+ /**
+ * Indicates whether the column reference is relative or absolute
+ */
+ private boolean columnRelative;
+
+ /**
+ * Indicates whether the row reference is relative or absolute
+ */
+ private boolean rowRelative;
+
+ /**
+ * The column reference
+ */
+ private int column;
+
+ /**
+ * The row reference
+ */
+ private int row;
+
+ /**
+ * The cell containing the formula. Stored in order to determine
+ * relative cell values
+ */
+ private Cell relativeTo;
+
+ /**
+ * Constructor
+ *
+ * @param rt the cell containing the formula
+ */
+ public CellReference(Cell rt)
+ {
+ relativeTo = rt;
+ }
+
+ /**
+ * Constructor
+ */
+ public CellReference()
+ {
+ }
+
+ /**
+ * Constructor invoked when parsing a text string
+ *
+ * @param s the string being parsed
+ */
+ public CellReference(String s)
+ {
+ column = CellReferenceHelper.getColumn(s);
+ row = CellReferenceHelper.getRow(s);
+ columnRelative = CellReferenceHelper.isColumnRelative(s);
+ rowRelative = CellReferenceHelper.isRowRelative(s);
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ row = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ int columnMask = IntegerHelper.getInt(data[pos + 2], data[pos + 3]);
+ column = columnMask & 0x00ff;
+ columnRelative = ((columnMask & 0x4000) != 0);
+ rowRelative = ((columnMask & 0x8000) != 0);
+
+ return 4;
+ }
+
+ /**
+ * Accessor for the column
+ *
+ * @return the column
+ */
+ public int getColumn()
+ {
+ return column;
+ }
+
+ /**
+ * Accessor for the row
+ *
+ * @return the row
+ */
+ public int getRow()
+ {
+ return row;
+ }
+
+ /**
+ * Gets the cell reference as a string for this item
+ *
+ * @param buf the string buffer to populate
+ */
+ public void getString(StringBuffer buf)
+ {
+ CellReferenceHelper.getCellReference(column, !columnRelative,
+ row, !rowRelative,
+ buf);
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[5];
+ data[0] = !useAlternateCode() ? Token.REF.getCode() :
+ Token.REF.getCode2();
+
+ IntegerHelper.getTwoBytes(row, data, 1);
+
+ int grcol = column;
+
+ // Set the row/column relative bits if applicable
+ if (rowRelative)
+ {
+ grcol |= 0x8000;
+ }
+
+ if (columnRelative)
+ {
+ grcol |= 0x4000;
+ }
+
+ IntegerHelper.getTwoBytes(grcol, data, 3);
+
+ return data;
+ }
+
+ /**
+ * Adjusts all the relative cell references in this formula by the
+ * amount specified. Used when copying formulas
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ if (columnRelative)
+ {
+ column += colAdjust;
+ }
+
+ if (rowRelative)
+ {
+ row += rowAdjust;
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ if (!currentSheet)
+ {
+ return;
+ }
+
+ if (column >= col)
+ {
+ column++;
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ if (!currentSheet)
+ {
+ return;
+ }
+
+ if (column >= col)
+ {
+ column--;
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was inserted
+ * @param r the row number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowInserted(int sheetIndex, int r, boolean currentSheet)
+ {
+ if (!currentSheet)
+ {
+ return;
+ }
+
+ if (row >= r)
+ {
+ row++;
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was removed
+ * @param r the row number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowRemoved(int sheetIndex, int r, boolean currentSheet)
+ {
+ if (!currentSheet)
+ {
+ return;
+ }
+
+ if (row >= r)
+ {
+ row--;
+ }
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Flags the formula as invalid
+ * Does nothing here
+ */
+ void handleImportedCellReferences()
+ {
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/CellReference3d.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/CellReference3d.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/CellReference3d.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,329 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Logger;
+
+import jxl.Cell;
+
+import jxl.biff.CellReferenceHelper;
+import jxl.biff.IntegerHelper;
+
+/**
+ * A 3d cell reference in a formula
+ */
+class CellReference3d extends Operand implements ParsedThing
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(CellReference3d.class);
+
+ /**
+ * Indicates whether the column reference is relative or absolute
+ */
+ private boolean columnRelative;
+
+ /**
+ * Indicates whether the row reference is relative or absolute
+ */
+ private boolean rowRelative;
+
+ /**
+ * The column reference
+ */
+ private int column;
+
+ /**
+ * The row reference
+ */
+ private int row;
+
+ /**
+ * The cell containing the formula. Stored in order to determine
+ * relative cell values
+ */
+ private Cell relativeTo;
+
+ /**
+ * The sheet which the reference is present on
+ */
+ private int sheet;
+
+ /**
+ * A handle to the container of the external sheets ie. the workbook
+ */
+ private ExternalSheet workbook;
+
+ /**
+ * Constructor
+ *
+ * @param rt the cell containing the formula
+ * @param w the list of external sheets
+ */
+ public CellReference3d(Cell rt, ExternalSheet w)
+ {
+ relativeTo = rt;
+ workbook = w;
+ }
+
+ /**
+ * Constructs this object from a string
+ *
+ * @param s the string
+ * @param w the external sheet
+ * @exception FormulaException
+ */
+ public CellReference3d(String s, ExternalSheet w) throws FormulaException
+ {
+ workbook = w;
+ columnRelative = true;
+ rowRelative = true;
+
+ // Get the cell details
+ int sep = s.indexOf('!');
+ String cellString = s.substring(sep + 1);
+ column = CellReferenceHelper.getColumn(cellString);
+ row = CellReferenceHelper.getRow(cellString);
+
+ // Get the sheet index
+ String sheetName = s.substring(0, sep);
+
+ // Remove single quotes, if they exist
+ if (sheetName.charAt(0) == '\'' &&
+ sheetName.charAt(sheetName.length() - 1) == '\'')
+ {
+ sheetName = sheetName.substring(1, sheetName.length() - 1);
+ }
+ sheet = w.getExternalSheetIndex(sheetName);
+
+ if (sheet < 0)
+ {
+ throw new FormulaException(FormulaException.SHEET_REF_NOT_FOUND,
+ sheetName);
+ }
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ sheet = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ row = IntegerHelper.getInt(data[pos + 2], data[pos + 3]);
+ int columnMask = IntegerHelper.getInt(data[pos + 4], data[pos + 5]);
+ column = columnMask & 0x00ff;
+ columnRelative = ((columnMask & 0x4000) != 0);
+ rowRelative = ((columnMask & 0x8000) != 0);
+
+ return 6;
+ }
+
+ /**
+ * Accessor for the column
+ *
+ * @return the column number
+ */
+ public int getColumn()
+ {
+ return column;
+ }
+
+ /**
+ * Accessor for the row
+ *
+ * @return the row number
+ */
+ public int getRow()
+ {
+ return row;
+ }
+
+ /**
+ * Gets the string version of this cell reference
+ *
+ * @param buf the buffer to append to
+ */
+ public void getString(StringBuffer buf)
+ {
+ CellReferenceHelper.getCellReference(sheet, column, !columnRelative,
+ row, !rowRelative,
+ workbook, buf);
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[7];
+ data[0] = Token.REF3D.getCode();
+
+ IntegerHelper.getTwoBytes(sheet, data, 1);
+ IntegerHelper.getTwoBytes(row, data, 3);
+
+ int grcol = column;
+
+ // Set the row/column relative bits if applicable
+ if (rowRelative)
+ {
+ grcol |= 0x8000;
+ }
+
+ if (columnRelative)
+ {
+ grcol |= 0x4000;
+ }
+
+ IntegerHelper.getTwoBytes(grcol, data, 5);
+
+ return data;
+ }
+
+ /**
+ * Adjusts all the relative cell references in this formula by the
+ * amount specified. Used when copying formulas
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ if (columnRelative)
+ {
+ column += colAdjust;
+ }
+
+ if (rowRelative)
+ {
+ row += rowAdjust;
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ if (sheetIndex != sheet)
+ {
+ return;
+ }
+
+ if (column >= col)
+ {
+ column++;
+ }
+ }
+
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ if (sheetIndex != sheet)
+ {
+ return;
+ }
+
+ if (column >= col)
+ {
+ column--;
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was inserted
+ * @param r the row number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowInserted(int sheetIndex, int r, boolean currentSheet)
+ {
+ if (sheetIndex != sheet)
+ {
+ return;
+ }
+
+ if (row >= r)
+ {
+ row++;
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was removed
+ * @param r the row number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowRemoved(int sheetIndex, int r, boolean currentSheet)
+ {
+ if (sheetIndex != sheet)
+ {
+ return;
+ }
+
+ if (row >= r)
+ {
+ row--;
+ }
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Flags the formula as invalid
+ */
+ void handleImportedCellReferences()
+ {
+ setInvalid();
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/CellReferenceError.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/CellReferenceError.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/CellReferenceError.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,88 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Logger;
+
+/**
+ * An cell reference error which occurs in a formula
+ */
+class CellReferenceError extends Operand implements ParsedThing
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(CellReferenceError.class);
+
+ /**
+ * Constructor
+ */
+ public CellReferenceError()
+ {
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ // the data is unused - just return the four bytes
+
+ return 4;
+ }
+
+ /**
+ * Gets the cell reference as a string for this item
+ *
+ * @param buf the string buffer to populate
+ */
+ public void getString(StringBuffer buf)
+ {
+ buf.append(FormulaErrorCode.REF.getDescription());
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[5];
+ data[0] = Token.REFERR.getCode();
+
+ // bytes 1-5 are unused
+
+ return data;
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing
+ */
+ void handleImportedCellReferences()
+ {
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/CloseParentheses.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/CloseParentheses.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/CloseParentheses.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,33 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * The close of parentheses token
+ */
+class CloseParentheses extends StringParseItem
+{
+ /**
+ * Constructor
+ */
+ public CloseParentheses()
+ {
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/ColumnRange.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/ColumnRange.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/ColumnRange.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,85 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.biff.CellReferenceHelper;
+
+/**
+ * A class to hold range information across two entire columns
+ */
+class ColumnRange extends Area
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(ColumnRange.class);
+
+ /**
+ * Constructor
+ */
+ ColumnRange()
+ {
+ super();
+ }
+
+ /**
+ * Constructor invoked when parsing a string formula
+ *
+ * @param s the string to parse
+ */
+ ColumnRange(String s)
+ {
+ int seppos = s.indexOf(":");
+ Assert.verify(seppos != -1);
+ String startcell = s.substring(0, seppos);
+ String endcell = s.substring(seppos + 1);
+
+ int columnFirst = CellReferenceHelper.getColumn(startcell);
+ int rowFirst = 0;
+ int columnLast = CellReferenceHelper.getColumn(endcell);
+ int rowLast = 0xffff;
+
+ boolean columnFirstRelative =
+ CellReferenceHelper.isColumnRelative(startcell);
+ boolean rowFirstRelative = false;
+ boolean columnLastRelative = CellReferenceHelper.isColumnRelative(endcell);
+ boolean rowLastRelative = false;
+
+ setRangeData(columnFirst, columnLast,
+ rowFirst, rowLast,
+ columnFirstRelative, columnLastRelative,
+ rowFirstRelative, rowLastRelative);
+ }
+
+ /**
+ * Gets the string representation of this item
+ *
+ * @param buf the string buffer
+ */
+ public void getString(StringBuffer buf)
+ {
+ CellReferenceHelper.getColumnReference(getFirstColumn(), buf);
+ buf.append(':');
+ CellReferenceHelper.getColumnReference(getLastColumn(), buf);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/ColumnRange3d.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/ColumnRange3d.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/ColumnRange3d.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,129 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.biff.CellReferenceHelper;
+
+/**
+ * A nested class to hold range information
+ */
+class ColumnRange3d extends Area3d
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(ColumnRange3d.class);
+
+ /**
+ * A handle to the workbook
+ */
+ private ExternalSheet workbook;
+
+ /**
+ * The sheet number
+ */
+ private int sheet;
+
+ /**
+ * Constructor
+ *
+ * @param es the external sheet
+ */
+ ColumnRange3d(ExternalSheet es)
+ {
+ super(es);
+ workbook = es;
+ }
+
+ /**
+ * Constructor invoked when parsing a string formula
+ *
+ * @param s the string to parse
+ * @param es the external sheet
+ * @exception FormulaException
+ */
+ ColumnRange3d(String s, ExternalSheet es) throws FormulaException
+ {
+ super(es);
+ workbook = es;
+ int seppos = s.lastIndexOf(":");
+ Assert.verify(seppos != -1);
+ String startcell = s.substring(0, seppos);
+ String endcell = s.substring(seppos + 1);
+
+ // Get the the start cell details
+ int sep = s.indexOf('!');
+ String cellString = s.substring(sep + 1, seppos);
+ int columnFirst = CellReferenceHelper.getColumn(cellString);
+ int rowFirst = 0;
+
+ // Get the sheet index
+ String sheetName = s.substring(0, sep);
+ int sheetNamePos = sheetName.lastIndexOf(']');
+
+ // Remove single quotes, if they exist
+ if (sheetName.charAt(0) == '\'' &&
+ sheetName.charAt(sheetName.length() - 1) == '\'')
+ {
+ sheetName = sheetName.substring(1, sheetName.length() - 1);
+ }
+
+ sheet = es.getExternalSheetIndex(sheetName);
+
+ if (sheet < 0)
+ {
+ throw new FormulaException(FormulaException.SHEET_REF_NOT_FOUND,
+ sheetName);
+ }
+
+ // Get the last cell index
+ int columnLast = CellReferenceHelper.getColumn(endcell);
+ int rowLast = 0xffff;
+
+ boolean columnFirstRelative = true;
+ boolean rowFirstRelative = true;
+ boolean columnLastRelative = true;
+ boolean rowLastRelative = true;
+
+ setRangeData(sheet, columnFirst, columnLast, rowFirst, rowLast,
+ columnFirstRelative, rowFirstRelative,
+ columnLastRelative, rowLastRelative);
+ }
+
+ /**
+ * Gets the string representation of this column range
+ *
+ * @param buf the string buffer to append to
+ */
+ public void getString(StringBuffer buf)
+ {
+ buf.append('\'');
+ buf.append(workbook.getExternalSheetName(sheet));
+ buf.append('\'');
+ buf.append('!');
+
+ CellReferenceHelper.getColumnReference(getFirstColumn(), buf);
+ buf.append(':');
+ CellReferenceHelper.getColumnReference(getLastColumn(), buf);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Concatenate.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Concatenate.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Concatenate.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,64 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A cell reference in a formula
+ */
+class Concatenate extends BinaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public Concatenate()
+ {
+ }
+
+ /**
+ * Gets the string representation of this symbol
+ *
+ * @return the concatenation symbol
+ */
+ public String getSymbol()
+ {
+ return "&";
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.CONCAT;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 3;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Divide.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Divide.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Divide.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,65 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A cell reference in a formula
+ */
+class Divide extends BinaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public Divide()
+ {
+ }
+
+ /**
+ * Gets the string representation of this symbol
+ *
+ * @return the symbol
+ */
+ public String getSymbol()
+ {
+ return "/";
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.DIVIDE;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 3;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/DoubleValue.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/DoubleValue.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/DoubleValue.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,124 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Logger;
+
+import jxl.biff.DoubleHelper;
+
+/**
+ * A cell reference in a formula
+ */
+class DoubleValue extends NumberValue implements ParsedThing
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(DoubleValue.class);
+
+ /**
+ * The value of this double in the formula
+ */
+ private double value;
+
+ /**
+ * Constructor
+ */
+ public DoubleValue()
+ {
+ }
+
+ /**
+ * Constructor - invoked when writing an integer value that's out
+ * of range for a short
+ *
+ * @param v the double value
+ */
+ DoubleValue(double v)
+ {
+ value = v;
+ }
+
+ /**
+ * Constructor for a double value when reading from a string
+ *
+ * @param s the string representation of this token
+ */
+ public DoubleValue(String s)
+ {
+ try
+ {
+ value = Double.parseDouble(s);
+ }
+ catch (NumberFormatException e)
+ {
+ logger.warn(e, e);
+ value = 0;
+ }
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ value = DoubleHelper.getIEEEDouble(data, pos);
+
+ return 8;
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[9];
+ data[0] = Token.DOUBLE.getCode();
+
+ DoubleHelper.getIEEEBytes(value, data, 1);
+
+ return data;
+ }
+
+ /**
+ * The double value
+ *
+ * @return the value
+ */
+ public double getValue()
+ {
+ return value;
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing
+ */
+ void handleImportedCellReferences()
+ {
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Equal.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Equal.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Equal.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,66 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A cell reference in a formula
+ */
+class Equal extends BinaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public Equal()
+ {
+ }
+
+ /**
+ * Gets the string for this symbol
+ *
+ * @return the symbol string
+ */
+ public String getSymbol()
+ {
+ return "=";
+ }
+
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.EQUAL;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 5;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/ErrorConstant.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/ErrorConstant.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/ErrorConstant.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,98 @@
+/*********************************************************************
+*
+* Copyright (C) 2006 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import jxl.biff.IntegerHelper;
+
+/**
+ * An error constant
+ */
+class ErrorConstant extends Operand implements ParsedThing
+{
+ /**
+ * The error
+ */
+ private FormulaErrorCode error;
+
+ /**
+ * Constructor
+ */
+ public ErrorConstant()
+ {
+ }
+
+ /**
+ * Constructor
+ *
+ * @param s the error constant
+ */
+ public ErrorConstant(String s)
+ {
+ error = FormulaErrorCode.getErrorCode(s);
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ int code = data[pos];
+ error = FormulaErrorCode.getErrorCode(code);
+ return 1;
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[2];
+ data[0] = Token.ERR.getCode();
+ data[1] = (byte) error.getCode();
+
+ return data;
+ }
+
+ /**
+ * Abstract method implementation to get the string equivalent of this
+ * token
+ *
+ * @param buf the string to append to
+ */
+ public void getString(StringBuffer buf)
+ {
+ buf.append(error.getDescription());
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing
+ */
+ void handleImportedCellReferences()
+ {
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/ExternalSheet.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/ExternalSheet.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/ExternalSheet.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,77 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import jxl.read.biff.BOFRecord;
+
+/**
+ * Interface which exposes the methods needed by formulas
+ * to access external sheet records
+ */
+public interface ExternalSheet
+{
+ /**
+ * Gets the name of the external sheet specified by the index
+ *
+ * @param index the external sheet index
+ * @return the name of the external sheet
+ */
+ public String getExternalSheetName(int index);
+
+ /**
+ * Gets the index of the first external sheet for the name
+ *
+ * @param sheetName the name of the external sheet
+ * @return the index of the external sheet with the specified name
+ */
+ public int getExternalSheetIndex(String sheetName);
+
+ /**
+ * Gets the index of the first external sheet for the name
+ *
+ * @param index the external sheet index
+ * @return the sheet index of the external sheet index
+ */
+ public int getExternalSheetIndex(int index);
+
+ /**
+ * Gets the index of the last external sheet for the name
+ *
+ * @param sheetName the name of the external sheet
+ * @return the index of the external sheet with the specified name
+ */
+ public int getLastExternalSheetIndex(String sheetName);
+
+ /**
+ * Gets the index of the first external sheet for the name
+ *
+ * @param index the external sheet index
+ * @return the sheet index of the external sheet index
+ */
+ public int getLastExternalSheetIndex(int index);
+
+ /**
+ * Parsing of formulas is only supported for a subset of the available
+ * biff version, so we need to test to see if this version is acceptable
+ *
+ * @return the BOF record
+ */
+ public BOFRecord getWorkbookBof();
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/FormulaErrorCode.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/FormulaErrorCode.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/FormulaErrorCode.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,142 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * Enumeration for formula error codes
+ */
+public class FormulaErrorCode
+{
+ /**
+ * The error code
+ */
+ private int errorCode;
+
+ /**
+ * The description
+ */
+ private String description;
+
+ /**
+ * The list of error codes
+ */
+ private static FormulaErrorCode[] codes = new FormulaErrorCode[0];
+
+ /**
+ * Constructor
+ *
+ * @param code the code
+ * @param desc the description
+ */
+ FormulaErrorCode(int code, String desc)
+ {
+ errorCode = code;
+ description = desc;
+ FormulaErrorCode[] newcodes = new FormulaErrorCode[codes.length + 1];
+ System.arraycopy(codes, 0, newcodes, 0, codes.length);
+ newcodes[codes.length] = this;
+ codes = newcodes;
+ }
+
+ /**
+ * Accessor for the code
+ *
+ * @return the code
+ */
+ public int getCode()
+ {
+ return errorCode;
+ }
+
+ /**
+ * Accessor for the description
+ *
+ * @return the description
+ */
+ public String getDescription()
+ {
+ return description;
+ }
+
+ /**
+ * Gets the error type given just the code
+ *
+ * @param code the code to lookup
+ * @return the error type
+ */
+ public static FormulaErrorCode getErrorCode(int code)
+ {
+ boolean found = false;
+ FormulaErrorCode ec = UNKNOWN;
+ for (int i = 0; i < codes.length && !found; i++)
+ {
+ if (codes[i].errorCode == code)
+ {
+ found = true;
+ ec = codes[i];
+ }
+ }
+ return ec;
+ }
+
+ /**
+ * Gets the error type given the string value
+ *
+ * @param code the code to lookup
+ * @return the error type
+ */
+ public static FormulaErrorCode getErrorCode(String code)
+ {
+ boolean found = false;
+ FormulaErrorCode ec = UNKNOWN;
+
+ if (code == null || code.length() == 0)
+ {
+ return ec;
+ }
+
+ for (int i = 0; i < codes.length && !found; i++)
+ {
+ if (codes[i].description.equals(code))
+ {
+ found = true;
+ ec = codes[i];
+ }
+ }
+ return ec;
+ }
+
+ public static final FormulaErrorCode UNKNOWN =
+ new FormulaErrorCode(0xff, "?");
+ public static final FormulaErrorCode NULL =
+ new FormulaErrorCode(0x0, "#NULL!");
+ public static final FormulaErrorCode DIV0 =
+ new FormulaErrorCode(0x7, "#DIV/0!");
+ public static final FormulaErrorCode VALUE =
+ new FormulaErrorCode(0xf, "#VALUE!");
+ public static final FormulaErrorCode REF =
+ new FormulaErrorCode(0x17, "#REF!");
+ public static final FormulaErrorCode NAME =
+ new FormulaErrorCode(0x1d, "#NAME?");
+ public static final FormulaErrorCode NUM = new FormulaErrorCode(0x24,
+ "#NUM!");
+ public static final FormulaErrorCode NA = new FormulaErrorCode(0x2a,
+ "#N/A!");
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/FormulaException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/FormulaException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/FormulaException.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,127 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import jxl.JXLException;
+
+/**
+ * Exception thrown when parsing a formula
+ */
+public class FormulaException extends JXLException
+{
+ /**
+ * Inner class containing the message
+ */
+ private static class FormulaMessage
+ {
+ /**
+ * The message
+ */
+ private String message;
+
+ /**
+ * Constructs this exception with the specified message
+ *
+ * @param m the message
+ */
+ FormulaMessage(String m)
+ {
+ message = m;
+ }
+
+ /**
+ * Accessor for the message
+ *
+ * @return the message
+ */
+ public String getMessage()
+ {
+ return message;
+ }
+ }
+
+ /**
+ */
+ static final FormulaMessage UNRECOGNIZED_TOKEN =
+ new FormulaMessage("Unrecognized token");
+
+ /**
+ */
+ static final FormulaMessage UNRECOGNIZED_FUNCTION =
+ new FormulaMessage("Unrecognized function");
+
+ /**
+ */
+ public static final FormulaMessage BIFF8_SUPPORTED =
+ new FormulaMessage("Only biff8 formulas are supported");
+
+ /**
+ */
+ static final FormulaMessage LEXICAL_ERROR =
+ new FormulaMessage("Lexical error: ");
+
+ /**
+ */
+ static final FormulaMessage INCORRECT_ARGUMENTS =
+ new FormulaMessage("Incorrect arguments supplied to function");
+
+ /**
+ */
+ static final FormulaMessage SHEET_REF_NOT_FOUND =
+ new FormulaMessage("Could not find sheet");
+
+ /**
+ */
+ static final FormulaMessage CELL_NAME_NOT_FOUND =
+ new FormulaMessage("Could not find named cell");
+
+
+ /**
+ * Constructs this exception with the specified message
+ *
+ * @param m the message
+ */
+ public FormulaException(FormulaMessage m)
+ {
+ super(m.message);
+ }
+
+ /**
+ * Constructs this exception with the specified message
+ *
+ * @param m the message
+ * @param val the value
+ */
+ public FormulaException(FormulaMessage m, int val)
+ {
+ super(m.message + " " + val);
+ }
+
+ /**
+ * Constructs this exception with the specified message
+ *
+ * @param m the message
+ * @param val the value
+ */
+ public FormulaException(FormulaMessage m, String val)
+ {
+ super(m.message + " " + val);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/FormulaParser.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/FormulaParser.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/FormulaParser.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,205 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.Cell;
+import jxl.WorkbookSettings;
+import jxl.biff.WorkbookMethods;
+
+/**
+ * Parses the formula passed in (either as parsed strings or as a string)
+ * into a tree of operators and operands
+ */
+public class FormulaParser
+{
+ /**
+ * The logger
+ */
+ private static final Logger logger = Logger.getLogger(FormulaParser.class);
+
+ /**
+ * The formula parser. The object implementing this interface will either
+ * parse tokens or strings
+ */
+ private Parser parser;
+
+ /**
+ * Constructor which creates the parse tree out of tokens
+ *
+ * @param tokens the list of parsed tokens
+ * @param rt the cell containing the formula
+ * @param es a handle to the external sheet
+ * @param nt a handle to the name table
+ * @param ws the workbook settings
+ * @exception FormulaException
+ */
+ public FormulaParser(byte[] tokens,
+ Cell rt,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ WorkbookSettings ws)
+ throws FormulaException
+ {
+ // A null workbook bof means that it is a writable workbook and therefore
+ // must be biff8
+ if (es.getWorkbookBof() != null &&
+ !es.getWorkbookBof().isBiff8())
+ {
+ throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
+ }
+ Assert.verify(nt != null);
+ parser = new TokenFormulaParser(tokens, rt, es, nt, ws);
+ }
+
+ /**
+ * Constructor which creates the parse tree out of the string
+ *
+ * @param form the formula string
+ * @param es the external sheet handle
+ * @param nt the name table
+ * @param ws the workbook settings
+ */
+ public FormulaParser(String form,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ WorkbookSettings ws)
+ {
+ parser = new StringFormulaParser(form, es, nt, ws);
+ }
+
+
+ /**
+ * Adjusts all the relative cell references in this formula by the
+ * amount specified. Used when copying formulas
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ parser.adjustRelativeCellReferences(colAdjust, rowAdjust);
+ }
+
+ /**
+ * Parses the formula into a parse tree
+ *
+ * @exception FormulaException
+ */
+ public void parse() throws FormulaException
+ {
+ parser.parse();
+ }
+
+ /**
+ * Gets the formula as a string
+ *
+ * @return the formula as a string
+ * @exception FormulaException
+ */
+ public String getFormula() throws FormulaException
+ {
+ return parser.getFormula();
+ }
+
+ /**
+ * Gets the bytes for the formula. This takes into account any
+ * token mapping necessary because of shared formulas
+ *
+ * @return the bytes in RPN
+ */
+ public byte[] getBytes()
+ {
+ return parser.getBytes();
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ parser.columnInserted(sheetIndex, col, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ parser.columnRemoved(sheetIndex, col, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param row the row number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void rowInserted(int sheetIndex, int row, boolean currentSheet)
+ {
+ parser.rowInserted(sheetIndex, row, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param row the row number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void rowRemoved(int sheetIndex, int row, boolean currentSheet)
+ {
+ parser.rowRemoved(sheetIndex, row, currentSheet);
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ *
+ * @return TRUE if the formula is valid import, FALSE otherwise
+ */
+ public boolean handleImportedCellReferences()
+ {
+ return parser.handleImportedCellReferences();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Function.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Function.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Function.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,716 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+
+/**
+ * An enumeration detailing the Excel function codes
+ */
+final class Function
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(Function.class);
+
+ /**
+ * The code which applies to this function
+ */
+ private final int code;
+
+ /**
+ * The property name of this function
+ */
+ private final String name;
+
+ /**
+ * The number of args this function expects
+ */
+ private final int numArgs;
+
+
+ /**
+ * All available functions. This attribute is package protected in order
+ * to enable the FunctionNames to initialize
+ */
+ private static Function[] functions = new Function[0];
+
+ /**
+ * Constructor
+ * Sets the token value and adds this token to the array of all token
+ *
+ * @param v the biff code for the token
+ * @param s the string
+ * @param a the number of arguments
+ */
+ private Function(int v, String s, int a)
+ {
+ code = v;
+ name = s;
+ numArgs = a;
+
+ // Grow the array
+ Function[] newarray = new Function[functions.length + 1];
+ System.arraycopy(functions, 0, newarray, 0, functions.length);
+ newarray[functions.length] = this;
+ functions = newarray;
+ }
+
+ /**
+ * Standard hash code method
+ *
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ return code;
+ }
+
+ /**
+ * Gets the function code - used when generating token data
+ *
+ * @return the code
+ */
+ int getCode()
+ {
+ return code;
+ }
+
+ /**
+ * Gets the property name. Used by the FunctionNames object when initializing
+ * the locale specific names
+ *
+ * @return the property name for this function
+ */
+ String getPropertyName()
+ {
+ return name;
+ }
+
+ /**
+ * Gets the function name
+ * @param ws the workbook settings
+ * @return the function name
+ */
+ String getName(WorkbookSettings ws)
+ {
+ FunctionNames fn = ws.getFunctionNames();
+ return fn.getName(this);
+ }
+
+ /**
+ * Gets the number of arguments for this function
+ *
+ * @return the number of arguments
+ */
+ int getNumArgs()
+ {
+ return numArgs;
+ }
+
+ /**
+ * Gets the type object from its integer value
+ *
+ * @param v the function value
+ * @return the function
+ */
+ public static Function getFunction(int v)
+ {
+ Function f = null;
+
+ for (int i = 0; i < functions.length; i++)
+ {
+ if (functions[i].code == v)
+ {
+ f = functions[i];
+ break;
+ }
+ }
+
+ return f != null ? f : UNKNOWN;
+ }
+
+ /**
+ * Gets the type object from its string value. Used when parsing strings
+ *
+ * @param v the function name
+ * @param ws the workbook settings
+ * @return the function
+ */
+ public static Function getFunction(String v, WorkbookSettings ws)
+ {
+ FunctionNames fn = ws.getFunctionNames();
+ Function f = fn.getFunction(v);
+ return f != null ? f : UNKNOWN;
+ }
+
+ /**
+ * Accessor for all the functions, used by the internationalization
+ * work around
+ *
+ * @return all the functions
+ */
+ static Function[] getFunctions()
+ {
+ return functions;
+ }
+
+ // The functions
+
+ public static final Function COUNT =
+ new Function(0x0, "count", 0xff);
+ public static final Function ATTRIBUTE = new Function(0x1, "", 0xff);
+ public static final Function ISNA =
+ new Function(0x2, "isna", 1);
+ public static final Function ISERROR =
+ new Function(0x3, "iserror", 1);
+ public static final Function SUM =
+ new Function(0x4, "sum", 0xff);
+ public static final Function AVERAGE =
+ new Function(0x5, "average", 0xff);
+ public static final Function MIN =
+ new Function(0x6, "min", 0xff);
+ public static final Function MAX =
+ new Function(0x7, "max", 0xff);
+ public static final Function ROW =
+ new Function(0x8, "row", 0xff);
+ public static final Function COLUMN =
+ new Function(0x9, "column", 0xff);
+ public static final Function NA =
+ new Function(0xa, "na", 0);
+ public static final Function NPV =
+ new Function(0xb, "npv", 0xff);
+ public static final Function STDEV =
+ new Function(0xc, "stdev", 0xff);
+ public static final Function DOLLAR =
+ new Function(0xd, "dollar", 2);
+ public static final Function FIXED =
+ new Function(0xe, "fixed", 0xff);
+ public static final Function SIN =
+ new Function(0xf, "sin", 1);
+ public static final Function COS =
+ new Function(0x10, "cos", 1);
+ public static final Function TAN =
+ new Function(0x11, "tan", 1);
+ public static final Function ATAN =
+ new Function(0x12, "atan", 1);
+ public static final Function PI =
+ new Function(0x13, "pi", 0);
+ public static final Function SQRT =
+ new Function(0x14, "sqrt", 1);
+ public static final Function EXP =
+ new Function(0x15, "exp", 1);
+ public static final Function LN =
+ new Function(0x16, "ln", 1);
+ public static final Function LOG10 =
+ new Function(0x17, "log10", 1);
+ public static final Function ABS =
+ new Function(0x18, "abs", 1);
+ public static final Function INT =
+ new Function(0x19, "int", 1);
+ public static final Function SIGN =
+ new Function(0x1a, "sign", 1);
+ public static final Function ROUND =
+ new Function(0x1b, "round", 2);
+ public static final Function LOOKUP =
+ new Function(0x1c, "lookup", 2);
+ public static final Function INDEX =
+ new Function(0x1d, "index", 3);
+ public static final Function REPT = new Function(0x1e, "rept", 2);
+ public static final Function MID =
+ new Function(0x1f, "mid", 3);
+ public static final Function LEN =
+ new Function(0x20, "len", 1);
+ public static final Function VALUE =
+ new Function(0x21, "value", 1);
+ public static final Function TRUE =
+ new Function(0x22, "true", 0);
+ public static final Function FALSE =
+ new Function(0x23, "false", 0);
+ public static final Function AND =
+ new Function(0x24, "and", 0xff);
+ public static final Function OR =
+ new Function(0x25, "or", 0xff);
+ public static final Function NOT =
+ new Function(0x26, "not", 1);
+ public static final Function MOD =
+ new Function(0x27, "mod", 2);
+ public static final Function DCOUNT =
+ new Function(0x28, "dcount", 3);
+ public static final Function DSUM =
+ new Function(0x29, "dsum", 3);
+ public static final Function DAVERAGE =
+ new Function(0x2a, "daverage", 3);
+ public static final Function DMIN =
+ new Function(0x2b, "dmin", 3);
+ public static final Function DMAX =
+ new Function(0x2c, "dmax", 3);
+ public static final Function DSTDEV =
+ new Function(0x2d, "dstdev", 3);
+ public static final Function VAR =
+ new Function(0x2e, "var", 0xff);
+ public static final Function DVAR =
+ new Function(0x2f, "dvar", 3);
+ public static final Function TEXT =
+ new Function(0x30, "text", 2);
+ public static final Function LINEST =
+ new Function(0x31, "linest", 0xff);
+ public static final Function TREND =
+ new Function(0x32, "trend", 0xff);
+ public static final Function LOGEST =
+ new Function(0x33, "logest", 0xff);
+ public static final Function GROWTH =
+ new Function(0x34, "growth", 0xff);
+ //public static final Function GOTO = new Function(0x35, "GOTO",);
+ //public static final Function HALT = new Function(0x36, "HALT",);
+ public static final Function PV =
+ new Function(0x38, "pv", 0xff);
+ public static final Function FV =
+ new Function(0x39, "fv", 0xff);
+ public static final Function NPER =
+ new Function(0x3a, "nper", 0xff);
+ public static final Function PMT =
+ new Function(0x3b, "pmt", 0xff);
+ public static final Function RATE =
+ new Function(0x3c, "rate", 0xff);
+ //public static final Function MIRR = new Function(0x3d, "MIRR",);
+ //public static final Function IRR = new Function(0x3e, "IRR",);
+ public static final Function RAND =
+ new Function(0x3f, "rand", 0);
+ public static final Function MATCH =
+ new Function(0x40, "match", 3);
+ public static final Function DATE =
+ new Function(0x41, "date", 3);
+ public static final Function TIME =
+ new Function(0x42, "time", 3);
+ public static final Function DAY =
+ new Function(0x43, "day", 1);
+ public static final Function MONTH =
+ new Function(0x44, "month", 1);
+ public static final Function YEAR =
+ new Function(0x45, "year", 1);
+ public static final Function WEEKDAY =
+ new Function(0x46, "weekday", 2);
+ public static final Function HOUR =
+ new Function(0x47, "hour", 1);
+ public static final Function MINUTE =
+ new Function(0x48, "minute", 1);
+ public static final Function SECOND =
+ new Function(0x49, "second", 1);
+ public static final Function NOW =
+ new Function(0x4a, "now", 0);
+ public static final Function AREAS =
+ new Function(0x4b, "areas", 0xff);
+ public static final Function ROWS =
+ new Function(0x4c, "rows", 1);
+ public static final Function COLUMNS =
+ new Function(0x4d, "columns", 0xff);
+ public static final Function OFFSET =
+ new Function(0x4e, "offset", 0xff);
+ //public static final Function ABSREF = new Function(0x4f, "ABSREF",);
+ //public static final Function RELREF = new Function(0x50, "RELREF",);
+ //public static final Function ARGUMENT = new Function(0x51,"ARGUMENT",);
+ public static final Function SEARCH = new Function(0x52, "search", 0xff);
+ public static final Function TRANSPOSE =
+ new Function(0x53, "transpose", 0xff);
+ public static final Function ERROR =
+ new Function(0x54, "error", 1);
+ //public static final Function STEP = new Function(0x55, "STEP",);
+ public static final Function TYPE =
+ new Function(0x56, "type", 1);
+ //public static final Function ECHO = new Function(0x57, "ECHO",);
+ //public static final Function SETNAME = new Function(0x58, "SETNAME",);
+ //public static final Function CALLER = new Function(0x59, "CALLER",);
+ //public static final Function DEREF = new Function(0x5a, "DEREF",);
+ //public static final Function WINDOWS = new Function(0x5b, "WINDOWS",);
+ //public static final Function SERIES = new Function(0x5c, "SERIES",);
+ //public static final Function DOCUMENTS = new Function(0x5d,"DOCUMENTS",);
+ //public static final Function ACTIVECELL = new Function(0x5e,"ACTIVECELL",);
+ //public static final Function SELECTION = new Function(0x5f,"SELECTION",);
+ //public static final Function RESULT = new Function(0x60, "RESULT",);
+ public static final Function ATAN2 =
+ new Function(0x61, "atan2", 1);
+ public static final Function ASIN =
+ new Function(0x62, "asin", 1);
+ public static final Function ACOS =
+ new Function(0x63, "acos", 1);
+ public static final Function CHOOSE =
+ new Function(0x64, "choose", 0xff);
+ public static final Function HLOOKUP =
+ new Function(0x65, "hlookup", 0xff);
+ public static final Function VLOOKUP =
+ new Function(0x66, "vlookup", 0xff);
+ //public static final Function LINKS = new Function(0x67, "LINKS",);
+ //public static final Function INPUT = new Function(0x68, "INPUT",);
+ public static final Function ISREF =
+ new Function(0x69, "isref", 1);
+ //public static final Function GETFORMULA = new Function(0x6a,"GETFORMULA",);
+ //public static final Function GETNAME = new Function(0x6b, "GETNAME",);
+ //public static final Function SETVALUE = new Function(0x6c,"SETVALUE",);
+ public static final Function LOG =
+ new Function(0x6d, "log", 0xff);
+ //public static final Function EXEC = new Function(0x6e, "EXEC",);
+ public static final Function CHAR =
+ new Function(0x6f, "char", 1);
+ public static final Function LOWER =
+ new Function(0x70, "lower", 1);
+ public static final Function UPPER =
+ new Function(0x71, "upper", 1);
+ public static final Function PROPER =
+ new Function(0x72, "proper", 1);
+ public static final Function LEFT =
+ new Function(0x73, "left", 0xff);
+ public static final Function RIGHT =
+ new Function(0x74, "right", 0xff);
+ public static final Function EXACT =
+ new Function(0x75, "exact", 2);
+ public static final Function TRIM =
+ new Function(0x76, "trim", 1);
+ public static final Function REPLACE =
+ new Function(0x77, "replace", 4);
+ public static final Function SUBSTITUTE =
+ new Function(0x78, "substitute", 0xff);
+ public static final Function CODE =
+ new Function(0x79, "code", 1);
+ //public static final Function NAMES = new Function(0x7a, "NAMES",);
+ //public static final Function DIRECTORY = new Function(0x7b,"DIRECTORY",);
+ public static final Function FIND =
+ new Function(0x7c, "find", 0xff);
+ public static final Function CELL =
+ new Function(0x7d, "cell", 2);
+ public static final Function ISERR =
+ new Function(0x7e, "iserr", 1);
+ public static final Function ISTEXT =
+ new Function(0x7f, "istext", 1);
+ public static final Function ISNUMBER =
+ new Function(0x80, "isnumber", 1);
+ public static final Function ISBLANK =
+ new Function(0x81, "isblank", 1);
+ public static final Function T =
+ new Function(0x82, "t", 1);
+ public static final Function N =
+ new Function(0x83, "n", 1);
+ //public static final Function FOPEN = new Function(0x84, "FOPEN",);
+ //public static final Function FCLOSE = new Function(0x85, "FCLOSE",);
+ //public static final Function FSIZE = new Function(0x86, "FSIZE",);
+ //public static final Function FREADLN = new Function(0x87, "FREADLN",);
+ //public static final Function FREAD = new Function(0x88, "FREAD",);
+ //public static final Function FWRITELN = new Function(0x89,"FWRITELN",);
+ //public static final Function FWRITE = new Function(0x8a, "FWRITE",);
+ //public static final Function FPOS = new Function(0x8b, "FPOS",);
+ public static final Function DATEVALUE =
+ new Function(0x8c, "datevalue", 1);
+ public static final Function TIMEVALUE =
+ new Function(0x8d, "timevalue", 1);
+ public static final Function SLN =
+ new Function(0x8e, "sln", 3);
+ public static final Function SYD =
+ new Function(0x8f, "syd", 3);
+ public static final Function DDB =
+ new Function(0x90, "ddb", 0xff);
+ //public static final Function GETDEF = new Function(0x91, "GETDEF",);
+ //public static final Function REFTEXT = new Function(0x92, "REFTEXT",);
+ //public static final Function TEXTREF = new Function(0x93, "TEXTREF",);
+ public static final Function INDIRECT =
+ new Function(0x94, "indirect", 0xff);
+ //public static final Function REGISTER = new Function(0x95,"REGISTER",);
+ //public static final Function CALL = new Function(0x96, "CALL",);
+ //public static final Function ADDBAR = new Function(0x97, "ADDBAR",);
+ //public static final Function ADDMENU = new Function(0x98, "ADDMENU",);
+ //public static final Function ADDCOMMAND =
+ // new Function(0x99,"ADDCOMMAND",);
+ //public static final Function ENABLECOMMAND =
+ // new Function(0x9a,"ENABLECOMMAND",);
+ //public static final Function CHECKCOMMAND =
+ // new Function(0x9b,"CHECKCOMMAND",);
+ //public static final Function RENAMECOMMAND =
+ // new Function(0x9c,"RENAMECOMMAND",);
+ //public static final Function SHOWBAR = new Function(0x9d, "SHOWBAR",);
+ //public static final Function DELETEMENU =
+ // new Function(0x9e,"DELETEMENU",);
+ //public static final Function DELETECOMMAND =
+ // new Function(0x9f,"DELETECOMMAND",);
+ //public static final Function GETCHARTITEM =
+ // new Function(0xa0,"GETCHARTITEM",);
+ //public static final Function DIALOGBOX = new Function(0xa1,"DIALOGBOX",);
+ public static final Function CLEAN =
+ new Function(0xa2, "clean", 1);
+ public static final Function MDETERM =
+ new Function(0xa3, "mdeterm", 0xff);
+ public static final Function MINVERSE =
+ new Function(0xa4, "minverse", 0xff);
+ public static final Function MMULT =
+ new Function(0xa5, "mmult", 0xff);
+ //public static final Function FILES = new Function(0xa6, "FILES",
+
+ public static final Function IPMT =
+ new Function(0xa7, "ipmt", 0xff);
+ public static final Function PPMT =
+ new Function(0xa8, "ppmt", 0xff);
+ public static final Function COUNTA =
+ new Function(0xa9, "counta", 0xff);
+ public static final Function PRODUCT =
+ new Function(0xb7, "product", 0xff);
+ public static final Function FACT =
+ new Function(0xb8, "fact", 1);
+ //public static final Function GETCELL = new Function(0xb9, "GETCELL",);
+ //public static final Function GETWORKSPACE =
+ // new Function(0xba,"GETWORKSPACE",);
+ //public static final Function GETWINDOW = new Function(0xbb,"GETWINDOW",);
+ //public static final Function GETDOCUMENT =
+ // new Function(0xbc,"GETDOCUMENT",);
+ public static final Function DPRODUCT =
+ new Function(0xbd, "dproduct", 3);
+ public static final Function ISNONTEXT =
+ new Function(0xbe, "isnontext", 1);
+ //public static final Function GETNOTE = new Function(0xbf, "GETNOTE",);
+ //public static final Function NOTE = new Function(0xc0, "NOTE",);
+ public static final Function STDEVP =
+ new Function(0xc1, "stdevp", 0xff);
+ public static final Function VARP =
+ new Function(0xc2, "varp", 0xff);
+ public static final Function DSTDEVP =
+ new Function(0xc3, "dstdevp", 0xff);
+ public static final Function DVARP =
+ new Function(0xc4, "dvarp", 0xff);
+ public static final Function TRUNC =
+ new Function(0xc5, "trunc", 0xff);
+ public static final Function ISLOGICAL =
+ new Function(0xc6, "islogical", 1);
+ public static final Function DCOUNTA =
+ new Function(0xc7, "dcounta", 0xff);
+ public static final Function FINDB =
+ new Function(0xcd, "findb", 0xff);
+ public static final Function SEARCHB =
+ new Function(0xce, "searchb", 3);
+ public static final Function REPLACEB =
+ new Function(0xcf, "replaceb", 4);
+ public static final Function LEFTB =
+ new Function(0xd0, "leftb", 0xff);
+ public static final Function RIGHTB =
+ new Function(0xd1, "rightb", 0xff);
+ public static final Function MIDB =
+ new Function(0xd2, "midb", 3);
+ public static final Function LENB =
+ new Function(0xd3, "lenb", 1);
+ public static final Function ROUNDUP =
+ new Function(0xd4, "roundup", 2);
+ public static final Function ROUNDDOWN =
+ new Function(0xd5, "rounddown", 2);
+ public static final Function RANK =
+ new Function(0xd8, "rank", 0xff);
+ public static final Function ADDRESS =
+ new Function(0xdb, "address", 0xff);
+ public static final Function AYS360 =
+ new Function(0xdc, "days360", 0xff);
+ public static final Function ODAY =
+ new Function(0xdd, "today", 0);
+ public static final Function VDB =
+ new Function(0xde, "vdb", 0xff);
+ public static final Function MEDIAN =
+ new Function(0xe3, "median", 0xff);
+ public static final Function SUMPRODUCT =
+ new Function(0xe4, "sumproduct", 0xff);
+ public static final Function SINH =
+ new Function(0xe5, "sinh", 1);
+ public static final Function COSH =
+ new Function(0xe6, "cosh", 1);
+ public static final Function TANH =
+ new Function(0xe7, "tanh", 1);
+ public static final Function ASINH =
+ new Function(0xe8, "asinh", 1);
+ public static final Function ACOSH =
+ new Function(0xe9, "acosh", 1);
+ public static final Function ATANH =
+ new Function(0xea, "atanh", 1);
+ public static final Function INFO =
+ new Function(0xf4, "info", 1);
+ public static final Function AVEDEV =
+ new Function(0x10d, "avedev", 0XFF);
+ public static final Function BETADIST =
+ new Function(0x10e, "betadist", 0XFF);
+ public static final Function GAMMALN =
+ new Function(0x10f, "gammaln", 1);
+ public static final Function BETAINV =
+ new Function(0x110, "betainv", 0XFF);
+ public static final Function BINOMDIST =
+ new Function(0x111, "binomdist", 4);
+ public static final Function CHIDIST =
+ new Function(0x112, "chidist", 2);
+ public static final Function CHIINV =
+ new Function(0x113, "chiinv", 2);
+ public static final Function COMBIN =
+ new Function(0x114, "combin", 2);
+ public static final Function CONFIDENCE =
+ new Function(0x115, "confidence", 3);
+ public static final Function CRITBINOM =
+ new Function(0x116, "critbinom", 3);
+ public static final Function EVEN =
+ new Function(0x117, "even", 1);
+ public static final Function EXPONDIST =
+ new Function(0x118, "expondist", 3);
+ public static final Function FDIST =
+ new Function(0x119, "fdist", 3);
+ public static final Function FINV =
+ new Function(0x11a, "finv", 3);
+ public static final Function FISHER =
+ new Function(0x11b, "fisher", 1);
+ public static final Function FISHERINV =
+ new Function(0x11c, "fisherinv", 1);
+ public static final Function FLOOR =
+ new Function(0x11d, "floor", 2);
+ public static final Function GAMMADIST =
+ new Function(0x11e, "gammadist", 4);
+ public static final Function GAMMAINV =
+ new Function(0x11f, "gammainv", 3);
+ public static final Function CEILING =
+ new Function(0x120, "ceiling", 2);
+ public static final Function HYPGEOMDIST =
+ new Function(0x121, "hypgeomdist", 4);
+ public static final Function LOGNORMDIST =
+ new Function(0x122, "lognormdist", 3);
+ public static final Function LOGINV =
+ new Function(0x123, "loginv", 3);
+ public static final Function NEGBINOMDIST =
+ new Function(0x124, "negbinomdist", 3);
+ public static final Function NORMDIST =
+ new Function(0x125, "normdist", 4);
+ public static final Function NORMSDIST =
+ new Function(0x126, "normsdist", 1);
+ public static final Function NORMINV =
+ new Function(0x127, "norminv", 3);
+ public static final Function NORMSINV =
+ new Function(0x128, "normsinv", 1);
+ public static final Function STANDARDIZE =
+ new Function(0x129, "standardize", 3);
+ public static final Function ODD =
+ new Function(0x12a, "odd", 1);
+ public static final Function PERMUT =
+ new Function(0x12b, "permut", 2);
+ public static final Function POISSON =
+ new Function(0x12c, "poisson", 3);
+ public static final Function TDIST =
+ new Function(0x12d, "tdist", 3);
+ public static final Function WEIBULL =
+ new Function(0x12e, "weibull", 4);
+ public static final Function SUMXMY2 =
+ new Function(303, "sumxmy2", 0xff);
+ public static final Function SUMX2MY2 =
+ new Function(304, "sumx2my2", 0xff);
+ public static final Function SUMX2PY2 =
+ new Function(305, "sumx2py2", 0xff);
+ public static final Function CHITEST =
+ new Function(0x132, "chitest", 0xff);
+ public static final Function CORREL =
+ new Function(0x133, "correl", 0xff);
+ public static final Function COVAR =
+ new Function(0x134, "covar", 0xff);
+ public static final Function FORECAST =
+ new Function(0x135, "forecast", 0xff);
+ public static final Function FTEST =
+ new Function(0x136, "ftest", 0xff);
+ public static final Function INTERCEPT =
+ new Function(0x137, "intercept", 0xff);
+ public static final Function PEARSON =
+ new Function(0x138, "pearson", 0xff);
+ public static final Function RSQ =
+ new Function(0x139, "rsq", 0xff);
+ public static final Function STEYX =
+ new Function(0x13a, "steyx", 0xff);
+ public static final Function SLOPE =
+ new Function(0x13b, "slope", 2);
+ public static final Function TTEST =
+ new Function(0x13c, "ttest", 0xff);
+ public static final Function PROB =
+ new Function(0x13d, "prob", 0xff);
+ public static final Function DEVSQ =
+ new Function(0x13e, "devsq", 0xff);
+ public static final Function GEOMEAN =
+ new Function(0x13f, "geomean", 0xff);
+ public static final Function HARMEAN =
+ new Function(0x140, "harmean", 0xff);
+ public static final Function SUMSQ =
+ new Function(0x141, "sumsq", 0xff);
+ public static final Function KURT =
+ new Function(0x142, "kurt", 0xff);
+ public static final Function SKEW =
+ new Function(0x143, "skew", 0xff);
+ public static final Function ZTEST =
+ new Function(0x144, "ztest", 0xff);
+ public static final Function LARGE =
+ new Function(0x145, "large", 0xff);
+ public static final Function SMALL =
+ new Function(0x146, "small", 0xff);
+ public static final Function QUARTILE =
+ new Function(0x147, "quartile", 0xff);
+ public static final Function PERCENTILE =
+ new Function(0x148, "percentile", 0xff);
+ public static final Function PERCENTRANK =
+ new Function(0x149, "percentrank", 0xff);
+ public static final Function MODE =
+ new Function(0x14a, "mode", 0xff);
+ public static final Function TRIMMEAN =
+ new Function(0x14b, "trimmean", 0xff);
+ public static final Function TINV =
+ new Function(0x14c, "tinv", 2);
+ public static final Function CONCATENATE =
+ new Function(0x150, "concatenate", 0xff);
+ public static final Function POWER =
+ new Function(0x151, "power", 2);
+ public static final Function RADIANS =
+ new Function(0x156, "radians", 1);
+ public static final Function DEGREES =
+ new Function(0x157, "degrees", 1);
+ public static final Function SUBTOTAL =
+ new Function(0x158, "subtotal", 0xff);
+ public static final Function SUMIF =
+ new Function(0x159, "sumif", 0xff);
+ public static final Function COUNTIF =
+ new Function(0x15a, "countif", 2);
+ public static final Function COUNTBLANK =
+ new Function(0x15b, "countblank", 1);
+ public static final Function HYPERLINK =
+ new Function(0x167, "hyperlink", 2);
+ public static final Function AVERAGEA =
+ new Function(0x169, "averagea", 0xff);
+ public static final Function MAXA =
+ new Function(0x16a, "maxa", 0xff);
+ public static final Function MINA =
+ new Function(0x16b, "mina", 0xff);
+ public static final Function STDEVPA =
+ new Function(0x16c, "stdevpa", 0xff);
+ public static final Function VARPA =
+ new Function(0x16d, "varpa", 0xff);
+ public static final Function STDEVA =
+ new Function(0x16e, "stdeva", 0xff);
+ public static final Function VARA =
+ new Function(0x16f, "vara", 0xff);
+
+ // If token. This is not an excel assigned number, but one made up
+ // in order that the if command may be recognized
+ public static final Function IF =
+ new Function(0xfffe, "if", 0xff);
+
+ // Unknown token
+ public static final Function UNKNOWN = new Function(0xffff, "", 0);
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/FunctionNames.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/FunctionNames.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/FunctionNames.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,104 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import common.Logger;
+
+/**
+ * A class which contains the function names for the current workbook. The
+ * function names can potentially vary from workbook to workbook depending
+ * on the locale
+ */
+public class FunctionNames
+{
+ /**
+ * The logger class
+ */
+ private static Logger logger = Logger.getLogger(FunctionNames.class);
+
+ /**
+ * A hash mapping keyed on the function and returning its locale specific
+ * name
+ */
+ private HashMap names;
+
+ /**
+ * A hash mapping keyed on the locale specific name and returning the
+ * function
+ */
+ private HashMap functions;
+
+ /**
+ * Constructor
+ *
+ * @param l the locale
+ */
+ public FunctionNames(Locale l)
+ {
+ ResourceBundle rb = ResourceBundle.getBundle("functions", l);
+ Function[] allfunctions = Function.getFunctions();
+ names = new HashMap(allfunctions.length);
+ functions = new HashMap(allfunctions.length);
+
+ // Iterate through all the functions, adding them to the hash maps
+ Function f = null;
+ String n = null;
+ String propname = null;
+ for (int i = 0; i < allfunctions.length; i++)
+ {
+ f = allfunctions[i];
+ propname = f.getPropertyName();
+
+ n = propname.length() != 0 ? rb.getString(propname) : null;
+
+ if (n != null)
+ {
+ names.put(f, n);
+ functions.put(n, f);
+ }
+ }
+ }
+
+ /**
+ * Gets the function for the specified name
+ *
+ * @param s the string
+ * @return the function
+ */
+ Function getFunction(String s)
+ {
+ return (Function) functions.get(s);
+ }
+
+ /**
+ * Gets the name for the function
+ *
+ * @param f the function
+ * @return the string
+ */
+ String getName(Function f)
+ {
+ return (String) names.get(f);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/GreaterEqual.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/GreaterEqual.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/GreaterEqual.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,59 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A cell reference in a formula
+ */
+class GreaterEqual extends BinaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public GreaterEqual()
+ {
+ }
+
+ public String getSymbol()
+ {
+ return ">=";
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.GREATER_EQUAL;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 5;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/GreaterThan.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/GreaterThan.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/GreaterThan.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,59 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A cell reference in a formula
+ */
+class GreaterThan extends BinaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public GreaterThan()
+ {
+ }
+
+ public String getSymbol()
+ {
+ return ">";
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.GREATER_THAN;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 5;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/IntegerValue.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/IntegerValue.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/IntegerValue.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,130 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+
+/**
+ * A cell reference in a formula
+ */
+class IntegerValue extends NumberValue implements ParsedThing
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(IntegerValue.class);
+
+ /**
+ * The value of this integer
+ */
+ private double value;
+
+ /**
+ * Flag which indicates whether or not this integer is out range
+ */
+ private boolean outOfRange;
+
+ /**
+ * Constructor
+ */
+ public IntegerValue()
+ {
+ outOfRange = false;
+ }
+
+ /**
+ * Constructor for an integer value being read from a string
+ */
+ public IntegerValue(String s)
+ {
+ try
+ {
+ value = Integer.parseInt(s);
+ }
+ catch (NumberFormatException e)
+ {
+ logger.warn(e, e);
+ value = 0;
+ }
+
+ short v = (short) value;
+ outOfRange = (value != v);
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ value = IntegerHelper.getInt(data[pos], data[pos+1]);
+
+ return 2;
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[3];
+ data[0] = Token.INTEGER.getCode();
+
+ IntegerHelper.getTwoBytes((int) value, data, 1);
+
+ return data;
+ }
+
+ /**
+ * Accessor for the value
+ *
+ * @return the value
+ */
+ public double getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Accessor for the out of range flag
+ *
+ * @return TRUE if the value is out of range for an excel integer
+ */
+ boolean isOutOfRange()
+ {
+ return outOfRange;
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing
+ */
+ void handleImportedCellReferences()
+ {
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/LessEqual.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/LessEqual.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/LessEqual.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,71 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A cell reference in a formula
+ */
+class LessEqual extends BinaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public LessEqual()
+ {
+ }
+
+ public String getSymbol()
+ {
+ return "<=";
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.LESS_EQUAL;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 5;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/LessThan.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/LessThan.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/LessThan.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,59 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A cell reference in a formula
+ */
+class LessThan extends BinaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public LessThan()
+ {
+ }
+
+ public String getSymbol()
+ {
+ return "<";
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.LESS_THAN;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 5;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/MemArea.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/MemArea.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/MemArea.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,75 @@
+/*********************************************************************
+*
+* Copyright (C) 2007 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import jxl.biff.IntegerHelper;
+
+/**
+ * Indicates that the function doesn't evaluate to a constant reference
+ */
+class MemArea extends SubExpression
+{
+ /**
+ * Constructor
+ */
+ public MemArea()
+ {
+ }
+
+ public void getString(StringBuffer buf)
+ {
+ ParseItem[] subExpression = getSubExpression();
+
+ if (subExpression.length == 1)
+ {
+ subExpression[0].getString(buf);
+ }
+ else if (subExpression.length == 2)
+ {
+ subExpression[1].getString(buf);
+ buf.append(':');
+ subExpression[0].getString(buf);
+ }
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ // For mem areas, the first four bytes are not used
+ setLength(IntegerHelper.getInt(data[pos+4], data[pos+5]));
+ return 6;
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing
+ */
+ void handleImportedCellReferences()
+ {
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/MemFunc.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/MemFunc.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/MemFunc.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,54 @@
+/*********************************************************************
+ *
+ * Copyright (C) 2002 Andrew Khan
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ***************************************************************************/
+
+package jxl.biff.formula;
+
+import java.util.Stack;
+
+import jxl.biff.IntegerHelper;
+
+/**
+ * Indicates that the function doesn't evaluate to a constant reference
+ */
+class MemFunc extends SubExpression
+{
+ /**
+ * Constructor
+ */
+ public MemFunc()
+ {
+ }
+
+ public void getString(StringBuffer sb)
+ {
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing
+ */
+ void handleImportedCellReferences()
+ {
+ }
+}
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Minus.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Minus.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Minus.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,67 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Logger;
+/**
+ * Ambiguously defined minus operator, used as a place holder when parsing
+ * string formulas. At this stage it could be either
+ * a unary or binary operator - the string parser will deduce which and
+ * create the appropriate type
+ */
+class Minus extends StringOperator
+{
+ // The logger
+ private static Logger logger = Logger.getLogger(StringOperator.class);
+
+ /**
+ * Constructor
+ */
+ public Minus()
+ {
+ super();
+ }
+
+ /**
+ * Abstract method which gets the binary version of this operator
+ */
+ Operator getBinaryOperator()
+ {
+ return new Subtract();
+ }
+
+ /**
+ * Abstract method which gets the unary version of this operator
+ */
+ Operator getUnaryOperator()
+ {
+ return new UnaryMinus();
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing, as operators don't have cell references
+ */
+ void handleImportedCellReferences()
+ {
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/MissingArg.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/MissingArg.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/MissingArg.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,79 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * Represents a missing argument in an argument list
+ */
+class MissingArg extends Operand implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public MissingArg()
+ {
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position.
+ * A missing argument contains no associated data
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ return 0;
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[1];
+ data[0] = Token.MISSING_ARG.getCode();
+
+ return data;
+ }
+
+ /**
+ * Abstract method implementation to get the string equivalent of this
+ * token
+ *
+ * @param buf the string to append to
+ */
+ public void getString(StringBuffer buf)
+ {
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing
+ */
+ void handleImportedCellReferences()
+ {
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Multiply.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Multiply.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Multiply.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,59 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A cell reference in a formula
+ */
+class Multiply extends BinaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public Multiply()
+ {
+ }
+
+ public String getSymbol()
+ {
+ return "*";
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.MULTIPLY;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 3;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Name.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Name.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Name.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,79 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import jxl.biff.IntegerHelper;
+/**
+ * A name operand
+ */
+class Name extends Operand implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public Name()
+ {
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ return 6;
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[6];
+
+ return data;
+ }
+
+ /**
+ * Abstract method implementation to get the string equivalent of this
+ * token
+ *
+ * @param buf the string to append to
+ */
+ public void getString(StringBuffer buf)
+ {
+ buf.append("[Name record not implemented]");
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Sets this formula to invalid
+ */
+ void handleImportedCellReferences()
+ {
+ setInvalid();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/NameRange.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/NameRange.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/NameRange.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,130 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Assert;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.WorkbookMethods;
+
+/**
+ * A name operand
+ */
+class NameRange extends Operand implements ParsedThing
+{
+ /**
+ * A handle to the name table
+ */
+ private WorkbookMethods nameTable;
+
+ /**
+ * The string name
+ */
+ private String name;
+
+ /**
+ * The index into the name table
+ */
+ private int index;
+
+ /**
+ * Constructor
+ */
+ public NameRange(WorkbookMethods nt)
+ {
+ nameTable = nt;
+ Assert.verify(nameTable != null);
+ }
+
+ /**
+ * Constructor when parsing a string via the api
+ *
+ * @param nm the name string
+ * @param nt the name table
+ */
+ public NameRange(String nm, WorkbookMethods nt) throws FormulaException
+ {
+ name = nm;
+ nameTable = nt;
+
+ index = nameTable.getNameIndex(name);
+
+ if (index < 0 )
+ {
+ throw new FormulaException(FormulaException.CELL_NAME_NOT_FOUND, name);
+ }
+
+ index += 1; // indexes are 1-based
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ index = IntegerHelper.getInt(data[pos], data[pos+1]);
+
+ name = nameTable.getName(index - 1); // ilbl is 1-based
+
+ return 4;
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[5];
+ data[0] = Token.NAMED_RANGE.getCode();
+
+ IntegerHelper.getTwoBytes(index, data, 1);
+
+ return data;
+ }
+
+ /**
+ * Abstract method implementation to get the string equivalent of this
+ * token
+ *
+ * @param buf the string to append to
+ */
+ public void getString(StringBuffer buf)
+ {
+ buf.append(name);
+ }
+
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Flags the formula as invalid
+ */
+ void handleImportedCellReferences()
+ {
+ setInvalid();
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/NotEqual.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/NotEqual.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/NotEqual.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,60 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A cell reference in a formula
+ */
+class NotEqual extends BinaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public NotEqual()
+ {
+ }
+
+ public String getSymbol()
+ {
+ return "<>";
+ }
+
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.NOT_EQUAL;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 5;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/NumberValue.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/NumberValue.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/NumberValue.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,37 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A constant numerical value in a formula
+ */
+abstract class NumberValue extends Operand implements ParsedThing
+{
+ protected NumberValue()
+ {
+ }
+
+ public abstract double getValue();
+
+ public void getString(StringBuffer buf)
+ {
+ buf.append(Double.toString(getValue()));
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/OpenParentheses.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/OpenParentheses.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/OpenParentheses.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,34 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A dummy token used when parsing strings in order to indicate the
+ * opening of some parenthesees
+ */
+class OpenParentheses extends StringParseItem
+{
+ /**
+ * Constructor
+ */
+ public OpenParentheses()
+ {
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Operand.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Operand.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Operand.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,109 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * An operand in the parse tree. Operands represent leaf nodes in the
+ * tree, and may not have children
+ * Operands include numerical values, cell references and ranges
+ */
+abstract class Operand extends ParseItem
+{
+ /**
+ * Constructor
+ */
+ public Operand()
+ {
+ }
+
+ /**
+ * Default behaviour is to do nothing
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ }
+
+ /**
+ * Default behaviour is to do nothing
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was inserted
+ * @param row the row number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowInserted(int sheetIndex, int row, boolean currentSheet)
+ {
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was removed
+ * @param row the row number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowRemoved(int sheetIndex, int row, boolean currentSheet)
+ {
+ }
+}
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Operator.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Operator.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Operator.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,90 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import java.util.Stack;
+
+/**
+ * An operator is a node in a parse tree. Its children can be other
+ * operators or operands
+ * Arithmetic operators and functions are all considered operators
+ */
+abstract class Operator extends ParseItem
+{
+ /**
+ * The items which this operator manipulates. There will be at most two
+ */
+ private ParseItem[] operands;
+
+ /**
+ * Constructor
+ */
+ public Operator()
+ {
+ operands = new ParseItem[0];
+ }
+
+ /**
+ * Tells the operands to use the alternate code
+ */
+ protected void setOperandAlternateCode()
+ {
+ for (int i = 0 ; i < operands.length ; i++)
+ {
+ operands[i].setAlternateCode();
+ }
+ }
+
+ /**
+ * Adds operands to this item
+ */
+ protected void add(ParseItem n)
+ {
+ n.setParent(this);
+
+ // Grow the array
+ ParseItem[] newOperands = new ParseItem[operands.length + 1];
+ System.arraycopy(operands, 0, newOperands, 0, operands.length);
+ newOperands[operands.length] = n;
+ operands = newOperands;
+ }
+
+ /**
+ * Gets the operands for this operator from the stack
+ */
+ public abstract void getOperands(Stack s);
+
+ /**
+ * Gets the operands ie. the children of the node
+ */
+ protected ParseItem[] getOperands()
+ {
+ return operands;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ abstract int getPrecedence();
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Parenthesis.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Parenthesis.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Parenthesis.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,193 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import java.util.Stack;
+
+/**
+ * A cell reference in a formula
+ */
+class Parenthesis extends Operator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public Parenthesis()
+ {
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ return 0;
+ }
+
+ /**
+ * Gets the operands for this operator from the stack
+ */
+ public void getOperands(Stack s)
+ {
+ ParseItem pi = (ParseItem) s.pop();
+
+ add(pi);
+ }
+
+ public void getString(StringBuffer buf)
+ {
+ ParseItem[] operands = getOperands();
+ buf.append('(');
+ operands[0].getString(buf);
+ buf.append(')');
+ }
+
+ /**
+ * Adjusts all the relative cell references in this formula by the
+ * amount specified. Used when copying formulas
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ ParseItem[] operands = getOperands();
+ operands[0].adjustRelativeCellReferences(colAdjust, rowAdjust);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ operands[0].columnInserted(sheetIndex, col, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ operands[0].columnRemoved(sheetIndex, col, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was inserted
+ * @param row the row number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowInserted(int sheetIndex, int row, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ operands[0].rowInserted(sheetIndex, row, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was removed
+ * @param row the row number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowRemoved(int sheetIndex, int row, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ operands[0].rowRemoved(sheetIndex, row, currentSheet);
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing, as operators don't have cell references
+ */
+ void handleImportedCellReferences()
+ {
+ ParseItem[] operands = getOperands();
+ operands[0].handleImportedCellReferences();
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.PARENTHESIS;
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ // Get the data for the operands
+ ParseItem[] operands = getOperands();
+ byte[] data = operands[0].getBytes();
+
+ // Add on the operator byte
+ byte[] newdata = new byte[data.length + 1];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ newdata[data.length] = getToken().getCode();
+
+ return newdata;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 4;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/ParseItem.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/ParseItem.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/ParseItem.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,211 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Logger;
+
+/**
+ * Abstract base class for an item in a formula parse tree
+ */
+abstract class ParseItem
+{
+ // The logger
+ private static Logger logger = Logger.getLogger(ParseItem.class);
+
+ /**
+ * The parent of this parse item
+ */
+ private ParseItem parent;
+
+ /**
+ * Volatile flag
+ */
+ private boolean volatileFunction;
+
+ /**
+ * Indicates that the alternative token code should be used
+ */
+ private boolean alternateCode;
+
+ /**
+ * Indicates whether this tree represents a valid formula or not. If not
+ * the parser replaces it with a valid one
+ */
+ private boolean valid;
+
+ /**
+ * Constructor
+ */
+ public ParseItem()
+ {
+ volatileFunction = false;
+ alternateCode = false;
+ valid = true;
+ }
+
+ /**
+ * Called by this class to initialize the parent
+ */
+ protected void setParent(ParseItem p)
+ {
+ parent = p;
+ }
+
+ /**
+ * Sets the volatile flag and ripples all the way up the parse tree
+ */
+ protected void setVolatile()
+ {
+ volatileFunction = true;
+ if (parent != null && !parent.isVolatile())
+ {
+ parent.setVolatile();
+ }
+ }
+
+ /**
+ * Sets the invalid flag and ripples all the way up the parse tree
+ */
+ protected final void setInvalid()
+ {
+ valid = false;
+ if (parent != null)
+ {
+ parent.setInvalid();
+ }
+ }
+
+ /**
+ * Accessor for the volatile function
+ *
+ * @return TRUE if the formula is volatile, FALSE otherwise
+ */
+ final boolean isVolatile()
+ {
+ return volatileFunction;
+ }
+
+ /**
+ * Accessor for the volatile function
+ *
+ * @return TRUE if the formula is volatile, FALSE otherwise
+ */
+ final boolean isValid()
+ {
+ return valid;
+ }
+
+ /**
+ * Gets the string representation of this item
+ * @param ws the workbook settings
+ */
+ abstract void getString(StringBuffer buf);
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ abstract byte[] getBytes();
+
+ /**
+ * Adjusts all the relative cell references in this formula by the
+ * amount specified. Used when copying formulas
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ abstract void adjustRelativeCellReferences(int colAdjust, int rowAdjust);
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ abstract void columnInserted(int sheetIndex, int col, boolean currentSheet);
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ abstract void columnRemoved(int sheetIndex, int col, boolean currentSheet);
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was inserted
+ * @param row the row number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ abstract void rowInserted(int sheetIndex, int row, boolean currentSheet);
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was removed
+ * @param row the row number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ abstract void rowRemoved(int sheetIndex, int row, boolean currentSheet);
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ */
+ abstract void handleImportedCellReferences();
+
+ /**
+ * Tells the operands to use the alternate code
+ */
+ protected void setAlternateCode()
+ {
+ alternateCode = true;
+ }
+
+ /**
+ * Accessor for the alternate code flag
+ *
+ * @return TRUE to use the alternate code, FALSE otherwise
+ */
+ protected final boolean useAlternateCode()
+ {
+ return alternateCode;
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/ParsedThing.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/ParsedThing.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/ParsedThing.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,35 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * An interface for an excel ptg
+ */
+interface ParsedThing
+{
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos) throws FormulaException;
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Parser.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Parser.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Parser.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,114 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * Interface used by the two different types of formula parser
+ */
+interface Parser
+{
+ /**
+ * Parses the formula
+ *
+ * @exception FormulaException if an error occurs
+ */
+ public void parse() throws FormulaException;
+
+ /**
+ * Gets the string version of the formula
+ *
+ * @return the formula as a string
+ */
+ public String getFormula();
+
+ /**
+ * Gets the bytes for the formula. This takes into account any
+ * token mapping necessary because of shared formulas
+ *
+ * @return the bytes in RPN
+ */
+ public byte[] getBytes();
+
+ /**
+ * Adjusts all the relative cell references in this formula by the
+ * amount specified.
+ *
+ * @param colAdjust
+ * @param rowAdjust
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust);
+
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void columnInserted(int sheetIndex, int col, boolean currentSheet);
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void columnRemoved(int sheetIndex, int col, boolean currentSheet);
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param row the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void rowInserted(int sheetIndex, int row, boolean currentSheet);
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param row the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void rowRemoved(int sheetIndex, int row, boolean currentSheet);
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ *
+ * @return TRUE if the formula is valid import, FALSE otherwise
+ */
+ public boolean handleImportedCellReferences();
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Percent.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Percent.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Percent.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,77 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A cell reference in a formula
+ */
+class Percent extends UnaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public Percent()
+ {
+ }
+
+ public String getSymbol()
+ {
+ return "%";
+ }
+
+ public void getString(StringBuffer buf)
+ {
+ ParseItem[] operands = getOperands();
+ operands[0].getString(buf);
+ buf.append(getSymbol());
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing, as operators don't have cell references
+ */
+ void handleImportedCellReferences()
+ {
+ ParseItem[] operands = getOperands();
+ operands[0].handleImportedCellReferences();
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.PERCENT;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 5;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Plus.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Plus.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Plus.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,63 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * Ambiguously defined plus operator, used as a place holder when parsing
+ * string formulas. At this stage it could be either
+ * a unary or binary operator - the string parser will deduce which and
+ * create the appropriate type
+ */
+class Plus extends StringOperator
+{
+ /**
+ * Constructor
+ */
+ public Plus()
+ {
+ super();
+ }
+
+ /**
+ * Abstract method which gets the binary version of this operator
+ */
+ Operator getBinaryOperator()
+ {
+ return new Add();
+ }
+
+ /**
+ * Abstract method which gets the unary version of this operator
+ */
+ Operator getUnaryOperator()
+ {
+ return new UnaryPlus();
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing, as operators don't have cell references
+ */
+ void handleImportedCellReferences()
+ {
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Power.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Power.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Power.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,59 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A cell reference in a formula
+ */
+class Power extends BinaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public Power()
+ {
+ }
+
+ public String getSymbol()
+ {
+ return "^";
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.POWER;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 1;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/RangeSeparator.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/RangeSeparator.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/RangeSeparator.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,87 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import jxl.biff.IntegerHelper;
+
+/**
+ * A "holding" token for a range separator. This token gets instantiated
+ * when the lexical analyzer can't distinguish a range cleanly, eg in the
+ * case where where one of the identifiers of the range is a formula
+ */
+class RangeSeparator extends BinaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public RangeSeparator()
+ {
+ }
+
+ public String getSymbol()
+ {
+ return ":";
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.RANGE;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 1;
+ }
+
+ /**
+ * Overrides the getBytes() method in the base class and prepends the
+ * memFunc token
+ *
+ * @return the bytes
+ */
+ byte[] getBytes()
+ {
+ setVolatile();
+ setOperandAlternateCode();
+
+ byte[] funcBytes = super.getBytes();
+
+ byte[] bytes = new byte[funcBytes.length+3];
+ System.arraycopy(funcBytes, 0, bytes, 3, funcBytes.length);
+
+ // Indicate the mem func
+ bytes[0] = Token.MEM_FUNC.getCode();
+ IntegerHelper.getTwoBytes(funcBytes.length, bytes, 1);
+
+ return bytes;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/SharedFormulaArea.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/SharedFormulaArea.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/SharedFormulaArea.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,166 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import jxl.Cell;
+import jxl.biff.CellReferenceHelper;
+import jxl.biff.IntegerHelper;
+
+/**
+ * A cell reference in a formula
+ */
+class SharedFormulaArea extends Operand implements ParsedThing
+{
+ private int columnFirst;
+ private int rowFirst;
+ private int columnLast;
+ private int rowLast;
+
+ private boolean columnFirstRelative;
+ private boolean rowFirstRelative;
+ private boolean columnLastRelative;
+ private boolean rowLastRelative;
+
+ /**
+ * The cell containing the formula. Stored in order to determine
+ * relative cell values
+ */
+ private Cell relativeTo;
+
+ /**
+ * Constructor
+ *
+ * @param the cell the formula is relative to
+ */
+ public SharedFormulaArea(Cell rt)
+ {
+ relativeTo = rt;
+ }
+
+ int getFirstColumn()
+ {
+ return columnFirst;
+ }
+
+ int getFirstRow()
+ {
+ return rowFirst;
+ }
+
+ int getLastColumn()
+ {
+ return columnLast;
+ }
+
+ int getLastRow()
+ {
+ return rowLast;
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ // Preserve signage on column and row values, because they will
+ // probably be relative
+
+ rowFirst = IntegerHelper.getShort(data[pos], data[pos+1]);
+ rowLast = IntegerHelper.getShort(data[pos+2], data[pos+3]);
+
+ int columnMask = IntegerHelper.getInt(data[pos+4], data[pos+5]);
+ columnFirst = columnMask & 0x00ff;
+ columnFirstRelative = ((columnMask & 0x4000) != 0);
+ rowFirstRelative = ((columnMask & 0x8000) != 0);
+
+ if (columnFirstRelative)
+ {
+ columnFirst = relativeTo.getColumn() + columnFirst;
+ }
+
+ if (rowFirstRelative)
+ {
+ rowFirst = relativeTo.getRow() + rowFirst;
+ }
+
+ columnMask = IntegerHelper.getInt(data[pos+6], data[pos+7]);
+ columnLast = columnMask & 0x00ff;
+
+ columnLastRelative = ((columnMask & 0x4000) != 0);
+ rowLastRelative = ((columnMask & 0x8000) != 0);
+
+ if (columnLastRelative)
+ {
+ columnLast = relativeTo.getColumn() + columnLast;
+ }
+
+ if (rowLastRelative)
+ {
+ rowLast = relativeTo.getRow() + rowLast;
+ }
+
+
+ return 8;
+ }
+
+ public void getString(StringBuffer buf)
+ {
+ CellReferenceHelper.getCellReference(columnFirst, rowFirst, buf);
+ buf.append(':');
+ CellReferenceHelper.getCellReference(columnLast, rowLast, buf);
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[9];
+ data[0] = Token.AREA.getCode();
+
+ // Use absolute references for columns, so don't bother about
+ // the col relative/row relative bits
+ IntegerHelper.getTwoBytes(rowFirst, data, 1);
+ IntegerHelper.getTwoBytes(rowLast, data, 3);
+ IntegerHelper.getTwoBytes(columnFirst, data, 5);
+ IntegerHelper.getTwoBytes(columnLast, data, 7);
+
+ return data;
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing
+ */
+ void handleImportedCellReferences()
+ {
+ }
+
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/SharedFormulaCellReference.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/SharedFormulaCellReference.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/SharedFormulaCellReference.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,168 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Logger;
+
+import jxl.Cell;
+import jxl.biff.CellReferenceHelper;
+import jxl.biff.IntegerHelper;
+
+
+/**
+ * A cell reference in a formula
+ */
+class SharedFormulaCellReference extends Operand implements ParsedThing
+{
+ // The logger
+ private static Logger logger =
+ Logger.getLogger(SharedFormulaCellReference.class);
+
+ /**
+ * Indicates whether the column reference is relative or absolute
+ */
+ private boolean columnRelative;
+
+ /**
+ * Indicates whether the row reference is relative or absolute
+ */
+ private boolean rowRelative;
+
+ /**
+ * The column reference
+ */
+ private int column;
+
+ /**
+ * The row reference
+ */
+ private int row;
+
+ /**
+ * The cell containing the formula. Stored in order to determine
+ * relative cell values
+ */
+ private Cell relativeTo;
+
+ /**
+ * Constructor
+ *
+ * @param the cell the formula is relative to
+ */
+ public SharedFormulaCellReference(Cell rt)
+ {
+ relativeTo = rt;
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ // Preserve signage on column and row values, because they will
+ // probably be relative
+ row = IntegerHelper.getShort(data[pos], data[pos+1]);
+
+ int columnMask = IntegerHelper.getInt(data[pos+2], data[pos+3]);
+
+ column = (byte) (columnMask & 0xff);
+ columnRelative = ((columnMask & 0x4000) != 0);
+ rowRelative = ((columnMask & 0x8000) != 0);
+
+ if (columnRelative && relativeTo != null)
+ {
+ column = relativeTo.getColumn() + column;
+ }
+
+ if (rowRelative && relativeTo != null)
+ {
+ row = relativeTo.getRow() + row;
+ }
+
+ return 4;
+ }
+
+ public int getColumn()
+ {
+ return column;
+ }
+
+ public int getRow()
+ {
+ return row;
+ }
+
+ public void getString(StringBuffer buf)
+ {
+ CellReferenceHelper.getCellReference(column, row, buf);
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[5];
+ data[0] = Token.REF.getCode();
+
+ IntegerHelper.getTwoBytes(row, data, 1);
+
+ int columnMask = column;
+
+ if (columnRelative)
+ {
+ columnMask |= 0x4000;
+ }
+
+ if (rowRelative)
+ {
+ columnMask |= 0x8000;
+ }
+
+ IntegerHelper.getTwoBytes(columnMask, data, 3);
+
+ return data;
+ }
+
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing
+ */
+ void handleImportedCellReferences()
+ {
+ }
+}
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/StringFormulaParser.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/StringFormulaParser.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/StringFormulaParser.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,567 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Stack;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.WorkbookMethods;
+
+/**
+ * Parses a string formula into a parse tree
+ */
+class StringFormulaParser implements Parser
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(StringFormulaParser.class);
+
+ /**
+ * The formula string passed to this object
+ */
+ private String formula;
+
+ /**
+ * The parsed formula string, as retrieved from the parse tree
+ */
+ private String parsedFormula;
+
+ /**
+ * The parse tree
+ */
+ private ParseItem root;
+
+ /**
+ * The stack argument used when parsing a function in order to
+ * pass multiple arguments back to the calling method
+ */
+ private Stack arguments;
+
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings settings;
+
+ /**
+ * A handle to the external sheet
+ */
+ private ExternalSheet externalSheet;
+
+ /**
+ * A handle to the name table
+ */
+ private WorkbookMethods nameTable;
+
+ /**
+ * Constructor
+ * @param f
+ * @param ws
+ */
+ public StringFormulaParser(String f,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ WorkbookSettings ws)
+ {
+ formula = f;
+ settings = ws;
+ externalSheet = es;
+ nameTable = nt;
+ }
+
+ /**
+ * Parses the list of tokens
+ *
+ * @exception FormulaException
+ */
+ public void parse() throws FormulaException
+ {
+ ArrayList tokens = getTokens();
+
+ Iterator i = tokens.iterator();
+
+ root = parseCurrent(i);
+ }
+
+ /**
+ * Recursively parses the token array. Recursion is used in order
+ * to evaluate parentheses and function arguments
+ *
+ * @param i an iterator of tokens
+ * @return the root node of the current parse stack
+ * @exception FormulaException if an error occurs
+ */
+ private ParseItem parseCurrent(Iterator i) throws FormulaException
+ {
+ Stack stack = new Stack();
+ Stack operators = new Stack();
+ Stack args = null; // we usually don't need this
+
+ boolean parenthesesClosed = false;
+ ParseItem lastParseItem = null;
+
+ while (i.hasNext() && !parenthesesClosed)
+ {
+ ParseItem pi = (ParseItem) i.next();
+
+ if (pi instanceof Operand)
+ {
+ handleOperand((Operand) pi, stack);
+ }
+ else if (pi instanceof StringFunction)
+ {
+ handleFunction((StringFunction) pi, i, stack);
+ }
+ else if (pi instanceof Operator)
+ {
+ Operator op = (Operator) pi;
+
+ // See if the operator is a binary or unary operator
+ // It is a unary operator either if the stack is empty, or if
+ // the last thing off the stack was another operator
+ if (op instanceof StringOperator)
+ {
+ StringOperator sop = (StringOperator) op;
+ if (stack.isEmpty() || lastParseItem instanceof Operator)
+ {
+ op = sop.getUnaryOperator();
+ }
+ else
+ {
+ op = sop.getBinaryOperator();
+ }
+ }
+
+ if (operators.empty())
+ {
+ // nothing much going on, so do nothing for the time being
+ operators.push(op);
+ }
+ else
+ {
+ Operator operator = (Operator) operators.peek();
+
+ // If the last operator has a higher precedence then add this to
+ // the operator stack and wait
+ if (op.getPrecedence() < operator.getPrecedence())
+ {
+ operators.push(op);
+ }
+ else if (op.getPrecedence() == operator.getPrecedence() &&
+ op instanceof UnaryOperator)
+ {
+ // The operators are of equal precedence, but because it is a
+ // unary operator the operand isn't available yet, so put it on
+ // the stack
+ operators.push(op);
+ }
+ else
+ {
+ // The operator is of a lower precedence so we can sort out
+ // some of the items on the stack
+ operators.pop(); // remove the operator from the stack
+ operator.getOperands(stack);
+ stack.push(operator);
+ operators.push(op);
+ }
+ }
+ }
+ else if (pi instanceof ArgumentSeparator)
+ {
+ // Clean up any remaining items on this stack
+ while (!operators.isEmpty())
+ {
+ Operator o = (Operator) operators.pop();
+ o.getOperands(stack);
+ stack.push(o);
+ }
+
+ // Add it to the argument stack. Create the argument stack
+ // if necessary. Items will be stored on the argument stack in
+ // reverse order
+ if (args == null)
+ {
+ args = new Stack();
+ }
+
+ args.push(stack.pop());
+ stack.clear();
+ }
+ else if (pi instanceof OpenParentheses)
+ {
+ ParseItem pi2 = parseCurrent(i);
+ Parenthesis p = new Parenthesis();
+ pi2.setParent(p);
+ p.add(pi2);
+ stack.push(p);
+ }
+ else if (pi instanceof CloseParentheses)
+ {
+ parenthesesClosed = true;
+ }
+
+ lastParseItem = pi;
+ }
+
+ while (!operators.isEmpty())
+ {
+ Operator o = (Operator) operators.pop();
+ o.getOperands(stack);
+ stack.push(o);
+ }
+
+ ParseItem rt = !stack.empty()? (ParseItem) stack.pop():null;
+
+ // if the argument stack is not null, then add it to that stack
+ // as well for good measure
+ if (args != null && rt != null)
+ {
+ args.push(rt);
+ }
+
+ arguments = args;
+
+ if (!stack.empty() || !operators.empty() )
+ {
+ logger.warn("Formula " + formula +
+ " has a non-empty parse stack");
+ }
+
+ return rt;
+ }
+
+ /**
+ * Gets the list of lexical tokens using the generated lexical analyzer
+ *
+ * @return the list of tokens
+ * @exception FormulaException if an error occurs
+ */
+ private ArrayList getTokens() throws FormulaException
+ {
+ ArrayList tokens = new ArrayList();
+
+ StringReader sr = new StringReader(formula);
+ Yylex lex = new Yylex(sr);
+ lex.setExternalSheet(externalSheet);
+ lex.setNameTable(nameTable);
+ try
+ {
+ ParseItem pi = lex.yylex();
+ while (pi != null)
+ {
+ tokens.add(pi);
+ pi = lex.yylex();
+ }
+ }
+ catch (IOException e)
+ {
+ logger.warn(e.toString());
+ }
+ catch (Error e)
+ {
+ throw new FormulaException(FormulaException.LEXICAL_ERROR,
+ formula + " at char " + lex.getPos());
+ }
+
+ return tokens;
+ }
+
+ /**
+ * Gets the formula as a string. Uses the parse tree to do this, and
+ * does not simply return whatever string was passed in
+ */
+ public String getFormula()
+ {
+ if (parsedFormula == null)
+ {
+ StringBuffer sb = new StringBuffer();
+ root.getString(sb);
+ parsedFormula = sb.toString();
+ }
+
+ return parsedFormula;
+ }
+
+ /**
+ * Gets the bytes for the formula
+ *
+ * @return the bytes in RPN
+ */
+ public byte[] getBytes()
+ {
+ byte[] bytes = root.getBytes();
+
+ if (root.isVolatile())
+ {
+ byte[] newBytes = new byte[bytes.length + 4];
+ System.arraycopy(bytes, 0, newBytes, 4, bytes.length);
+ newBytes[0] = Token.ATTRIBUTE.getCode();
+ newBytes[1] = (byte) 0x1;
+ bytes = newBytes;
+ }
+
+ return bytes;
+ }
+
+ /**
+ * Handles the case when parsing a string when a token is a function
+ *
+ * @param sf the string function
+ * @param i the token iterator
+ * @param stack the parse tree stack
+ * @exception FormulaException if an error occurs
+ */
+ private void handleFunction(StringFunction sf, Iterator i,
+ Stack stack)
+ throws FormulaException
+ {
+ ParseItem pi2 = parseCurrent(i);
+
+ // If the function is unknown, then throw an error
+ if (sf.getFunction(settings) == Function.UNKNOWN)
+ {
+ throw new FormulaException(FormulaException.UNRECOGNIZED_FUNCTION);
+ }
+
+ // First check for possible optimized functions and possible
+ // use of the Attribute token
+ if (sf.getFunction(settings) == Function.SUM && arguments == null)
+ {
+ // this is handled by an attribute
+ Attribute a = new Attribute(sf, settings);
+ a.add(pi2);
+ stack.push(a);
+ return;
+ }
+
+ if (sf.getFunction(settings) == Function.IF)
+ {
+ // this is handled by an attribute
+ Attribute a = new Attribute(sf, settings);
+
+ // Add in the if conditions as a var arg function in
+ // the correct order
+ VariableArgFunction vaf = new VariableArgFunction(settings);
+ int numargs = arguments.size();
+ for (int j = 0 ; j < numargs; j++)
+ {
+ ParseItem pi3 = (ParseItem) arguments.get(j);
+ vaf.add(pi3);
+ }
+
+ a.setIfConditions(vaf);
+ stack.push(a);
+ return;
+ }
+
+ // Function cannot be optimized. See if it is a variable argument
+ // function or not
+ if (sf.getFunction(settings).getNumArgs() == 0xff)
+ {
+ // If the arg stack has not been initialized, it means
+ // that there was only one argument, which is the
+ // returned parse item
+ if (arguments == null)
+ {
+ int numArgs = pi2 != null? 1:0;
+ VariableArgFunction vaf = new VariableArgFunction
+ (sf.getFunction(settings), numArgs, settings);
+
+ if (pi2 != null)
+ {
+ vaf.add(pi2);
+ }
+
+ stack.push(vaf);
+ }
+ else
+ {
+ // Add the args to the function in the correct order
+ int numargs = arguments.size();
+ VariableArgFunction vaf = new VariableArgFunction
+ (sf.getFunction(settings), numargs, settings);
+
+ ParseItem[] args = new ParseItem[numargs];
+ for (int j = 0 ; j < numargs; j++)
+ {
+ ParseItem pi3 = (ParseItem) arguments.pop();
+ args[numargs-j-1] = pi3;
+ }
+
+ for (int j = 0 ; j < args.length ; j++)
+ {
+ vaf.add(args[j]);
+ }
+ stack.push(vaf);
+ arguments.clear();
+ arguments = null;
+ }
+ return;
+ }
+
+ // Function is a standard built in function
+ BuiltInFunction bif = new BuiltInFunction(sf.getFunction(settings),
+ settings);
+
+ int numargs = sf.getFunction(settings).getNumArgs();
+ if (numargs == 1)
+ {
+ // only one item which is the returned ParseItem
+ bif.add(pi2);
+ }
+ else
+ {
+ if ((arguments == null && numargs != 0) ||
+ (arguments != null && numargs != arguments.size()))
+ {
+ throw new FormulaException(FormulaException.INCORRECT_ARGUMENTS);
+ }
+ // multiple arguments so go to the arguments stack.
+ // Unlike the variable argument function, the args are
+ // stored in reverse order
+ for (int j = 0; j < numargs ; j++)
+ {
+ ParseItem pi3 = (ParseItem) arguments.get(j);
+ bif.add(pi3);
+ }
+ }
+ stack.push(bif);
+ }
+
+ /**
+ * Default behaviour is to do nothing
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ root.adjustRelativeCellReferences(colAdjust, rowAdjust);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ root.columnInserted(sheetIndex, col, currentSheet);
+ }
+
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ root.columnRemoved(sheetIndex, col, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param row the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void rowInserted(int sheetIndex, int row, boolean currentSheet)
+ {
+ root.rowInserted(sheetIndex, row, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param row the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void rowRemoved(int sheetIndex, int row, boolean currentSheet)
+ {
+ root.rowRemoved(sheetIndex, row, currentSheet);
+ }
+
+ /**
+ * Handles operands by pushing them onto the stack
+ *
+ * @param o operand
+ * @param stack stack
+ */
+ private void handleOperand(Operand o, Stack stack)
+ {
+ if (!(o instanceof IntegerValue))
+ {
+ stack.push(o);
+ return;
+ }
+
+ if (o instanceof IntegerValue)
+ {
+ IntegerValue iv = (IntegerValue) o;
+ if (!iv.isOutOfRange())
+ {
+ stack.push(iv);
+ }
+ else
+ {
+ // convert to a double
+ DoubleValue dv = new DoubleValue(iv.getValue());
+ stack.push(dv);
+ }
+ }
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ *
+ * @return TRUE if the formula is valid import, FALSE otherwise
+ */
+ public boolean handleImportedCellReferences()
+ {
+ root.handleImportedCellReferences();
+ return root.isValid();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/StringFunction.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/StringFunction.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/StringFunction.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,71 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+
+/**
+ * Class used to hold a function when reading it in from a string. At this
+ * stage it is unknown whether it is a BuiltInFunction or a VariableArgFunction
+ */
+class StringFunction extends StringParseItem
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(StringFunction.class);
+
+ /**
+ * The function
+ */
+ private Function function;
+
+ /**
+ * The function string
+ */
+ private String functionString;
+
+ /**
+ * Constructor
+ *
+ * @param s the lexically parsed stirng
+ */
+ StringFunction(String s)
+ {
+ functionString = s.substring(0, s.length() - 1);
+ }
+
+ /**
+ * Accessor for the function
+ *
+ * @param ws the workbook settings
+ * @return the function
+ */
+ Function getFunction(WorkbookSettings ws)
+ {
+ if (function == null)
+ {
+ function = Function.getFunction(functionString, ws);
+ }
+ return function;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/StringOperator.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/StringOperator.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/StringOperator.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,160 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import java.util.Stack;
+
+import common.Assert;
+
+/**
+ * Ambiguously defined operator, used as a place holder when parsing
+ * string formulas. At this stage it could be either
+ * a unary or binary operator - the string parser will deduce which and
+ * create the appropriate type
+ */
+abstract class StringOperator extends Operator
+{
+ /**
+ * Constructor
+ */
+ protected StringOperator()
+ {
+ super();
+ }
+
+ /**
+ * Gets the operands for this operator from the stack. Does nothing
+ * here
+ */
+ public void getOperands(Stack s)
+ {
+ Assert.verify(false);
+ }
+
+ /**
+ * Gets the precedence for this operator. Does nothing here
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ Assert.verify(false);
+ return 0;
+ }
+
+ /**
+ * Gets the token representation of this item in RPN. Does nothing here
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ Assert.verify(false);
+ return null;
+ }
+
+ /**
+ * Gets the string representation of this item
+ */
+ void getString(StringBuffer buf)
+ {
+ Assert.verify(false);
+ }
+
+ /**
+ * Default behaviour is to do nothing
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ Assert.verify(false);
+ }
+
+
+ /**
+ * Default behaviour is to do nothing
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ Assert.verify(false);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ Assert.verify(false);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was inserted
+ * @param row the row number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowInserted(int sheetIndex, int row, boolean currentSheet)
+ {
+ Assert.verify(false);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was removed
+ * @param row the row number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowRemoved(int sheetIndex, int row, boolean currentSheet)
+ {
+ Assert.verify(false);
+ }
+
+ /**
+ * Abstract method which gets the binary version of this operator
+ */
+ abstract Operator getBinaryOperator();
+
+ /**
+ * Abstract method which gets the unary version of this operator
+ */
+ abstract Operator getUnaryOperator();
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/StringParseItem.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/StringParseItem.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/StringParseItem.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,128 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A dummy implementation used for typing information when tokens
+ * are read when parsing strings. These are then stored by the parser before
+ * being re-stored as the appropriate RPN syntactic equivalent
+ */
+class StringParseItem extends ParseItem
+{
+ /**
+ * Constructor
+ */
+ protected StringParseItem()
+ {
+ }
+
+ /**
+ * Gets the string representation of this item. Does nothing here
+ *
+ * @param buf
+ */
+ void getString(StringBuffer buf)
+ {
+ }
+
+ /**
+ * Gets the token representation of this item in RPN. Does nothing here
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ return new byte[0];
+ }
+
+ /**
+ * Default behaviour is to do nothing
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ }
+
+ /**
+ * Default behaviour is to do nothing
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was inserted
+ * @param row the row number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowInserted(int sheetIndex, int row, boolean currentSheet)
+ {
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was removed
+ * @param row the row number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowRemoved(int sheetIndex, int row, boolean currentSheet)
+ {
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing
+ */
+ void handleImportedCellReferences()
+ {
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/StringValue.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/StringValue.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/StringValue.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,133 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.IntegerHelper;
+import jxl.biff.StringHelper;
+
+
+/**
+ * A string constant operand in a formula
+ */
+class StringValue extends Operand implements ParsedThing
+{
+ /**
+ * The logger
+ */
+ private final static Logger logger = Logger.getLogger(StringValue.class);
+
+ /**
+ * The string value
+ */
+ private String value;
+
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings settings;
+
+ /**
+ * Constructor
+ */
+ public StringValue(WorkbookSettings ws)
+ {
+ settings = ws;
+ }
+
+ /**
+ * Constructor used when parsing a string formula
+ *
+ * @param s the string token, including quote marks
+ */
+ public StringValue(String s)
+ {
+ // remove the quotes
+ value = s;
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ int length = data[pos] & 0xff;
+ int consumed = 2;
+
+ if ((data[pos+1] & 0x01) == 0)
+ {
+ value = StringHelper.getString(data, length, pos+2, settings);
+ consumed += length;
+ }
+ else
+ {
+ value = StringHelper.getUnicodeString(data, length, pos+2);
+ consumed += length * 2;
+ }
+
+ return consumed;
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ byte[] data = new byte[value.length() * 2 + 3];
+ data[0] = Token.STRING.getCode();
+ data[1] = (byte) (value.length());
+ data[2] = 0x01;
+ StringHelper.getUnicodeBytes(value, data, 3);
+
+ return data;
+ }
+
+ /**
+ * Abstract method implementation to get the string equivalent of this
+ * token
+ *
+ * @param buf the string to append to
+ */
+ public void getString(StringBuffer buf)
+ {
+ buf.append("\"");
+ buf.append(value);
+ buf.append("\"");
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing
+ */
+ void handleImportedCellReferences()
+ {
+ }
+
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/SubExpression.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/SubExpression.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/SubExpression.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,116 @@
+/*********************************************************************
+*
+* Copyright (C) 2007 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import java.util.Stack;
+
+import jxl.biff.IntegerHelper;
+
+/**
+ * Base class for those tokens which encapsulate a subexpression
+ */
+abstract class SubExpression extends Operand implements ParsedThing
+{
+ /**
+ * The number of bytes in the subexpression
+ */
+ private int length;
+
+ /**
+ * The sub expression
+ */
+ private ParseItem[] subExpression;
+
+ /**
+ * Constructor
+ */
+ protected SubExpression()
+ {
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ length = IntegerHelper.getInt(data[pos], data[pos+1]);
+ return 2;
+ }
+
+ /**
+ * Gets the operands for this operator from the stack
+ */
+ public void getOperands(Stack s)
+ {
+ }
+
+ /**
+ * Gets the token representation of this item in RPN. The Attribute
+ * token is a special case, which overrides anything useful we could do
+ * in the base class
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ return null;
+ }
+
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 5;
+ }
+
+ /**
+ * Accessor for the length
+ *
+ * @return the length of the subexpression
+ */
+ public int getLength()
+ {
+ return length;
+ }
+
+ protected final void setLength(int l)
+ {
+ length = l;
+ }
+
+ public void setSubExpression(ParseItem[] pi)
+ {
+ subExpression = pi;
+ }
+
+ protected ParseItem[] getSubExpression()
+ {
+ return subExpression;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Subtract.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Subtract.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Subtract.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,59 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A cell reference in a formula
+ */
+class Subtract extends BinaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public Subtract()
+ {
+ }
+
+ public String getSymbol()
+ {
+ return "-";
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.SUBTRACT;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 4;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Token.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Token.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Token.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,198 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import java.util.HashMap;
+
+/**
+ * An enumeration detailing the Excel parsed tokens
+ * A particular token may be associated with more than one token code
+ */
+class Token
+{
+ /**
+ * The array of values which apply to this token
+ */
+ public final int[] value;
+
+ /**
+ * All available tokens, keyed on value
+ */
+ private static HashMap tokens = new HashMap(20);
+
+ /**
+ * Constructor
+ * Sets the token value and adds this token to the array of all token
+ *
+ * @param v the biff code for the token
+ */
+ private Token(int v)
+ {
+ value = new int[] {v};
+
+ tokens.put(new Integer(v), this);
+ }
+
+ /**
+ * Constructor
+ * Sets the token value and adds this token to the array of all token
+ *
+ * @param v the biff code for the token
+ */
+ private Token(int v1, int v2)
+ {
+ value = new int[] {v1, v2};
+
+ tokens.put(new Integer(v1), this);
+ tokens.put(new Integer(v2), this);
+ }
+
+ /**
+ * Constructor
+ * Sets the token value and adds this token to the array of all token
+ *
+ * @param v the biff code for the token
+ */
+ private Token(int v1, int v2, int v3)
+ {
+ value = new int[] {v1, v2, v3};
+
+ tokens.put(new Integer(v1), this);
+ tokens.put(new Integer(v2), this);
+ tokens.put(new Integer(v3), this);
+ }
+
+ /**
+ * Constructor
+ * Sets the token value and adds this token to the array of all token
+ *
+ * @param v the biff code for the token
+ */
+ private Token(int v1, int v2, int v3, int v4)
+ {
+ value = new int[] {v1, v2, v3, v4};
+
+ tokens.put(new Integer(v1), this);
+ tokens.put(new Integer(v2), this);
+ tokens.put(new Integer(v3), this);
+ tokens.put(new Integer(v4), this);
+ }
+
+ /**
+ * Constructor
+ * Sets the token value and adds this token to the array of all token
+ *
+ * @param v the biff code for the token
+ */
+ private Token(int v1, int v2, int v3, int v4, int v5)
+ {
+ value = new int[] {v1, v2, v3, v4, v5};
+
+ tokens.put(new Integer(v1), this);
+ tokens.put(new Integer(v2), this);
+ tokens.put(new Integer(v3), this);
+ tokens.put(new Integer(v4), this);
+ tokens.put(new Integer(v5), this);
+ }
+
+ /**
+ * Gets the token code for the specified token
+ *
+ * @return the token code. This is the first item in the array
+ */
+ public byte getCode()
+ {
+ return (byte) value[0];
+ }
+
+ /**
+ * Gets an alternative token code for the specified token
+ * Used for certain types of volatile function
+ *
+ * @return the token code
+ */
+ public byte getCode2()
+ {
+ return (byte) (value.length > 0 ? value[1] : value[0]);
+ }
+
+ /**
+ * Gets the type object from its integer value
+ */
+ public static Token getToken(int v)
+ {
+ Token t = (Token) tokens.get(new Integer(v));
+
+ return t != null ? t : UNKNOWN;
+ }
+
+ // Operands
+ public static final Token REF = new Token(0x44, 0x24, 0x64);
+ public static final Token REF3D = new Token(0x5a, 0x3a, 0x7a);
+ public static final Token MISSING_ARG = new Token(0x16);
+ public static final Token STRING = new Token(0x17);
+ public static final Token ERR = new Token(0x1c);
+ public static final Token BOOL = new Token(0x1d);
+ public static final Token INTEGER = new Token(0x1e);
+ public static final Token DOUBLE = new Token(0x1f);
+ public static final Token REFERR = new Token(0x2a, 0x4a, 0x6a);
+ public static final Token REFV = new Token(0x2c, 0x4c, 0x6c);
+ public static final Token AREAV = new Token(0x2d, 0x4d, 0x6d);
+ public static final Token MEM_AREA = new Token(0x26, 0x46, 0x66);
+ public static final Token AREA = new Token(0x25, 0x65, 0x45);
+ public static final Token NAMED_RANGE = new Token(0x23, 0x43, 0x63);
+ //need 0x23 for data validation references
+ public static final Token NAME = new Token(0x39, 0x59);
+ public static final Token AREA3D = new Token(0x3b, 0x5b);
+
+ // Unary Operators
+ public static final Token UNARY_PLUS = new Token(0x12);
+ public static final Token UNARY_MINUS = new Token(0x13);
+ public static final Token PERCENT = new Token(0x14);
+ public static final Token PARENTHESIS = new Token(0x15);
+
+ // Binary Operators
+ public static final Token ADD = new Token(0x3);
+ public static final Token SUBTRACT = new Token(0x4);
+ public static final Token MULTIPLY = new Token(0x5);
+ public static final Token DIVIDE = new Token(0x6);
+ public static final Token POWER = new Token(0x7);
+ public static final Token CONCAT = new Token(0x8);
+ public static final Token LESS_THAN = new Token(0x9);
+ public static final Token LESS_EQUAL = new Token(0xa);
+ public static final Token EQUAL = new Token(0xb);
+ public static final Token GREATER_EQUAL = new Token(0xc);
+ public static final Token GREATER_THAN = new Token(0xd);
+ public static final Token NOT_EQUAL = new Token(0xe);
+ public static final Token UNION = new Token(0x10);
+ public static final Token RANGE = new Token(0x11);
+
+ // Functions
+ public static final Token FUNCTION = new Token(0x41, 0x21, 0x61);
+ public static final Token FUNCTIONVARARG = new Token(0x42, 0x22, 0x62);
+
+ // Control
+ public static final Token ATTRIBUTE = new Token(0x19);
+ public static final Token MEM_FUNC = new Token(0x29, 0x49, 0x69);
+
+ // Unknown token
+ public static final Token UNKNOWN = new Token(0xffff);
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/TokenFormulaParser.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/TokenFormulaParser.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/TokenFormulaParser.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,559 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import java.util.Stack;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.Cell;
+import jxl.WorkbookSettings;
+import jxl.biff.WorkbookMethods;
+
+/**
+ * Parses the excel ptgs into a parse tree
+ */
+class TokenFormulaParser implements Parser
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(TokenFormulaParser.class);
+
+ /**
+ * The Excel ptgs
+ */
+ private byte[] tokenData;
+
+ /**
+ * The cell containing the formula. This is used in order to determine
+ * relative cell values
+ */
+ private Cell relativeTo;
+
+ /**
+ * The current position within the array
+ */
+ private int pos;
+
+ /**
+ * The parse tree
+ */
+ private ParseItem root;
+
+ /**
+ * The hash table of items that have been parsed
+ */
+ private Stack tokenStack;
+
+ /**
+ * A reference to the workbook which holds the external sheet
+ * information
+ */
+ private ExternalSheet workbook;
+
+ /**
+ * A reference to the name table
+ */
+ private WorkbookMethods nameTable;
+
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings settings;
+
+ /**
+ * Constructor
+ */
+ public TokenFormulaParser(byte[] data,
+ Cell c,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ WorkbookSettings ws)
+ {
+ tokenData = data;
+ pos = 0;
+ relativeTo = c;
+ workbook = es;
+ nameTable = nt;
+ tokenStack = new Stack();
+ settings = ws;
+
+ Assert.verify(nameTable != null);
+ }
+
+ /**
+ * Parses the sublist of tokens. In most cases this will equate to
+ * the full list
+ *
+ * @exception FormulaException
+ */
+ public void parse() throws FormulaException
+ {
+ parseSubExpression(tokenData.length);
+
+ // Finally, there should be one thing left on the stack. Get that
+ // and add it to the root node
+ root = (ParseItem) tokenStack.pop();
+
+ Assert.verify(tokenStack.empty());
+
+ }
+
+ /**
+ * Parses the sublist of tokens. In most cases this will equate to
+ * the full list
+ *
+ * @param len the length of the subexpression to parse
+ * @exception FormulaException
+ */
+ private void parseSubExpression(int len) throws FormulaException
+ {
+ int tokenVal = 0;
+ Token t = null;
+
+ // Indicates that we are parsing the incredibly complicated and
+ // hacky if construct that MS saw fit to include, the gits
+ Stack ifStack = new Stack();
+
+ // The end position of the sub-expression
+ int endpos = pos + len;
+
+ while (pos < endpos)
+ {
+ tokenVal = tokenData[pos];
+ pos++;
+
+ t = Token.getToken(tokenVal);
+
+ if (t == Token.UNKNOWN)
+ {
+ throw new FormulaException
+ (FormulaException.UNRECOGNIZED_TOKEN, tokenVal);
+ }
+
+ Assert.verify(t != Token.UNKNOWN);
+
+ // Operands
+ if (t == Token.REF)
+ {
+ CellReference cr = new CellReference(relativeTo);
+ pos += cr.read(tokenData, pos);
+ tokenStack.push(cr);
+ }
+ else if (t == Token.REFERR)
+ {
+ CellReferenceError cr = new CellReferenceError();
+ pos += cr.read(tokenData, pos);
+ tokenStack.push(cr);
+ }
+ else if (t == Token.ERR)
+ {
+ ErrorConstant ec = new ErrorConstant();
+ pos += ec.read(tokenData, pos);
+ tokenStack.push(ec);
+ }
+ else if (t == Token.REFV)
+ {
+ SharedFormulaCellReference cr =
+ new SharedFormulaCellReference(relativeTo);
+ pos += cr.read(tokenData, pos);
+ tokenStack.push(cr);
+ }
+ else if (t == Token.REF3D)
+ {
+ CellReference3d cr = new CellReference3d(relativeTo, workbook);
+ pos += cr.read(tokenData, pos);
+ tokenStack.push(cr);
+ }
+ else if (t == Token.AREA)
+ {
+ Area a = new Area();
+ pos += a.read(tokenData, pos);
+ tokenStack.push(a);
+ }
+ else if (t == Token.AREAV)
+ {
+ SharedFormulaArea a = new SharedFormulaArea(relativeTo);
+ pos += a.read(tokenData, pos);
+ tokenStack.push(a);
+ }
+ else if (t == Token.AREA3D)
+ {
+ Area3d a = new Area3d(workbook);
+ pos += a.read(tokenData, pos);
+ tokenStack.push(a);
+ }
+ else if (t == Token.NAME)
+ {
+ Name n = new Name();
+ pos += n.read(tokenData, pos);
+ tokenStack.push(n);
+ }
+ else if (t == Token.NAMED_RANGE)
+ {
+ NameRange nr = new NameRange(nameTable);
+ pos += nr.read(tokenData, pos);
+ tokenStack.push(nr);
+ }
+ else if (t == Token.INTEGER)
+ {
+ IntegerValue i = new IntegerValue();
+ pos += i.read(tokenData, pos);
+ tokenStack.push(i);
+ }
+ else if (t == Token.DOUBLE)
+ {
+ DoubleValue d = new DoubleValue();
+ pos += d.read(tokenData, pos);
+ tokenStack.push(d);
+ }
+ else if (t == Token.BOOL)
+ {
+ BooleanValue bv = new BooleanValue();
+ pos += bv.read(tokenData, pos);
+ tokenStack.push(bv);
+ }
+ else if (t == Token.STRING)
+ {
+ StringValue sv = new StringValue(settings);
+ pos += sv.read(tokenData, pos);
+ tokenStack.push(sv);
+ }
+ else if (t == Token.MISSING_ARG)
+ {
+ MissingArg ma = new MissingArg();
+ pos += ma.read(tokenData, pos);
+ tokenStack.push(ma);
+ }
+
+ // Unary Operators
+ else if (t == Token.UNARY_PLUS)
+ {
+ UnaryPlus up = new UnaryPlus();
+ pos += up.read(tokenData, pos);
+ addOperator(up);
+ }
+ else if (t == Token.UNARY_MINUS)
+ {
+ UnaryMinus um = new UnaryMinus();
+ pos += um.read(tokenData, pos);
+ addOperator(um);
+ }
+ else if (t == Token.PERCENT)
+ {
+ Percent p = new Percent();
+ pos += p.read(tokenData, pos);
+ addOperator(p);
+ }
+
+ // Binary Operators
+ else if (t == Token.SUBTRACT)
+ {
+ Subtract s = new Subtract();
+ pos += s.read(tokenData, pos);
+ addOperator(s);
+ }
+ else if (t == Token.ADD)
+ {
+ Add s = new Add();
+ pos += s.read(tokenData, pos);
+ addOperator(s);
+ }
+ else if (t == Token.MULTIPLY)
+ {
+ Multiply s = new Multiply();
+ pos += s.read(tokenData, pos);
+ addOperator(s);
+ }
+ else if (t == Token.DIVIDE)
+ {
+ Divide s = new Divide();
+ pos += s.read(tokenData, pos);
+ addOperator(s);
+ }
+ else if (t == Token.CONCAT)
+ {
+ Concatenate c = new Concatenate();
+ pos += c.read(tokenData, pos);
+ addOperator(c);
+ }
+ else if (t == Token.POWER)
+ {
+ Power p = new Power();
+ pos += p.read(tokenData, pos);
+ addOperator(p);
+ }
+ else if (t == Token.LESS_THAN)
+ {
+ LessThan lt = new LessThan();
+ pos += lt.read(tokenData, pos);
+ addOperator(lt);
+ }
+ else if (t == Token.LESS_EQUAL)
+ {
+ LessEqual lte = new LessEqual();
+ pos += lte.read(tokenData, pos);
+ addOperator(lte);
+ }
+ else if (t == Token.GREATER_THAN)
+ {
+ GreaterThan gt = new GreaterThan();
+ pos += gt.read(tokenData, pos);
+ addOperator(gt);
+ }
+ else if (t == Token.GREATER_EQUAL)
+ {
+ GreaterEqual gte = new GreaterEqual();
+ pos += gte.read(tokenData, pos);
+ addOperator(gte);
+ }
+ else if (t == Token.NOT_EQUAL)
+ {
+ NotEqual ne = new NotEqual();
+ pos += ne.read(tokenData, pos);
+ addOperator(ne);
+ }
+ else if (t == Token.EQUAL)
+ {
+ Equal e = new Equal();
+ pos += e.read(tokenData, pos);
+ addOperator(e);
+ }
+ else if (t == Token.PARENTHESIS)
+ {
+ Parenthesis p = new Parenthesis();
+ pos += p.read(tokenData, pos);
+ addOperator(p);
+ }
+
+ // Functions
+ else if (t == Token.ATTRIBUTE)
+ {
+ Attribute a = new Attribute(settings);
+ pos += a.read(tokenData, pos);
+
+ if (a.isSum())
+ {
+ addOperator(a);
+ }
+ else if (a.isIf())
+ {
+ // Add it to a special stack for ifs
+ ifStack.push(a);
+ }
+ }
+ else if (t == Token.FUNCTION)
+ {
+ BuiltInFunction bif = new BuiltInFunction(settings);
+ pos += bif.read(tokenData, pos);
+
+ addOperator(bif);
+ }
+ else if (t == Token.FUNCTIONVARARG)
+ {
+ VariableArgFunction vaf = new VariableArgFunction(settings);
+ pos += vaf.read(tokenData, pos);
+
+ if (vaf.getFunction() != Function.ATTRIBUTE)
+ {
+ addOperator(vaf);
+ }
+ else
+ {
+ // This is part of an IF function. Get the operands, but then
+ // add it to the top of the if stack
+ vaf.getOperands(tokenStack);
+
+ Attribute ifattr = null;
+ if (ifStack.empty())
+ {
+ ifattr = new Attribute(settings);
+ }
+ else
+ {
+ ifattr = (Attribute) ifStack.pop();
+ }
+
+ ifattr.setIfConditions(vaf);
+ tokenStack.push(ifattr);
+ }
+ }
+
+ // Other things
+ else if (t == Token.MEM_FUNC)
+ {
+ MemFunc memFunc = new MemFunc();
+ handleMemoryFunction(memFunc);
+ }
+ else if (t == Token.MEM_AREA)
+ {
+ MemArea memArea = new MemArea();
+ handleMemoryFunction(memArea);
+ }
+ }
+ }
+
+ /**
+ * Handles a memory function
+ */
+ private void handleMemoryFunction(SubExpression subxp)
+ throws FormulaException
+ {
+ pos += subxp.read(tokenData, pos);
+
+ // Create new tokenStack for the sub expression
+ Stack oldStack = tokenStack;
+ tokenStack = new Stack();
+
+ parseSubExpression(subxp.getLength());
+
+ ParseItem[] subexpr = new ParseItem[tokenStack.size()];
+ int i = 0;
+ while (!tokenStack.isEmpty())
+ {
+ subexpr[i] = (ParseItem) tokenStack.pop();
+ i++;
+ }
+
+ subxp.setSubExpression(subexpr);
+
+ tokenStack = oldStack;
+ tokenStack.push(subxp);
+ }
+
+ /**
+ * Adds the specified operator to the parse tree, taking operands off
+ * the stack as appropriate
+ */
+ private void addOperator(Operator o)
+ {
+ // Get the operands off the stack
+ o.getOperands(tokenStack);
+
+ // Add this operator onto the stack
+ tokenStack.push(o);
+ }
+
+ /**
+ * Gets the formula as a string
+ */
+ public String getFormula()
+ {
+ StringBuffer sb = new StringBuffer();
+ root.getString(sb);
+ return sb.toString();
+ }
+
+ /**
+ * Adjusts all the relative cell references in this formula by the
+ * amount specified. Used when copying formulas
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ root.adjustRelativeCellReferences(colAdjust, rowAdjust);
+ }
+
+ /**
+ * Gets the bytes for the formula. This takes into account any
+ * token mapping necessary because of shared formulas
+ *
+ * @return the bytes in RPN
+ */
+ public byte[] getBytes()
+ {
+ return root.getBytes();
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ root.columnInserted(sheetIndex, col, currentSheet);
+ }
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ root.columnRemoved(sheetIndex, col, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param row the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void rowInserted(int sheetIndex, int row, boolean currentSheet)
+ {
+ root.rowInserted(sheetIndex, row, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param row the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ public void rowRemoved(int sheetIndex, int row, boolean currentSheet)
+ {
+ root.rowRemoved(sheetIndex, row, currentSheet);
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ *
+ * @return TRUE if the formula is valid import, FALSE otherwise
+ */
+ public boolean handleImportedCellReferences()
+ {
+ root.handleImportedCellReferences();
+ return root.isValid();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/UnaryMinus.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/UnaryMinus.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/UnaryMinus.java 17 Aug 2012 14:51:14 -0000 1.1
@@ -0,0 +1,68 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A cell reference in a formula
+ */
+class UnaryMinus extends UnaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public UnaryMinus()
+ {
+ }
+
+ public String getSymbol()
+ {
+ return "-";
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.UNARY_MINUS;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 2;
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing, as operators don't have cell references
+ */
+ void handleImportedCellReferences()
+ {
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/UnaryOperator.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/UnaryOperator.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/UnaryOperator.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,192 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import java.util.Stack;
+
+/**
+ * A cell reference in a formula
+ */
+abstract class UnaryOperator extends Operator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public UnaryOperator()
+ {
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ */
+ public int read(byte[] data, int pos)
+ {
+ return 0;
+ }
+
+ /**
+ * Gets the operands for this operator from the stack
+ */
+ public void getOperands(Stack s)
+ {
+ ParseItem o1 = (ParseItem) s.pop();
+
+ add(o1);
+ }
+
+ /**
+ * Gets the string
+ *
+ * @param buf
+ */
+ public void getString(StringBuffer buf)
+ {
+ ParseItem[] operands = getOperands();
+ buf.append(getSymbol());
+ operands[0].getString(buf);
+ }
+
+ /**
+ * Adjusts all the relative cell references in this formula by the
+ * amount specified. Used when copying formulas
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ ParseItem[] operands = getOperands();
+ operands[0].adjustRelativeCellReferences(colAdjust, rowAdjust);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ operands[0].columnInserted(sheetIndex, col, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ operands[0].columnRemoved(sheetIndex, col, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was inserted
+ * @param row the row number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowInserted(int sheetIndex, int row, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ operands[0].rowInserted(sheetIndex, row, currentSheet);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was removed
+ * @param row the row number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowRemoved(int sheetIndex, int row, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ operands[0].rowRemoved(sheetIndex, row, currentSheet);
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ // Get the data for the operands
+ ParseItem[] operands = getOperands();
+ byte[] data = operands[0].getBytes();
+
+ // Add on the operator byte
+ byte[] newdata = new byte[data.length + 1];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ newdata[data.length] = getToken().getCode();
+
+ return newdata;
+ }
+
+ /**
+ * Abstract method which gets the binary operator string symbol
+ *
+ * @return the string symbol for this token
+ */
+ abstract String getSymbol();
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ abstract Token getToken();
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing, as operators don't have cell references
+ */
+ void handleImportedCellReferences()
+ {
+ ParseItem[] operands = getOperands();
+ operands[0].handleImportedCellReferences();
+ }
+
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/UnaryPlus.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/UnaryPlus.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/UnaryPlus.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,68 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A cell reference in a formula
+ */
+class UnaryPlus extends UnaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public UnaryPlus()
+ {
+ }
+
+ public String getSymbol()
+ {
+ return "+";
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.UNARY_PLUS;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 2;
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing, as operators don't have cell references
+ */
+ void handleImportedCellReferences()
+ {
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Union.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Union.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Union.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,59 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * A union of two cell ranges - the "," operator
+ */
+class Union extends BinaryOperator implements ParsedThing
+{
+ /**
+ * Constructor
+ */
+ public Union()
+ {
+ }
+
+ public String getSymbol()
+ {
+ return ",";
+ }
+
+ /**
+ * Abstract method which gets the token for this operator
+ *
+ * @return the string symbol for this token
+ */
+ Token getToken()
+ {
+ return Token.UNION;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 4;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/VariableArgFunction.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/VariableArgFunction.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/VariableArgFunction.java 17 Aug 2012 14:51:15 -0000 1.1
@@ -0,0 +1,348 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+import java.util.Stack;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.IntegerHelper;
+
+/**
+ * A built in function in a formula. These functions take a variable
+ * number of arguments, such as a range (eg. SUM etc)
+ */
+class VariableArgFunction extends Operator implements ParsedThing
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(VariableArgFunction.class);
+
+ /**
+ * The function
+ */
+ private Function function;
+
+ /**
+ * The number of arguments
+ */
+ private int arguments;
+
+ /**
+ * Flag which indicates whether this was initialized from the client
+ * api or from an excel sheet
+ */
+ private boolean readFromSheet;
+
+ /**
+ * The workbooks settings
+ */
+ private WorkbookSettings settings;
+
+ /**
+ * Constructor
+ */
+ public VariableArgFunction(WorkbookSettings ws)
+ {
+ readFromSheet = true;
+ settings = ws;
+ }
+
+ /**
+ * Constructor used when parsing a function from a string
+ *
+ * @param f the function
+ * @param a the number of arguments
+ */
+ public VariableArgFunction(Function f, int a, WorkbookSettings ws)
+ {
+ function = f;
+ arguments = a;
+ readFromSheet = false;
+ settings = ws;
+ }
+
+ /**
+ * Reads the ptg data from the array starting at the specified position
+ *
+ * @param data the RPN array
+ * @param pos the current position in the array, excluding the ptg identifier
+ * @return the number of bytes read
+ * @exception FormulaException
+ */
+ public int read(byte[] data, int pos) throws FormulaException
+ {
+ arguments = data[pos];
+ int index = IntegerHelper.getInt(data[pos+1], data[pos+2]);
+ function = Function.getFunction(index);
+
+ if (function == Function.UNKNOWN)
+ {
+ throw new FormulaException(FormulaException.UNRECOGNIZED_FUNCTION,
+ index);
+ }
+
+ return 3;
+ }
+
+ /**
+ * Gets the operands for this operator from the stack
+ */
+ public void getOperands(Stack s)
+ {
+ // parameters are in the correct order, god damn them
+ ParseItem[] items = new ParseItem[arguments];
+
+ for (int i = arguments - 1; i >= 0 ; i--)
+ {
+ ParseItem pi = (ParseItem) s.pop();
+
+ items[i] = pi;
+ }
+
+ for (int i = 0 ; i < arguments; i++)
+ {
+ add(items[i]);
+ }
+ }
+
+ public void getString(StringBuffer buf)
+ {
+ buf.append(function.getName(settings));
+ buf.append('(');
+
+ if (arguments > 0)
+ {
+ ParseItem[] operands = getOperands();
+ if (readFromSheet)
+ {
+ // arguments are in the same order they were specified
+ operands[0].getString(buf);
+
+ for (int i = 1; i < arguments; i++)
+ {
+ buf.append(',');
+ operands[i].getString(buf);
+ }
+ }
+ else
+ {
+ // arguments are stored in the reverse order to which they
+ // were specified, so iterate through them backwards
+ operands[arguments - 1].getString(buf);
+
+ for (int i = arguments - 2; i >= 0 ; i--)
+ {
+ buf.append(',');
+ operands[i].getString(buf);
+ }
+ }
+ }
+
+ buf.append(')');
+ }
+
+ /**
+ * Adjusts all the relative cell references in this formula by the
+ * amount specified. Used when copying formulas
+ *
+ * @param colAdjust the amount to add on to each relative cell reference
+ * @param rowAdjust the amount to add on to each relative row reference
+ */
+ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
+ {
+ ParseItem[] operands = getOperands();
+
+ for (int i = 0 ; i < operands.length ; i++)
+ {
+ operands[i].adjustRelativeCellReferences(colAdjust, rowAdjust);
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnInserted(int sheetIndex, int col, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ for (int i = 0 ; i < operands.length ; i++)
+ {
+ operands[i].columnInserted(sheetIndex, col, currentSheet);
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the column was removed
+ * @param col the column number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void columnRemoved(int sheetIndex, int col, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ for (int i = 0 ; i < operands.length ; i++)
+ {
+ operands[i].columnRemoved(sheetIndex, col, currentSheet);
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was inserted
+ * @param row the row number which was inserted
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowInserted(int sheetIndex, int row, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ for (int i = 0 ; i < operands.length ; i++)
+ {
+ operands[i].rowInserted(sheetIndex, row, currentSheet);
+ }
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Tells
+ * the formula parser to update all of its cell references beyond this
+ * column
+ *
+ * @param sheetIndex the sheet on which the row was removed
+ * @param row the row number which was removed
+ * @param currentSheet TRUE if this formula is on the sheet in which the
+ * column was inserted, FALSE otherwise
+ */
+ void rowRemoved(int sheetIndex, int row, boolean currentSheet)
+ {
+ ParseItem[] operands = getOperands();
+ for (int i = 0 ; i < operands.length ; i++)
+ {
+ operands[i].rowRemoved(sheetIndex, row, currentSheet);
+ }
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ * Does nothing, as operators don't have cell references
+ */
+ void handleImportedCellReferences()
+ {
+ ParseItem[] operands = getOperands();
+ for (int i = 0 ; i < operands.length ; i++)
+ {
+ operands[i].handleImportedCellReferences();
+ }
+ }
+
+ /**
+ * Gets the underlying function
+ */
+ Function getFunction()
+ {
+ return function;
+ }
+
+ /**
+ * Gets the token representation of this item in RPN
+ *
+ * @return the bytes applicable to this formula
+ */
+ byte[] getBytes()
+ {
+ handleSpecialCases();
+
+ // Get the data for the operands - in the correct order
+ ParseItem[] operands = getOperands();
+ byte[] data = new byte[0];
+
+ for (int i = 0 ; i < operands.length ; i++)
+ {
+ byte[] opdata = operands[i].getBytes();
+
+ // Grow the array
+ byte[] newdata = new byte[data.length + opdata.length];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ System.arraycopy(opdata, 0, newdata, data.length, opdata.length);
+ data = newdata;
+ }
+
+ // Add on the operator byte
+ byte[] newdata = new byte[data.length + 4];
+ System.arraycopy(data, 0, newdata, 0, data.length);
+ newdata[data.length] = !useAlternateCode() ?
+ Token.FUNCTIONVARARG.getCode() : Token.FUNCTIONVARARG.getCode2() ;
+ newdata[data.length+1] = (byte) arguments;
+ IntegerHelper.getTwoBytes(function.getCode(), newdata, data.length+2);
+
+ return newdata;
+ }
+
+ /**
+ * Gets the precedence for this operator. Operator precedents run from
+ * 1 to 5, one being the highest, 5 being the lowest
+ *
+ * @return the operator precedence
+ */
+ int getPrecedence()
+ {
+ return 3;
+ }
+
+ /**
+ * Handles functions which form a special case
+ */
+ private void handleSpecialCases()
+ {
+ // Handle the array functions. Tell all the Area records to
+ // use their alternative token code
+ if (function == Function.SUMPRODUCT)
+ {
+ // Get the data for the operands - in reverse order
+ ParseItem[] operands = getOperands();
+
+ for (int i = operands.length - 1 ; i >= 0 ; i--)
+ {
+ if (operands[i] instanceof Area)
+ {
+ operands[i].setAlternateCode();
+ }
+ }
+ }
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/biff/formula/Yylex.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/biff/formula/Yylex.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/biff/formula/Yylex.java 17 Aug 2012 14:51:16 -0000 1.1
@@ -0,0 +1,813 @@
+/* The following code was generated by JFlex 1.4.1 on 25/11/08 00:40 */
+
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.biff.formula;
+
+/**
+ * This file is generated by JLex. Do not alter the contents of this file
+ * because changes will be overridden
+ */
+
+import jxl.biff.WorkbookMethods;
+
+
+/**
+ * This class is a scanner generated by
+ * JFlex 1.4.1
+ * on 25/11/08 00:40 from the specification file
+ * xlformula.flex
+ */
+class Yylex {
+
+ /** This character denotes the end of file */
+ public static final int YYEOF = -1;
+
+ /** initial size of the lookahead buffer */
+ private static final int ZZ_BUFFERSIZE = 16384;
+
+ /** lexical states */
+ public static final int YYSTRING = 1;
+ public static final int YYINITIAL = 0;
+
+ /**
+ * Translates characters to character classes
+ */
+ private static final String ZZ_CMAP_PACKED =
+ "\10\0\3\25\25\0\1\25\1\24\1\21\1\26\1\10\2\0\1\22"+
+ "\1\5\1\6\1\41\1\37\1\4\1\40\1\7\1\33\1\34\11\2"+
+ "\1\3\1\0\1\44\1\43\1\42\1\36\1\0\1\16\2\1\1\30"+
+ "\1\14\1\15\2\1\1\31\2\1\1\17\1\35\1\27\3\1\1\12"+
+ "\1\20\1\11\1\13\1\32\4\1\4\0\1\23\1\0\32\1\uff85\0";
+
+ /**
+ * Translates characters to character classes
+ */
+ private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
+
+ /**
+ * Translates DFA states to action switch labels.
+ */
+ private static final int [] ZZ_ACTION = zzUnpackAction();
+
+ private static final String ZZ_ACTION_PACKED_0 =
+ "\1\0\1\1\1\2\1\3\1\4\1\5\1\6\1\7"+
+ "\1\0\2\2\1\10\1\0\1\11\1\0\1\12\1\13"+
+ "\1\14\1\15\1\16\1\17\1\20\1\1\1\21\1\2"+
+ "\1\22\1\0\1\23\1\0\1\2\3\0\2\2\5\0"+
+ "\1\24\1\25\1\26\1\2\1\0\1\27\1\0\1\22"+
+ "\2\0\1\30\1\0\2\2\10\0\1\27\1\0\1\31"+
+ "\1\0\1\32\10\0\1\33\2\0\1\31\2\0\1\34"+
+ "\4\0\1\35\3\0\1\35\1\0\1\36\1\0";
+
+ private static int [] zzUnpackAction() {
+ int [] result = new int[94];
+ int offset = 0;
+ offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
+ return result;
+ }
+
+ private static int zzUnpackAction(String packed, int offset, int [] result) {
+ int i = 0; /* index in packed string */
+ int j = offset; /* index in unpacked array */
+ int l = packed.length();
+ while (i < l) {
+ int count = packed.charAt(i++);
+ int value = packed.charAt(i++);
+ do result[j++] = value; while (--count > 0);
+ }
+ return j;
+ }
+
+
+ /**
+ * Translates a state to a row index in the transition table
+ */
+ private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
+
+ private static final String ZZ_ROWMAP_PACKED_0 =
+ "\0\0\0\45\0\112\0\157\0\224\0\224\0\224\0\224"+
+ "\0\271\0\336\0\u0103\0\224\0\u0128\0\224\0\u014d\0\224"+
+ "\0\224\0\224\0\224\0\u0172\0\224\0\u0197\0\u01bc\0\224"+
+ "\0\u01e1\0\u0206\0\u022b\0\224\0\u0250\0\u0275\0\u029a\0\u02bf"+
+ "\0\u02e4\0\u0309\0\u032e\0\u0353\0\u0378\0\u039d\0\u03c2\0\u03e7"+
+ "\0\224\0\224\0\224\0\u040c\0\u0431\0\u0456\0\u047b\0\u04a0"+
+ "\0\u04c5\0\u04ea\0\u02bf\0\u050f\0\u0534\0\u0559\0\u057e\0\u05a3"+
+ "\0\u05c8\0\u05ed\0\u0612\0\u0637\0\u065c\0\u0681\0\224\0\u06a6"+
+ "\0\u06cb\0\u06cb\0\u040c\0\u06f0\0\u0715\0\u073a\0\u075f\0\u0784"+
+ "\0\u07a9\0\u07ce\0\u07f3\0\u0818\0\u0818\0\u083d\0\u0862\0\u0887"+
+ "\0\u08ac\0\224\0\u08d1\0\u08f6\0\u091b\0\u0940\0\u0965\0\u098a"+
+ "\0\u09af\0\u09d4\0\224\0\u09f9\0\u0a1e\0\u0a1e";
+
+ private static int [] zzUnpackRowMap() {
+ int [] result = new int[94];
+ int offset = 0;
+ offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
+ return result;
+ }
+
+ private static int zzUnpackRowMap(String packed, int offset, int [] result) {
+ int i = 0; /* index in packed string */
+ int j = offset; /* index in unpacked array */
+ int l = packed.length();
+ while (i < l) {
+ int high = packed.charAt(i++) << 16;
+ result[j++] = high | packed.charAt(i++);
+ }
+ return j;
+ }
+
+ /**
+ * The transition table of the DFA
+ */
+ private static final int [] ZZ_TRANS = zzUnpackTrans();
+
+ private static final String ZZ_TRANS_PACKED_0 =
+ "\1\0\1\3\1\4\1\5\1\6\1\7\1\10\1\0"+
+ "\1\11\1\12\3\3\1\13\3\3\1\14\1\15\2\0"+
+ "\1\16\1\17\4\3\1\20\1\4\1\3\1\0\1\21"+
+ "\1\22\1\23\1\24\1\25\1\26\21\27\1\30\23\27"+
+ "\1\0\1\31\1\32\1\33\1\0\1\34\2\0\1\35"+
+ "\10\31\2\0\1\36\1\37\2\0\4\31\1\0\1\32"+
+ "\1\31\11\0\1\4\4\0\1\40\24\0\1\4\56\0"+
+ "\1\41\7\0\10\41\6\0\4\41\2\0\1\41\10\0"+
+ "\1\31\1\32\1\33\1\0\1\34\2\0\1\35\1\31"+
+ "\1\42\6\31\2\0\1\36\1\37\2\0\4\31\1\0"+
+ "\1\32\1\31\10\0\1\31\1\32\1\33\1\0\1\34"+
+ "\2\0\1\35\5\31\1\43\2\31\2\0\1\36\1\37"+
+ "\2\0\4\31\1\0\1\32\1\31\7\0\22\15\1\44"+
+ "\22\15\12\0\1\45\14\0\1\46\1\47\1\0\1\50"+
+ "\55\0\1\51\43\0\1\52\1\53\1\0\21\27\1\0"+
+ "\23\27\1\0\1\54\1\32\1\33\1\0\1\34\2\0"+
+ "\1\35\10\54\2\0\1\36\1\37\2\0\4\54\1\0"+
+ "\1\32\1\54\10\0\1\36\1\32\1\55\5\0\10\36"+
+ "\2\0\1\36\3\0\4\36\1\0\1\32\1\36\10\0"+
+ "\1\56\6\0\1\57\10\56\6\0\4\56\2\0\1\56"+
+ "\11\0\1\60\31\0\1\60\11\0\2\36\6\0\10\36"+
+ "\2\0\1\36\3\0\4\36\1\0\2\36\10\0\1\61"+
+ "\6\0\1\62\10\61\6\0\4\61\2\0\1\61\11\0"+
+ "\1\63\31\0\1\63\11\0\1\64\1\60\1\33\4\0"+
+ "\1\35\10\64\6\0\4\64\1\0\1\60\1\64\10\0"+
+ "\1\54\1\32\1\33\1\0\1\34\2\0\1\35\2\54"+
+ "\1\65\5\54\2\0\1\36\1\37\2\0\4\54\1\0"+
+ "\1\32\1\54\10\0\1\54\1\32\1\33\1\0\1\34"+
+ "\2\0\1\35\6\54\1\66\1\54\2\0\1\36\1\37"+
+ "\2\0\4\54\1\0\1\32\1\54\33\0\1\67\34\0"+
+ "\1\70\43\0\1\71\2\0\1\72\57\0\1\73\31\0"+
+ "\1\74\27\0\1\54\1\36\2\0\1\34\3\0\10\54"+
+ "\2\0\1\36\1\37\2\0\4\54\1\0\1\36\1\54"+
+ "\10\0\1\75\6\0\1\76\10\75\6\0\4\75\2\0"+
+ "\1\75\10\0\1\77\7\0\10\77\6\0\4\77\2\0"+
+ "\1\77\10\0\1\56\7\0\10\56\6\0\4\56\2\0"+
+ "\1\56\11\0\1\60\1\55\30\0\1\60\11\0\1\100"+
+ "\1\101\5\0\1\102\10\100\6\0\4\100\1\0\1\101"+
+ "\1\100\10\0\1\61\7\0\10\61\6\0\4\61\2\0"+
+ "\1\61\11\0\1\60\1\33\4\0\1\35\23\0\1\60"+
+ "\11\0\1\54\1\36\2\0\1\34\3\0\3\54\1\103"+
+ "\4\54\2\0\1\36\1\37\2\0\4\54\1\0\1\36"+
+ "\1\54\10\0\1\54\1\36\2\0\1\34\3\0\7\54"+
+ "\1\65\2\0\1\36\1\37\2\0\4\54\1\0\1\36"+
+ "\1\54\10\0\1\104\6\0\1\105\10\104\6\0\4\104"+
+ "\2\0\1\104\24\0\1\106\46\0\1\107\15\0\1\106"+
+ "\44\0\1\110\41\0\1\111\31\0\1\112\26\0\1\113"+
+ "\1\114\5\0\1\115\10\113\6\0\4\113\1\0\1\114"+
+ "\1\113\10\0\1\75\7\0\10\75\6\0\4\75\2\0"+
+ "\1\75\11\0\1\101\5\0\1\102\23\0\1\101\12\0"+
+ "\1\101\31\0\1\101\11\0\1\116\1\117\1\120\4\0"+
+ "\1\121\10\116\6\0\4\116\1\0\1\117\1\116\10\0"+
+ "\1\104\7\0\10\104\6\0\4\104\2\0\1\104\33\0"+
+ "\1\122\37\0\1\106\41\0\1\123\63\0\1\124\24\0"+
+ "\1\125\33\0\1\114\5\0\1\115\23\0\1\114\12\0"+
+ "\1\114\31\0\1\114\12\0\1\117\1\120\4\0\1\121"+
+ "\23\0\1\117\12\0\1\117\1\126\30\0\1\117\11\0"+
+ "\1\127\6\0\1\130\10\127\6\0\4\127\2\0\1\127"+
+ "\11\0\1\117\31\0\1\117\46\0\1\122\42\0\1\106"+
+ "\24\0\1\106\31\0\1\131\6\0\1\132\10\131\6\0"+
+ "\4\131\2\0\1\131\10\0\1\133\7\0\10\133\6\0"+
+ "\4\133\2\0\1\133\10\0\1\127\7\0\10\127\6\0"+
+ "\4\127\2\0\1\127\10\0\1\134\1\135\5\0\1\136"+
+ "\10\134\6\0\4\134\1\0\1\135\1\134\10\0\1\131"+
+ "\7\0\10\131\6\0\4\131\2\0\1\131\11\0\1\135"+
+ "\5\0\1\136\23\0\1\135\12\0\1\135\31\0\1\135"+
+ "\10\0";
+
+ private static int [] zzUnpackTrans() {
+ int [] result = new int[2627];
+ int offset = 0;
+ offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
+ return result;
+ }
+
+ private static int zzUnpackTrans(String packed, int offset, int [] result) {
+ int i = 0; /* index in packed string */
+ int j = offset; /* index in unpacked array */
+ int l = packed.length();
+ while (i < l) {
+ int count = packed.charAt(i++);
+ int value = packed.charAt(i++);
+ value--;
+ do result[j++] = value; while (--count > 0);
+ }
+ return j;
+ }
+
+
+ /* error codes */
+ private static final int ZZ_UNKNOWN_ERROR = 0;
+ private static final int ZZ_NO_MATCH = 1;
+ private static final int ZZ_PUSHBACK_2BIG = 2;
+
+ /* error messages for the codes above */
+ private static final String ZZ_ERROR_MSG[] = {
+ "Unkown internal scanner error",
+ "Error: could not match input",
+ "Error: pushback value was too large"
+ };
+
+ /**
+ * ZZ_ATTRIBUTE[aState] contains the attributes of state aState
+ */
+ private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
+
+ private static final String ZZ_ATTRIBUTE_PACKED_0 =
+ "\1\0\3\1\4\11\1\0\2\1\1\11\1\0\1\11"+
+ "\1\0\4\11\1\1\1\11\2\1\1\11\2\1\1\0"+
+ "\1\11\1\0\1\1\3\0\2\1\5\0\3\11\1\1"+
+ "\1\0\1\1\1\0\1\1\2\0\1\1\1\0\2\1"+
+ "\10\0\1\11\1\0\1\1\1\0\1\1\10\0\1\1"+
+ "\2\0\1\1\2\0\1\11\4\0\1\1\3\0\1\11"+
+ "\1\0\1\1\1\0";
+
+ private static int [] zzUnpackAttribute() {
+ int [] result = new int[94];
+ int offset = 0;
+ offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
+ return result;
+ }
+
+ private static int zzUnpackAttribute(String packed, int offset, int [] result) {
+ int i = 0; /* index in packed string */
+ int j = offset; /* index in unpacked array */
+ int l = packed.length();
+ while (i < l) {
+ int count = packed.charAt(i++);
+ int value = packed.charAt(i++);
+ do result[j++] = value; while (--count > 0);
+ }
+ return j;
+ }
+
+ /** the input device */
+ private java.io.Reader zzReader;
+
+ /** the current state of the DFA */
+ private int zzState;
+
+ /** the current lexical state */
+ private int zzLexicalState = YYINITIAL;
+
+ /** this buffer contains the current text to be matched and is
+ the source of the yytext() string */
+ private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
+
+ /** the textposition at the last accepting state */
+ private int zzMarkedPos;
+
+ /** the textposition at the last state to be included in yytext */
+ private int zzPushbackPos;
+
+ /** the current text position in the buffer */
+ private int zzCurrentPos;
+
+ /** startRead marks the beginning of the yytext() string in the buffer */
+ private int zzStartRead;
+
+ /** endRead marks the last character in the buffer, that has been read
+ from input */
+ private int zzEndRead;
+
+ /** number of newlines encountered up to the start of the matched text */
+ private int yyline;
+
+ /** the number of characters up to the start of the matched text */
+ private int yychar;
+
+ /**
+ * the number of characters from the last newline up to the start of the
+ * matched text
+ */
+ private int yycolumn;
+
+ /**
+ * zzAtBOL == true <=> the scanner is currently at the beginning of a line
+ */
+ private boolean zzAtBOL = true;
+
+ /** zzAtEOF == true <=> the scanner is at the EOF */
+ private boolean zzAtEOF;
+
+ /* user code: */
+ int getPos() { return yychar ; }
+ private boolean emptyString;
+ private ExternalSheet externalSheet;
+ private WorkbookMethods nameTable;
+
+ void setExternalSheet(ExternalSheet es)
+ {
+ externalSheet = es;
+ }
+
+ void setNameTable(WorkbookMethods nt)
+ {
+ nameTable = nt;
+ }
+
+
+ /**
+ * Creates a new scanner
+ * There is also a java.io.InputStream version of this constructor.
+ *
+ * @param in the java.io.Reader to read input from.
+ */
+ Yylex(java.io.Reader in) {
+ this.zzReader = in;
+ }
+
+ /**
+ * Creates a new scanner.
+ * There is also java.io.Reader version of this constructor.
+ *
+ * @param in the java.io.Inputstream to read input from.
+ */
+ Yylex(java.io.InputStream in) {
+ this(new java.io.InputStreamReader(in));
+ }
+
+ /**
+ * Unpacks the compressed character translation table.
+ *
+ * @param packed the packed character translation table
+ * @return the unpacked character translation table
+ */
+ private static char [] zzUnpackCMap(String packed) {
+ char [] map = new char[0x10000];
+ int i = 0; /* index in packed string */
+ int j = 0; /* index in unpacked array */
+ while (i < 100) {
+ int count = packed.charAt(i++);
+ char value = packed.charAt(i++);
+ do map[j++] = value; while (--count > 0);
+ }
+ return map;
+ }
+
+
+ /**
+ * Refills the input buffer.
+ *
+ * @return false
, iff there was new input.
+ *
+ * @exception java.io.IOException if any I/O-Error occurs
+ */
+ private boolean zzRefill() throws java.io.IOException {
+
+ /* first: make room (if you can) */
+ if (zzStartRead > 0) {
+ System.arraycopy(zzBuffer, zzStartRead,
+ zzBuffer, 0,
+ zzEndRead-zzStartRead);
+
+ /* translate stored positions */
+ zzEndRead-= zzStartRead;
+ zzCurrentPos-= zzStartRead;
+ zzMarkedPos-= zzStartRead;
+ zzPushbackPos-= zzStartRead;
+ zzStartRead = 0;
+ }
+
+ /* is the buffer big enough? */
+ if (zzCurrentPos >= zzBuffer.length) {
+ /* if not: blow it up */
+ char newBuffer[] = new char[zzCurrentPos*2];
+ System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length);
+ zzBuffer = newBuffer;
+ }
+
+ /* finally: fill the buffer with new input */
+ int numRead = zzReader.read(zzBuffer, zzEndRead,
+ zzBuffer.length-zzEndRead);
+
+ if (numRead < 0) {
+ return true;
+ }
+ else {
+ zzEndRead+= numRead;
+ return false;
+ }
+ }
+
+
+ /**
+ * Closes the input stream.
+ */
+ public final void yyclose() throws java.io.IOException {
+ zzAtEOF = true; /* indicate end of file */
+ zzEndRead = zzStartRead; /* invalidate buffer */
+
+ if (zzReader != null)
+ zzReader.close();
+ }
+
+
+ /**
+ * Resets the scanner to read from a new input stream.
+ * Does not close the old reader.
+ *
+ * All internal variables are reset, the old input stream
+ * cannot be reused (internal buffer is discarded and lost).
+ * Lexical state is set to ZZ_INITIAL .
+ *
+ * @param reader the new input stream
+ */
+ public final void yyreset(java.io.Reader reader) {
+ zzReader = reader;
+ zzAtBOL = true;
+ zzAtEOF = false;
+ zzEndRead = zzStartRead = 0;
+ zzCurrentPos = zzMarkedPos = zzPushbackPos = 0;
+ yyline = yychar = yycolumn = 0;
+ zzLexicalState = YYINITIAL;
+ }
+
+
+ /**
+ * Returns the current lexical state.
+ */
+ public final int yystate() {
+ return zzLexicalState;
+ }
+
+
+ /**
+ * Enters a new lexical state
+ *
+ * @param newState the new lexical state
+ */
+ public final void yybegin(int newState) {
+ zzLexicalState = newState;
+ }
+
+
+ /**
+ * Returns the text matched by the current regular expression.
+ */
+ public final String yytext() {
+ return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead );
+ }
+
+
+ /**
+ * Returns the character at position pos from the
+ * matched text.
+ *
+ * It is equivalent to yytext().charAt(pos), but faster
+ *
+ * @param pos the position of the character to fetch.
+ * A value from 0 to yylength()-1.
+ *
+ * @return the character at position pos
+ */
+ public final char yycharat(int pos) {
+ return zzBuffer[zzStartRead+pos];
+ }
+
+
+ /**
+ * Returns the length of the matched text region.
+ */
+ public final int yylength() {
+ return zzMarkedPos-zzStartRead;
+ }
+
+
+ /**
+ * Reports an error that occured while scanning.
+ *
+ * In a wellformed scanner (no or only correct usage of
+ * yypushback(int) and a match-all fallback rule) this method
+ * will only be called with things that "Can't Possibly Happen".
+ * If this method is called, something is seriously wrong
+ * (e.g. a JFlex bug producing a faulty scanner etc.).
+ *
+ * Usual syntax/scanner level error handling should be done
+ * in error fallback rules.
+ *
+ * @param errorCode the code of the errormessage to display
+ */
+ private void zzScanError(int errorCode) {
+ String message;
+ try {
+ message = ZZ_ERROR_MSG[errorCode];
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
+ }
+
+ throw new Error(message);
+ }
+
+
+ /**
+ * Pushes the specified amount of characters back into the input stream.
+ *
+ * They will be read again by then next call of the scanning method
+ *
+ * @param number the number of characters to be read again.
+ * This number must not be greater than yylength()!
+ */
+ public void yypushback(int number) {
+ if ( number > yylength() )
+ zzScanError(ZZ_PUSHBACK_2BIG);
+
+ zzMarkedPos -= number;
+ }
+
+
+ /**
+ * Resumes scanning until the next regular expression is matched,
+ * the end of input is encountered or an I/O-Error occurs.
+ *
+ * @return the next token
+ * @exception java.io.IOException if any I/O-Error occurs
+ */
+ public ParseItem yylex() throws java.io.IOException, jxl.biff.formula.FormulaException
+ {
+ int zzInput;
+ int zzAction;
+
+ // cached fields:
+ int zzCurrentPosL;
+ int zzMarkedPosL;
+ int zzEndReadL = zzEndRead;
+ char [] zzBufferL = zzBuffer;
+ char [] zzCMapL = ZZ_CMAP;
+
+ int [] zzTransL = ZZ_TRANS;
+ int [] zzRowMapL = ZZ_ROWMAP;
+ int [] zzAttrL = ZZ_ATTRIBUTE;
+
+ while (true) {
+ zzMarkedPosL = zzMarkedPos;
+
+ yychar+= zzMarkedPosL-zzStartRead;
+
+ boolean zzR = false;
+ for (zzCurrentPosL = zzStartRead; zzCurrentPosL < zzMarkedPosL;
+ zzCurrentPosL++) {
+ switch (zzBufferL[zzCurrentPosL]) {
+ case '\u000B':
+ case '\u000C':
+ case '\u0085':
+ case '\u2028':
+ case '\u2029':
+ yyline++;
+ zzR = false;
+ break;
+ case '\r':
+ yyline++;
+ zzR = true;
+ break;
+ case '\n':
+ if (zzR)
+ zzR = false;
+ else {
+ yyline++;
+ }
+ break;
+ default:
+ zzR = false;
+ }
+ }
+
+ if (zzR) {
+ // peek one character ahead if it is \n (if we have counted one line too much)
+ boolean zzPeek;
+ if (zzMarkedPosL < zzEndReadL)
+ zzPeek = zzBufferL[zzMarkedPosL] == '\n';
+ else if (zzAtEOF)
+ zzPeek = false;
+ else {
+ boolean eof = zzRefill();
+ zzEndReadL = zzEndRead;
+ zzMarkedPosL = zzMarkedPos;
+ zzBufferL = zzBuffer;
+ if (eof)
+ zzPeek = false;
+ else
+ zzPeek = zzBufferL[zzMarkedPosL] == '\n';
+ }
+ if (zzPeek) yyline--;
+ }
+ zzAction = -1;
+
+ zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
+
+ zzState = zzLexicalState;
+
+
+ zzForAction: {
+ while (true) {
+
+ if (zzCurrentPosL < zzEndReadL)
+ zzInput = zzBufferL[zzCurrentPosL++];
+ else if (zzAtEOF) {
+ zzInput = YYEOF;
+ break zzForAction;
+ }
+ else {
+ // store back cached positions
+ zzCurrentPos = zzCurrentPosL;
+ zzMarkedPos = zzMarkedPosL;
+ boolean eof = zzRefill();
+ // get translated positions and possibly new buffer
+ zzCurrentPosL = zzCurrentPos;
+ zzMarkedPosL = zzMarkedPos;
+ zzBufferL = zzBuffer;
+ zzEndReadL = zzEndRead;
+ if (eof) {
+ zzInput = YYEOF;
+ break zzForAction;
+ }
+ else {
+ zzInput = zzBufferL[zzCurrentPosL++];
+ }
+ }
+ int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ];
+ if (zzNext == -1) break zzForAction;
+ zzState = zzNext;
+
+ int zzAttributes = zzAttrL[zzState];
+ if ( (zzAttributes & 1) == 1 ) {
+ zzAction = zzState;
+ zzMarkedPosL = zzCurrentPosL;
+ if ( (zzAttributes & 8) == 8 ) break zzForAction;
+ }
+
+ }
+ }
+
+ // store back cached position
+ zzMarkedPos = zzMarkedPosL;
+
+ switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
+ case 12:
+ { return new Minus() ;
+ }
+ case 31: break;
+ case 7:
+ { return new CloseParentheses() ;
+ }
+ case 32: break;
+ case 3:
+ { return new IntegerValue(yytext()) ;
+ }
+ case 33: break;
+ case 24:
+ { return new DoubleValue(yytext()) ;
+ }
+ case 34: break;
+ case 29:
+ { return new ColumnRange3d(yytext(),externalSheet) ;
+ }
+ case 35: break;
+ case 4:
+ { return new RangeSeparator();
+ }
+ case 36: break;
+ case 10:
+ { return new Divide() ;
+ }
+ case 37: break;
+ case 25:
+ { return new CellReference3d(yytext(),externalSheet) ;
+ }
+ case 38: break;
+ case 26:
+ { return new BooleanValue(yytext());
+ }
+ case 39: break;
+ case 15:
+ { return new Equal() ;
+ }
+ case 40: break;
+ case 17:
+ { yybegin(YYINITIAL); if (emptyString) return new StringValue("");
+ }
+ case 41: break;
+ case 8:
+ { emptyString = true; yybegin(YYSTRING);
+ }
+ case 42: break;
+ case 21:
+ { return new NotEqual() ;
+ }
+ case 43: break;
+ case 22:
+ { return new LessEqual() ;
+ }
+ case 44: break;
+ case 16:
+ { return new LessThan() ;
+ }
+ case 45: break;
+ case 5:
+ { return new ArgumentSeparator() ;
+ }
+ case 46: break;
+ case 30:
+ { return new Area3d(yytext(),externalSheet) ;
+ }
+ case 47: break;
+ case 14:
+ { return new GreaterThan() ;
+ }
+ case 48: break;
+ case 18:
+ { return new CellReference(yytext()) ;
+ }
+ case 49: break;
+ case 20:
+ { return new GreaterEqual() ;
+ }
+ case 50: break;
+ case 27:
+ { return new Area(yytext()) ;
+ }
+ case 51: break;
+ case 23:
+ { return new ColumnRange(yytext());
+ }
+ case 52: break;
+ case 1:
+ { emptyString = false; return new StringValue(yytext()) ;
+ }
+ case 53: break;
+ case 2:
+ { return new NameRange(yytext(), nameTable);
+ }
+ case 54: break;
+ case 19:
+ { return new StringFunction(yytext()) ;
+ }
+ case 55: break;
+ case 11:
+ { return new Plus() ;
+ }
+ case 56: break;
+ case 28:
+ { return new ErrorConstant(yytext());
+ }
+ case 57: break;
+ case 9:
+ {
+ }
+ case 58: break;
+ case 13:
+ { return new Multiply() ;
+ }
+ case 59: break;
+ case 6:
+ { return new OpenParentheses() ;
+ }
+ case 60: break;
+ default:
+ if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
+ zzAtEOF = true;
+ return null;
+ }
+ else {
+ zzScanError(ZZ_NO_MATCH);
+ }
+ }
+ }
+ }
+
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/demo/BiffDump.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/demo/BiffDump.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/demo/BiffDump.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,367 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.demo;
+
+
+import java.io.BufferedWriter;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+
+import java.util.HashMap;
+
+import jxl.WorkbookSettings;
+import jxl.biff.Type;
+import jxl.read.biff.BiffException;
+import jxl.read.biff.BiffRecordReader;
+import jxl.read.biff.File;
+import jxl.read.biff.Record;
+
+/**
+ * Generates a biff dump of the specified excel file
+ */
+class BiffDump
+{
+ private BufferedWriter writer;
+ private BiffRecordReader reader;
+
+ private HashMap recordNames;
+
+ private int xfIndex;
+ private int fontIndex;
+ private int bofs;
+
+ private static final int bytesPerLine = 16;
+
+ /**
+ * Constructor
+ *
+ * @param file the file
+ * @param os the output stream
+ * @exception IOException
+ * @exception BiffException
+ */
+ public BiffDump(java.io.File file, OutputStream os)
+ throws IOException, BiffException
+ {
+ writer = new BufferedWriter(new OutputStreamWriter(os));
+ FileInputStream fis = new FileInputStream(file);
+ File f = new File(fis, new WorkbookSettings());
+ reader = new BiffRecordReader(f);
+
+ buildNameHash();
+ dump();
+
+ writer.flush();
+ writer.close();
+ fis.close();
+ }
+
+ /**
+ * Builds the hashmap of record names
+ */
+ private void buildNameHash()
+ {
+ recordNames = new HashMap(50);
+
+ recordNames.put(Type.BOF, "BOF");
+ recordNames.put(Type.EOF, "EOF");
+ recordNames.put(Type.FONT, "FONT");
+ recordNames.put(Type.SST, "SST");
+ recordNames.put(Type.LABELSST, "LABELSST");
+ recordNames.put(Type.WRITEACCESS, "WRITEACCESS");
+ recordNames.put(Type.FORMULA, "FORMULA");
+ recordNames.put(Type.FORMULA2, "FORMULA");
+ recordNames.put(Type.XF, "XF");
+ recordNames.put(Type.MULRK, "MULRK");
+ recordNames.put(Type.NUMBER, "NUMBER");
+ recordNames.put(Type.BOUNDSHEET, "BOUNDSHEET");
+ recordNames.put(Type.CONTINUE, "CONTINUE");
+ recordNames.put(Type.FORMAT, "FORMAT");
+ recordNames.put(Type.EXTERNSHEET, "EXTERNSHEET");
+ recordNames.put(Type.INDEX, "INDEX");
+ recordNames.put(Type.DIMENSION, "DIMENSION");
+ recordNames.put(Type.ROW, "ROW");
+ recordNames.put(Type.DBCELL, "DBCELL");
+ recordNames.put(Type.BLANK, "BLANK");
+ recordNames.put(Type.MULBLANK, "MULBLANK");
+ recordNames.put(Type.RK, "RK");
+ recordNames.put(Type.RK2, "RK");
+ recordNames.put(Type.COLINFO, "COLINFO");
+ recordNames.put(Type.LABEL, "LABEL");
+ recordNames.put(Type.SHAREDFORMULA, "SHAREDFORMULA");
+ recordNames.put(Type.CODEPAGE, "CODEPAGE");
+ recordNames.put(Type.WINDOW1, "WINDOW1");
+ recordNames.put(Type.WINDOW2, "WINDOW2");
+ recordNames.put(Type.MERGEDCELLS, "MERGEDCELLS");
+ recordNames.put(Type.HLINK, "HLINK");
+ recordNames.put(Type.HEADER, "HEADER");
+ recordNames.put(Type.FOOTER, "FOOTER");
+ recordNames.put(Type.INTERFACEHDR, "INTERFACEHDR");
+ recordNames.put(Type.MMS, "MMS");
+ recordNames.put(Type.INTERFACEEND, "INTERFACEEND");
+ recordNames.put(Type.DSF, "DSF");
+ recordNames.put(Type.FNGROUPCOUNT, "FNGROUPCOUNT");
+ recordNames.put(Type.COUNTRY, "COUNTRY");
+ recordNames.put(Type.TABID, "TABID");
+ recordNames.put(Type.PROTECT, "PROTECT");
+ recordNames.put(Type.SCENPROTECT, "SCENPROTECT");
+ recordNames.put(Type.OBJPROTECT, "OBJPROTECT");
+ recordNames.put(Type.WINDOWPROTECT, "WINDOWPROTECT");
+ recordNames.put(Type.PASSWORD, "PASSWORD");
+ recordNames.put(Type.PROT4REV, "PROT4REV");
+ recordNames.put(Type.PROT4REVPASS, "PROT4REVPASS");
+ recordNames.put(Type.BACKUP, "BACKUP");
+ recordNames.put(Type.HIDEOBJ, "HIDEOBJ");
+ recordNames.put(Type.NINETEENFOUR, "1904");
+ recordNames.put(Type.PRECISION, "PRECISION");
+ recordNames.put(Type.BOOKBOOL, "BOOKBOOL");
+ recordNames.put(Type.STYLE, "STYLE");
+ recordNames.put(Type.EXTSST, "EXTSST");
+ recordNames.put(Type.REFRESHALL, "REFRESHALL");
+ recordNames.put(Type.CALCMODE, "CALCMODE");
+ recordNames.put(Type.CALCCOUNT, "CALCCOUNT");
+ recordNames.put(Type.NAME, "NAME");
+ recordNames.put(Type.MSODRAWINGGROUP, "MSODRAWINGGROUP");
+ recordNames.put(Type.MSODRAWING, "MSODRAWING");
+ recordNames.put(Type.OBJ, "OBJ");
+ recordNames.put(Type.USESELFS, "USESELFS");
+ recordNames.put(Type.SUPBOOK, "SUPBOOK");
+ recordNames.put(Type.LEFTMARGIN, "LEFTMARGIN");
+ recordNames.put(Type.RIGHTMARGIN, "RIGHTMARGIN");
+ recordNames.put(Type.TOPMARGIN, "TOPMARGIN");
+ recordNames.put(Type.BOTTOMMARGIN, "BOTTOMMARGIN");
+ recordNames.put(Type.HCENTER, "HCENTER");
+ recordNames.put(Type.VCENTER, "VCENTER");
+ recordNames.put(Type.ITERATION, "ITERATION");
+ recordNames.put(Type.DELTA, "DELTA");
+ recordNames.put(Type.SAVERECALC, "SAVERECALC");
+ recordNames.put(Type.PRINTHEADERS, "PRINTHEADERS");
+ recordNames.put(Type.PRINTGRIDLINES, "PRINTGRIDLINES");
+ recordNames.put(Type.SETUP, "SETUP");
+ recordNames.put(Type.SELECTION, "SELECTION");
+ recordNames.put(Type.STRING, "STRING");
+ recordNames.put(Type.FONTX, "FONTX");
+ recordNames.put(Type.IFMT, "IFMT");
+ recordNames.put(Type.WSBOOL, "WSBOOL");
+ recordNames.put(Type.GRIDSET, "GRIDSET");
+ recordNames.put(Type.REFMODE, "REFMODE");
+ recordNames.put(Type.GUTS, "GUTS");
+ recordNames.put(Type.EXTERNNAME, "EXTERNNAME");
+ recordNames.put(Type.FBI, "FBI");
+ recordNames.put(Type.CRN, "CRN");
+ recordNames.put(Type.HORIZONTALPAGEBREAKS, "HORIZONTALPAGEBREAKS");
+ recordNames.put(Type.VERTICALPAGEBREAKS, "VERTICALPAGEBREAKS");
+ recordNames.put(Type.DEFAULTROWHEIGHT, "DEFAULTROWHEIGHT");
+ recordNames.put(Type.TEMPLATE, "TEMPLATE");
+ recordNames.put(Type.PANE, "PANE");
+ recordNames.put(Type.SCL, "SCL");
+ recordNames.put(Type.PALETTE, "PALETTE");
+ recordNames.put(Type.PLS, "PLS");
+ recordNames.put(Type.OBJPROJ, "OBJPROJ");
+ recordNames.put(Type.DEFCOLWIDTH, "DEFCOLWIDTH");
+ recordNames.put(Type.ARRAY, "ARRAY");
+ recordNames.put(Type.WEIRD1, "WEIRD1");
+ recordNames.put(Type.BOOLERR, "BOOLERR");
+ recordNames.put(Type.SORT, "SORT");
+ recordNames.put(Type.BUTTONPROPERTYSET, "BUTTONPROPERTYSET");
+ recordNames.put(Type.NOTE, "NOTE");
+ recordNames.put(Type.TXO, "TXO");
+ recordNames.put(Type.DV, "DV");
+ recordNames.put(Type.DVAL, "DVAL");
+ recordNames.put(Type.SERIES, "SERIES");
+ recordNames.put(Type.SERIESLIST, "SERIESLIST");
+ recordNames.put(Type.SBASEREF, "SBASEREF");
+ recordNames.put(Type.CONDFMT, "CONDFMT");
+ recordNames.put(Type.CF, "CF");
+ recordNames.put(Type.FILTERMODE, "FILTERMODE");
+ recordNames.put(Type.AUTOFILTER, "AUTOFILTER");
+ recordNames.put(Type.AUTOFILTERINFO, "AUTOFILTERINFO");
+
+ recordNames.put(Type.UNKNOWN, "???");
+ }
+ /**
+ * Dumps out the contents of the excel file
+ */
+ private void dump() throws IOException
+ {
+ Record r = null;
+ boolean cont = true;
+ while (reader.hasNext() && cont)
+ {
+ r = reader.next();
+ cont = writeRecord(r);
+ }
+ }
+
+ /**
+ * Writes out the biff record
+ * @param r
+ * @exception IOException if an error occurs
+ */
+ private boolean writeRecord(Record r)
+ throws IOException
+ {
+ boolean cont = true;
+ int pos = reader.getPos();
+ int code = r.getCode();
+
+ if (bofs == 0)
+ {
+ cont = (r.getType() == Type.BOF);
+ }
+
+ if (!cont)
+ {
+ return cont;
+ }
+
+ if (r.getType() == Type.BOF)
+ {
+ bofs++;
+ }
+
+ if (r.getType() == Type.EOF)
+ {
+ bofs--;
+ }
+
+ StringBuffer buf = new StringBuffer();
+
+ // Write out the record header
+ writeSixDigitValue(pos, buf);
+ buf.append(" [");
+ buf.append(recordNames.get(r.getType()));
+ buf.append("]");
+ buf.append(" (0x");
+ buf.append(Integer.toHexString(code));
+ buf.append(")");
+
+ if (code == Type.XF.value)
+ {
+ buf.append(" (0x");
+ buf.append(Integer.toHexString(xfIndex));
+ buf.append(")");
+ xfIndex++;
+ }
+
+ if (code == Type.FONT.value)
+ {
+ if (fontIndex == 4)
+ {
+ fontIndex++;
+ }
+
+ buf.append(" (0x");
+ buf.append(Integer.toHexString(fontIndex));
+ buf.append(")");
+ fontIndex++;
+ }
+
+ writer.write(buf.toString());
+ writer.newLine();
+
+ byte[] standardData = new byte[4];
+ standardData[0] = (byte) (code & 0xff);
+ standardData[1] = (byte) ((code & 0xff00) >> 8);
+ standardData[2] = (byte) (r.getLength() & 0xff);
+ standardData[3] = (byte) ((r.getLength() & 0xff00) >> 8);
+ byte[] recordData = r.getData();
+ byte[] data = new byte[standardData.length + recordData.length];
+ System.arraycopy(standardData, 0, data, 0, standardData.length);
+ System.arraycopy(recordData, 0, data,
+ standardData.length, recordData.length);
+
+ int byteCount = 0;
+ int lineBytes = 0;
+
+ while (byteCount < data.length)
+ {
+ buf = new StringBuffer();
+ writeSixDigitValue(pos+byteCount, buf);
+ buf.append(" ");
+
+ lineBytes = Math.min(bytesPerLine, data.length - byteCount);
+
+ for (int i = 0; i < lineBytes ; i++)
+ {
+ writeByte(data[i+byteCount], buf);
+ buf.append(' ');
+ }
+
+ // Perform any padding
+ if (lineBytes < bytesPerLine)
+ {
+ for(int i = 0; i < bytesPerLine - lineBytes; i++)
+ {
+ buf.append(" ");
+ }
+ }
+
+ buf.append(" ");
+
+ for (int i = 0 ; i < lineBytes; i++)
+ {
+ char c = (char) data[i+byteCount];
+ if (c < ' ' || c > 'z')
+ {
+ c = '.';
+ }
+ buf.append(c);
+ }
+
+ byteCount+= lineBytes;
+
+ writer.write(buf.toString());
+ writer.newLine();
+ }
+
+ return cont;
+ }
+
+ /**
+ * Writes the string passed in as a minimum of four digits
+ */
+ private void writeSixDigitValue(int pos, StringBuffer buf)
+ {
+ String val = Integer.toHexString(pos);
+
+ for (int i = 6; i > val.length() ; i--)
+ {
+ buf.append('0');
+ }
+ buf.append(val);
+ }
+
+ /**
+ * Writes the string passed in as a minimum of four digits
+ */
+ private void writeByte(byte val, StringBuffer buf)
+ {
+ String sv = Integer.toHexString((val & 0xff));
+
+ if (sv.length() == 1)
+ {
+ buf.append('0');
+ }
+ buf.append(sv);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/demo/CSV.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/demo/CSV.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/demo/CSV.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,112 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.demo;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+
+import jxl.Cell;
+import jxl.Sheet;
+import jxl.Workbook;
+
+/**
+ * Simple demo class which uses the api to present the contents
+ * of an excel 97 spreadsheet as comma separated values, using a workbook
+ * and output stream of your choice
+ */
+public class CSV
+{
+ /**
+ * Constructor
+ *
+ * @param w The workbook to interrogate
+ * @param out The output stream to which the CSV values are written
+ * @param encoding The encoding used by the output stream. Null or
+ * unrecognized values cause the encoding to default to UTF8
+ * @param hide Suppresses hidden cells
+ * @exception java.io.IOException
+ */
+ public CSV(Workbook w, OutputStream out, String encoding, boolean hide)
+ throws IOException
+ {
+ if (encoding == null || !encoding.equals("UnicodeBig"))
+ {
+ encoding = "UTF8";
+ }
+
+ try
+ {
+ OutputStreamWriter osw = new OutputStreamWriter(out, encoding);
+ BufferedWriter bw = new BufferedWriter(osw);
+
+ for (int sheet = 0; sheet < w.getNumberOfSheets(); sheet++)
+ {
+ Sheet s = w.getSheet(sheet);
+
+ if (!(hide && s.getSettings().isHidden()))
+ {
+ bw.write("*** " + s.getName() + " ****");
+ bw.newLine();
+
+ Cell[] row = null;
+
+ for (int i = 0 ; i < s.getRows() ; i++)
+ {
+ row = s.getRow(i);
+
+ if (row.length > 0)
+ {
+ if (!(hide && row[0].isHidden()))
+ {
+ bw.write(row[0].getContents());
+ // Java 1.4 code to handle embedded commas
+ // bw.write("\"" + row[0].getContents().replaceAll("\"","\"\"") + "\"");
+ }
+
+ for (int j = 1; j < row.length; j++)
+ {
+ bw.write(',');
+ if (!(hide && row[j].isHidden()))
+ {
+ bw.write(row[j].getContents());
+ // Java 1.4 code to handle embedded quotes
+ // bw.write("\"" + row[j].getContents().replaceAll("\"","\"\"") + "\"");
+ }
+ }
+ }
+ bw.newLine();
+ }
+ }
+ }
+ bw.flush();
+ bw.close();
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ System.err.println(e.toString());
+ }
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/demo/Demo.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/demo/Demo.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/demo/Demo.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,366 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.demo;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+
+import common.Logger;
+
+import jxl.Cell;
+import jxl.Range;
+import jxl.Workbook;
+
+/**
+ * The main demo class which interprets the command line switches in order
+ * to determine how to call the demo programs
+ * The demo program uses stdout as its default output stream
+ */
+public class Demo
+{
+ private static final int CSVFormat = 13;
+ private static final int XMLFormat = 14;
+
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(Demo.class);
+
+ /**
+ * Displays the acceptable command line arguments
+ */
+ private static void displayHelp()
+ {
+ System.err.println
+ ("Command format: Demo [-unicode] [-csv] [-hide] excelfile");
+ System.err.println(" Demo -xml [-format] excelfile");
+ System.err.println(" Demo -readwrite|-rw excelfile output");
+ System.err.println(" Demo -biffdump | -bd | -wa | -write | -formulas | -features | -escher | -escherdg excelfile");
+ System.err.println(" Demo -ps excelfile [property] [output]");
+ System.err.println(" Demo -version | -logtest | -h | -help");
+
+ }
+
+ /**
+ * The main method. Gets the worksheet and then uses the API
+ * within a simple loop to print out the spreadsheet contents as
+ * comma separated values
+ *
+ * @param args the command line arguments
+ */
+ public static void main(String args[])
+ {
+ if (args.length == 0)
+ {
+ displayHelp();
+ System.exit(1);
+ }
+
+ if (args[0].equals("-help") || args[0].equals("-h"))
+ {
+ displayHelp();
+ System.exit(1);
+ }
+
+ if (args[0].equals("-version"))
+ {
+ System.out.println("v"+Workbook.getVersion());
+ System.exit(0);
+ }
+
+ if (args[0].equals("-logtest"))
+ {
+ logger.debug("A sample \"debug\" message");
+ logger.info("A sample \"info\" message");
+ logger.warn("A sample \"warning\" message");
+ logger.error("A sample \"error\" message");
+ logger.fatal("A sample \"fatal\" message");
+ System.exit(0);
+ }
+
+ boolean write = false;
+ boolean readwrite = false;
+ boolean formulas = false;
+ boolean biffdump = false;
+ boolean jxlversion = false;
+ boolean propertysets = false;
+ boolean features = false;
+ boolean escher = false;
+ boolean escherdg = false;
+ String file = args[0];
+ String outputFile = null;
+ String propertySet = null;
+
+ if (args[0].equals("-write"))
+ {
+ write = true;
+ file = args[1];
+ }
+ else if (args[0].equals("-formulas"))
+ {
+ formulas = true;
+ file = args[1];
+ }
+ else if (args[0].equals("-features"))
+ {
+ features = true;
+ file = args[1];
+ }
+ else if (args[0].equals("-escher"))
+ {
+ escher = true;
+ file = args[1];
+ }
+ else if (args[0].equals("-escherdg"))
+ {
+ escherdg = true;
+ file = args[1];
+ }
+ else if (args[0].equals("-biffdump") || args[0].equals("-bd"))
+ {
+ biffdump = true;
+ file = args[1];
+ }
+ else if (args[0].equals("-wa"))
+ {
+ jxlversion = true;
+ file = args[1];
+ }
+ else if (args[0].equals("-ps"))
+ {
+ propertysets = true;
+ file = args[1];
+
+ if (args.length > 2)
+ {
+ propertySet = args[2];
+ }
+
+ if (args.length == 4)
+ {
+ outputFile = args[3];
+ }
+ }
+ else if (args[0].equals("-readwrite") || args[0].equals("-rw"))
+ {
+ readwrite = true;
+ file = args[1];
+ outputFile = args[2];
+ }
+ else
+ {
+ file = args[args.length - 1];
+ }
+
+ String encoding = "UTF8";
+ int format = CSVFormat;
+ boolean formatInfo = false;
+ boolean hideCells = false;
+
+ if (write == false &&
+ readwrite == false &&
+ formulas == false &&
+ biffdump == false &&
+ jxlversion == false &&
+ propertysets == false &&
+ features == false &&
+ escher == false &&
+ escherdg == false)
+ {
+ for (int i = 0; i < args.length - 1; i++)
+ {
+ if (args[i].equals("-unicode"))
+ {
+ encoding="UnicodeBig";
+ }
+ else if (args[i].equals("-xml"))
+ {
+ format = XMLFormat;
+ }
+ else if (args[i].equals("-csv"))
+ {
+ format = CSVFormat;
+ }
+ else if (args[i].equals("-format"))
+ {
+ formatInfo = true;
+ }
+ else if (args[i].equals("-hide"))
+ {
+ hideCells = true;
+ }
+ else
+ {
+ System.err.println
+ ("Command format: CSV [-unicode] [-xml|-csv] excelfile");
+ System.exit(1);
+ }
+ }
+ }
+
+ try
+ {
+ if (write)
+ {
+ Write w = new Write(file);
+ w.write();
+ }
+ else if (readwrite)
+ {
+ ReadWrite rw = new ReadWrite(file, outputFile);
+ rw.readWrite();
+ }
+ else if (formulas)
+ {
+ Workbook w = Workbook.getWorkbook(new File(file));
+ Formulas f = new Formulas(w, System.out, encoding);
+ w.close();
+ }
+ else if (features)
+ {
+ Workbook w = Workbook.getWorkbook(new File(file));
+ Features f = new Features(w, System.out, encoding);
+ w.close();
+ }
+ else if (escher)
+ {
+ Workbook w = Workbook.getWorkbook(new File(file));
+ Escher f = new Escher(w, System.out, encoding);
+ w.close();
+ }
+ else if (escherdg)
+ {
+ Workbook w = Workbook.getWorkbook(new File(file));
+ EscherDrawingGroup f = new EscherDrawingGroup(w, System.out, encoding);
+ w.close();
+ }
+ else if (biffdump)
+ {
+ BiffDump bd = new BiffDump(new File(file), System.out);
+ }
+ else if (jxlversion)
+ {
+ WriteAccess bd = new WriteAccess(new File(file));
+ }
+ else if (propertysets)
+ {
+ OutputStream os = System.out;
+ if (outputFile != null)
+ {
+ os = new FileOutputStream(outputFile);
+ }
+ PropertySetsReader psr = new PropertySetsReader(new File(file),
+ propertySet,
+ os);
+ }
+ else
+ {
+ Workbook w = Workbook.getWorkbook(new File(file));
+
+ // findTest(w);
+
+ if (format == CSVFormat)
+ {
+ CSV csv = new CSV(w, System.out, encoding, hideCells);
+ }
+ else if (format == XMLFormat)
+ {
+ XML xml = new XML(w, System.out, encoding, formatInfo);
+ }
+
+ w.close();
+ }
+ }
+ catch (Throwable t)
+ {
+ System.out.println(t.toString());
+ t.printStackTrace();
+ }
+ }
+
+ /**
+ * A private method to test the various find functions
+ */
+ private static void findTest(Workbook w)
+ {
+ logger.info("Find test");
+
+ Cell c = w.findCellByName("named1");
+ if (c != null)
+ {
+ logger.info("named1 contents: " + c.getContents());
+ }
+
+ c = w.findCellByName("named2");
+ if (c != null)
+ {
+ logger.info("named2 contents: " + c.getContents());
+ }
+
+ c = w.findCellByName("namedrange");
+ if (c != null)
+ {
+ logger.info("named2 contents: " + c.getContents());
+ }
+
+ Range[] range = w.findByName("namedrange");
+ if (range != null)
+ {
+ c = range[0].getTopLeft();
+ logger.info("namedrange top left contents: " + c.getContents());
+
+ c = range[0].getBottomRight();
+ logger.info("namedrange bottom right contents: " + c.getContents());
+ }
+
+ range = w.findByName("nonadjacentrange");
+ if (range != null)
+ {
+ for (int i = 0; i < range.length; i++)
+ {
+ c = range[i].getTopLeft();
+ logger.info("nonadjacent top left contents: " + c.getContents());
+
+ c = range[i].getBottomRight();
+ logger.info("nonadjacent bottom right contents: " + c.getContents());
+ }
+ }
+
+ range = w.findByName("horizontalnonadjacentrange");
+ if (range != null)
+ {
+ for (int i = 0; i < range.length; i++)
+ {
+ c = range[i].getTopLeft();
+ logger.info("horizontalnonadjacent top left contents: " +
+ c.getContents());
+
+ c = range[i].getBottomRight();
+ logger.info("horizontalnonadjacent bottom right contents: " +
+ c.getContents());
+ }
+ }
+
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/demo/Escher.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/demo/Escher.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/demo/Escher.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,89 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.demo;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+
+import jxl.Workbook;
+import jxl.biff.drawing.DrawingData;
+import jxl.biff.drawing.EscherDisplay;
+import jxl.read.biff.SheetImpl;
+
+/**
+ * Displays the escher data
+ */
+public class Escher
+{
+ /**
+ * Constructor
+ *
+ * @param w The workbook to interrogate
+ * @param out The output stream to which the CSV values are written
+ * @param encoding The encoding used by the output stream. Null or
+ * unrecognized values cause the encoding to default to UTF8
+ * @exception java.io.IOException
+ */
+ public Escher (Workbook w, OutputStream out, String encoding)
+ throws IOException
+ {
+ if (encoding == null || !encoding.equals("UnicodeBig"))
+ {
+ encoding = "UTF8";
+ }
+
+ try
+ {
+ OutputStreamWriter osw = new OutputStreamWriter(out, encoding);
+ BufferedWriter bw = new BufferedWriter(osw);
+
+ for (int i = 0; i < w.getNumberOfSheets(); i++)
+ {
+ SheetImpl s = (SheetImpl) w.getSheet(i);
+ bw.write(s.getName());
+ bw.newLine();
+ bw.newLine();
+
+ DrawingData dd = s.getDrawingData();
+
+ if (dd != null)
+ {
+ EscherDisplay ed = new EscherDisplay(dd, bw);
+ ed.display();
+ }
+
+ bw.newLine();
+ bw.newLine();
+ bw.flush();
+ }
+ bw.flush();
+ bw.close();
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ System.err.println(e.toString());
+ }
+ }
+
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/demo/EscherDrawingGroup.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/demo/EscherDrawingGroup.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/demo/EscherDrawingGroup.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,82 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.demo;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+
+import jxl.Workbook;
+import jxl.biff.drawing.DrawingGroup;
+import jxl.biff.drawing.EscherDisplay;
+import jxl.read.biff.WorkbookParser;
+
+/**
+ * Displays the escher data
+ */
+public class EscherDrawingGroup
+{
+ /**
+ * Constructor
+ *
+ * @param w The workbook to interrogate
+ * @param out The output stream to which the CSV values are written
+ * @param encoding The encoding used by the output stream. Null or
+ * unrecognized values cause the encoding to default to UTF8
+ * @exception java.io.IOException
+ */
+ public EscherDrawingGroup (Workbook w, OutputStream out, String encoding)
+ throws IOException
+ {
+ if (encoding == null || !encoding.equals("UnicodeBig"))
+ {
+ encoding = "UTF8";
+ }
+
+ try
+ {
+ OutputStreamWriter osw = new OutputStreamWriter(out, encoding);
+ BufferedWriter bw = new BufferedWriter(osw);
+
+ WorkbookParser wp = (WorkbookParser) w;
+
+ DrawingGroup dg = wp.getDrawingGroup();
+
+ if (dg != null)
+ {
+ EscherDisplay ed = new EscherDisplay(dg, bw);
+ ed.display();
+ }
+
+ bw.newLine();
+ bw.newLine();
+ bw.flush();
+ bw.close();
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ System.err.println(e.toString());
+ }
+ }
+
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/demo/Features.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/demo/Features.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/demo/Features.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,108 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.demo;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+
+import java.util.ArrayList;
+
+import jxl.Cell;
+import jxl.CellFeatures;
+import jxl.CellReferenceHelper;
+import jxl.Sheet;
+import jxl.Workbook;
+
+/**
+ * Goes through each cell in the workbook, and if the cell has any features
+ * associated with, it prints out the cell contents and the features
+ */
+public class Features
+{
+ /**
+ * Constructor
+ *
+ * @param w The workbook to interrogate
+ * @param out The output stream to which the CSV values are written
+ * @param encoding The encoding used by the output stream. Null or
+ * unrecognized values cause the encoding to default to UTF8
+ * @exception java.io.IOException
+ */
+ public Features(Workbook w, OutputStream out, String encoding)
+ throws IOException
+ {
+ if (encoding == null || !encoding.equals("UnicodeBig"))
+ {
+ encoding = "UTF8";
+ }
+
+ try
+ {
+ OutputStreamWriter osw = new OutputStreamWriter(out, encoding);
+ BufferedWriter bw = new BufferedWriter(osw);
+
+ for (int sheet = 0; sheet < w.getNumberOfSheets(); sheet++)
+ {
+ Sheet s = w.getSheet(sheet);
+
+ bw.write(s.getName());
+ bw.newLine();
+
+ Cell[] row = null;
+ Cell c = null;
+
+ for (int i = 0 ; i < s.getRows() ; i++)
+ {
+ row = s.getRow(i);
+
+ for (int j = 0; j < row.length; j++)
+ {
+ c = row[j];
+ if (c.getCellFeatures() != null)
+ {
+ CellFeatures features = c.getCellFeatures();
+ StringBuffer sb = new StringBuffer();
+ CellReferenceHelper.getCellReference
+ (c.getColumn(), c.getRow(), sb);
+
+ bw.write("Cell " + sb.toString() +
+ " contents: " + c.getContents());
+ bw.flush();
+ bw.write(" comment: " + features.getComment());
+ bw.flush();
+ bw.newLine();
+ }
+ }
+ }
+ }
+ bw.flush();
+ bw.close();
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ System.err.println(e.toString());
+ }
+ }
+
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/demo/Formulas.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/demo/Formulas.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/demo/Formulas.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,139 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.demo;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import jxl.Cell;
+import jxl.CellType;
+import jxl.FormulaCell;
+import jxl.Sheet;
+import jxl.Workbook;
+import jxl.biff.CellReferenceHelper;
+import jxl.biff.formula.FormulaException;
+
+/**
+ * Goes through each cell in the workbook, and if the contents of that
+ * cell is a formula, it prints out the last calculated value and
+ * the formula string
+ */
+public class Formulas
+{
+ /**
+ * Constructor
+ *
+ * @param w The workbook to interrogate
+ * @param out The output stream to which the CSV values are written
+ * @param encoding The encoding used by the output stream. Null or
+ * unrecognized values cause the encoding to default to UTF8
+ * @exception java.io.IOException
+ */
+ public Formulas(Workbook w, OutputStream out, String encoding)
+ throws IOException
+ {
+ if (encoding == null || !encoding.equals("UnicodeBig"))
+ {
+ encoding = "UTF8";
+ }
+
+ try
+ {
+ OutputStreamWriter osw = new OutputStreamWriter(out, encoding);
+ BufferedWriter bw = new BufferedWriter(osw);
+
+ ArrayList parseErrors = new ArrayList();
+
+ for (int sheet = 0; sheet < w.getNumberOfSheets(); sheet++)
+ {
+ Sheet s = w.getSheet(sheet);
+
+ bw.write(s.getName());
+ bw.newLine();
+
+ Cell[] row = null;
+ Cell c = null;
+
+ for (int i = 0 ; i < s.getRows() ; i++)
+ {
+ row = s.getRow(i);
+
+ for (int j = 0; j < row.length; j++)
+ {
+ c = row[j];
+ if (c.getType() == CellType.NUMBER_FORMULA ||
+ c.getType() == CellType.STRING_FORMULA ||
+ c.getType() == CellType.BOOLEAN_FORMULA ||
+ c.getType() == CellType.DATE_FORMULA ||
+ c.getType() == CellType.FORMULA_ERROR)
+ {
+ FormulaCell nfc = (FormulaCell) c;
+ StringBuffer sb = new StringBuffer();
+ CellReferenceHelper.getCellReference
+ (c.getColumn(), c.getRow(), sb);
+
+ try
+ {
+ bw.write("Formula in " + sb.toString() +
+ " value: " + c.getContents());
+ bw.flush();
+ bw.write(" formula: " + nfc.getFormula());
+ bw.flush();
+ bw.newLine();
+ }
+ catch (FormulaException e)
+ {
+ bw.newLine();
+ parseErrors.add(s.getName() + '!' +
+ sb.toString() + ": " + e.getMessage());
+ }
+ }
+ }
+ }
+ }
+ bw.flush();
+ bw.close();
+
+ if (parseErrors.size() > 0)
+ {
+ System.err.println();
+ System.err.println("There were " + parseErrors.size() + " errors");
+
+ Iterator i = parseErrors.iterator();
+ while (i.hasNext())
+ {
+ System.err.println(i.next());
+ }
+ }
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ System.err.println(e.toString());
+ }
+ }
+
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/demo/PropertySetsReader.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/demo/PropertySetsReader.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/demo/PropertySetsReader.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,149 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.demo;
+
+import java.io.BufferedWriter;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+
+import jxl.WorkbookSettings;
+import jxl.biff.BaseCompoundFile;
+import jxl.read.biff.BiffException;
+import jxl.read.biff.CompoundFile;
+
+
+/**
+ * Generates a biff dump of the specified excel file
+ */
+class PropertySetsReader
+{
+ private BufferedWriter writer;
+ private CompoundFile compoundFile;
+
+ /**
+ * Constructor
+ *
+ * @param file the file
+ * @param propertySet the property set to read
+ * @param os the output stream
+ * @exception IOException
+ * @exception BiffException
+ */
+ public PropertySetsReader(java.io.File file, String propertySet,
+ OutputStream os)
+ throws IOException, BiffException
+ {
+ writer = new BufferedWriter(new OutputStreamWriter(os));
+ FileInputStream fis = new FileInputStream(file);
+
+ int initialFileSize = 1024*1024; // 1mb
+ int arrayGrowSize = 1024*1024;// 1mb
+
+ byte[] d = new byte[initialFileSize];
+ int bytesRead = fis.read(d);
+ int pos = bytesRead;
+
+ while (bytesRead != -1)
+ {
+ if (pos >= d.length)
+ {
+ // Grow the array
+ byte newArray[] = new byte[d.length + arrayGrowSize];
+ System.arraycopy(d, 0, newArray, 0, d.length);
+ d = newArray;
+ }
+ bytesRead = fis.read(d, pos, d.length - pos);
+ pos += bytesRead;
+ }
+
+ bytesRead = pos + 1;
+
+ compoundFile = new CompoundFile(d, new WorkbookSettings());
+ fis.close();
+
+ if (propertySet == null)
+ {
+ displaySets();
+ }
+ else
+ {
+ displayPropertySet(propertySet, os);
+ }
+ }
+
+ /**
+ * Displays the properties to the output stream
+ */
+ void displaySets() throws IOException
+ {
+ int numSets = compoundFile.getNumberOfPropertySets();
+
+ for (int i = 0; i < numSets ; i++)
+ {
+ BaseCompoundFile.PropertyStorage ps = compoundFile.getPropertySet(i);
+ writer.write(Integer.toString(i));
+ writer.write(") ");
+ writer.write(ps.name);
+ writer.write("(type ");
+ writer.write(Integer.toString(ps.type));
+ writer.write(" size ");
+ writer.write(Integer.toString(ps.size));
+ writer.write(" prev " );
+ writer.write(Integer.toString(ps.previous));
+ writer.write(" next " );
+ writer.write(Integer.toString(ps.next));
+ writer.write(" child " );
+ writer.write(Integer.toString(ps.child));
+ writer.write(" start block " );
+ writer.write(Integer.toString(ps.startBlock));
+ writer.write(")");
+ writer.newLine();
+ }
+
+ writer.flush();
+ writer.close();
+ }
+
+ /**
+ * Write the property stream to the output stream
+ */
+ void displayPropertySet(String ps, OutputStream os)
+ throws IOException,BiffException
+ {
+ if (ps.equalsIgnoreCase("SummaryInformation"))
+ {
+ ps = BaseCompoundFile.SUMMARY_INFORMATION_NAME;
+ }
+ else if (ps.equalsIgnoreCase("DocumentSummaryInformation"))
+ {
+ ps = BaseCompoundFile.DOCUMENT_SUMMARY_INFORMATION_NAME;
+ }
+ else if (ps.equalsIgnoreCase("CompObj"))
+ {
+ ps = BaseCompoundFile.COMP_OBJ_NAME;
+ }
+
+ byte[] stream = compoundFile.getStream(ps);
+ os.write(stream);
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/demo/ReadWrite.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/demo/ReadWrite.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/demo/ReadWrite.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,438 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.demo;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+
+import common.Logger;
+
+import jxl.CellType;
+import jxl.Sheet;
+import jxl.Workbook;
+import jxl.format.CellFormat;
+import jxl.format.Colour;
+import jxl.format.UnderlineStyle;
+import jxl.read.biff.BiffException;
+import jxl.write.Blank;
+import jxl.write.DateFormat;
+import jxl.write.DateFormats;
+import jxl.write.DateTime;
+import jxl.write.Formula;
+import jxl.write.Label;
+import jxl.write.Number;
+import jxl.write.NumberFormat;
+import jxl.write.WritableCell;
+import jxl.write.WritableCellFeatures;
+import jxl.write.WritableCellFormat;
+import jxl.write.WritableFont;
+import jxl.write.WritableHyperlink;
+import jxl.write.WritableImage;
+import jxl.write.WritableSheet;
+import jxl.write.WritableWorkbook;
+import jxl.write.WriteException;
+
+/**
+ * Demo class which uses the api to read in a spreadsheet and generate a clone
+ * of that spreadsheet which contains the same data. If the spreadsheet read
+ * in is the spreadsheet called jxlrwtest.xls (provided with the distribution)
+ * then this class will modify certain fields in the copy of that spreadsheet.
+ * This is illustrating that it is possible to read in a spreadsheet, modify
+ * a few values, and write it under a new name.
+ */
+public class ReadWrite
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(ReadWrite.class);
+
+ /**
+ * The spreadsheet to read in
+ */
+ private File inputWorkbook;
+ /**
+ * The spreadsheet to output
+ */
+ private File outputWorkbook;
+
+ /**
+ * Constructor
+ *
+ * @param output
+ * @param input
+ */
+ public ReadWrite(String input, String output)
+ {
+ inputWorkbook = new File(input);
+ outputWorkbook = new File(output);
+ logger.setSuppressWarnings(Boolean.getBoolean("jxl.nowarnings"));
+ logger.info("Input file: " + input);
+ logger.info("Output file: " + output);
+ }
+
+ /**
+ * Reads in the inputFile and creates a writable copy of it called outputFile
+ *
+ * @exception IOException
+ * @exception BiffException
+ */
+ public void readWrite() throws IOException, BiffException, WriteException
+ {
+ logger.info("Reading...");
+ Workbook w1 = Workbook.getWorkbook(inputWorkbook);
+
+ logger.info("Copying...");
+ WritableWorkbook w2 = Workbook.createWorkbook(outputWorkbook, w1);
+
+ if (inputWorkbook.getName().equals("jxlrwtest.xls"))
+ {
+ modify(w2);
+ }
+
+ w2.write();
+ w2.close();
+ logger.info("Done");
+ }
+
+ /**
+ * If the inputFile was the test spreadsheet, then it modifies certain fields
+ * of the writable copy
+ *
+ * @param w
+ */
+ private void modify(WritableWorkbook w) throws WriteException
+ {
+ logger.info("Modifying...");
+
+ WritableSheet sheet = w.getSheet("modified");
+
+ WritableCell cell = null;
+ CellFormat cf = null;
+ Label l = null;
+ WritableCellFeatures wcf = null;
+
+ // Change the format of cell B4 to be emboldened
+ cell = sheet.getWritableCell(1,3);
+ WritableFont bold = new WritableFont(WritableFont.ARIAL,
+ WritableFont.DEFAULT_POINT_SIZE,
+ WritableFont.BOLD);
+ cf = new WritableCellFormat(bold);
+ cell.setCellFormat(cf);
+
+ // Change the format of cell B5 to be underlined
+ cell = sheet.getWritableCell(1,4);
+ WritableFont underline = new WritableFont(WritableFont.ARIAL,
+ WritableFont.DEFAULT_POINT_SIZE,
+ WritableFont.NO_BOLD,
+ false,
+ UnderlineStyle.SINGLE);
+ cf = new WritableCellFormat(underline);
+ cell.setCellFormat(cf);
+
+ // Change the point size of cell B6 to be 10 point
+ cell = sheet.getWritableCell(1,5);
+ WritableFont tenpoint = new WritableFont(WritableFont.ARIAL, 10);
+ cf = new WritableCellFormat(tenpoint);
+ cell.setCellFormat(cf);
+
+ // Change the contents of cell B7 to read "Label - mod"
+ cell = sheet.getWritableCell(1,6);
+ if (cell.getType() == CellType.LABEL)
+ {
+ Label lc = (Label) cell;
+ lc.setString(lc.getString() + " - mod");
+ }
+
+ // Change cell B10 to display 7 dps
+ cell = sheet.getWritableCell(1,9);
+ NumberFormat sevendps = new NumberFormat("#.0000000");
+ cf = new WritableCellFormat(sevendps);
+ cell.setCellFormat(cf);
+
+
+ // Change cell B11 to display in the format 1e4
+ cell = sheet.getWritableCell(1,10);
+ NumberFormat exp4 = new NumberFormat("0.####E0");
+ cf = new WritableCellFormat(exp4);
+ cell.setCellFormat(cf);
+
+ // Change cell B12 to be normal display
+ cell = sheet.getWritableCell(1,11);
+ cell.setCellFormat(WritableWorkbook.NORMAL_STYLE);
+
+ // Change the contents of cell B13 to 42
+ cell = sheet.getWritableCell(1,12);
+ if (cell.getType() == CellType.NUMBER)
+ {
+ Number n = (Number) cell;
+ n.setValue(42);
+ }
+
+ // Add 0.1 to the contents of cell B14
+ cell = sheet.getWritableCell(1,13);
+ if (cell.getType() == CellType.NUMBER)
+ {
+ Number n = (Number) cell;
+ n.setValue(n.getValue() + 0.1);
+ }
+
+ // Change the date format of cell B17 to be a custom format
+ cell = sheet.getWritableCell(1,16);
+ DateFormat df = new DateFormat("dd MMM yyyy HH:mm:ss");
+ cf = new WritableCellFormat(df);
+ cell.setCellFormat(cf);
+
+ // Change the date format of cell B18 to be a standard format
+ cell = sheet.getWritableCell(1,17);
+ cf = new WritableCellFormat(DateFormats.FORMAT9);
+ cell.setCellFormat(cf);
+
+ // Change the date in cell B19 to be 18 Feb 1998, 11:23:28
+ cell = sheet.getWritableCell(1,18);
+ if (cell.getType() == CellType.DATE)
+ {
+ DateTime dt = (DateTime) cell;
+ Calendar cal = Calendar.getInstance();
+ cal.set(1998, 1, 18, 11, 23, 28);
+ Date d = cal.getTime();
+ dt.setDate(d);
+ }
+
+ // Change the value in B23 to be 6.8. This should recalculate the
+ // formula
+ cell = sheet.getWritableCell(1,22);
+ if (cell.getType() == CellType.NUMBER)
+ {
+ Number n = (Number) cell;
+ n.setValue(6.8);
+ }
+
+ // Change the label in B30. This will have the effect of making
+ // the original string unreferenced
+ cell = sheet.getWritableCell(1, 29);
+ if (cell.getType() == CellType.LABEL)
+ {
+ l = (Label) cell;
+ l.setString("Modified string contents");
+ }
+ // Insert a new row (number 35)
+ sheet.insertRow(34);
+
+ // Delete row 38 (39 after row has been inserted)
+ sheet.removeRow(38);
+
+ // Insert a new column (J)
+ sheet.insertColumn(9);
+
+ // Remove a column (L - M after column has been inserted)
+ sheet.removeColumn(11);
+
+ // Remove row 44 (contains a hyperlink), and then insert an empty
+ // row just to keep the numbers consistent
+ sheet.removeRow(43);
+ sheet.insertRow(43);
+
+ // Modify the hyperlinks
+ WritableHyperlink hyperlinks[] = sheet.getWritableHyperlinks();
+
+ for (int i = 0; i < hyperlinks.length; i++)
+ {
+ WritableHyperlink wh = hyperlinks[i];
+ if (wh.getColumn() == 1 && wh.getRow() == 39)
+ {
+ try
+ {
+ // Change the hyperlink that begins in cell B40 to be a different API
+ wh.setURL(new URL("http://www.andykhan.com/jexcelapi/index.html"));
+ }
+ catch (MalformedURLException e)
+ {
+ logger.warn(e.toString());
+ }
+ }
+ else if (wh.getColumn() == 1 && wh.getRow() == 40)
+ {
+ wh.setFile(new File("../jexcelapi/docs/overview-summary.html"));
+ }
+ else if (wh.getColumn() == 1 && wh.getRow() == 41)
+ {
+ wh.setFile(new File("d:/home/jexcelapi/docs/jxl/package-summary.html"));
+ }
+ else if (wh.getColumn() == 1 && wh.getRow() == 44)
+ {
+ // Remove the hyperlink at B45
+ sheet.removeHyperlink(wh);
+ }
+ }
+
+ // Change the background of cell F31 from blue to red
+ WritableCell c = sheet.getWritableCell(5,30);
+ WritableCellFormat newFormat = new WritableCellFormat(c.getCellFormat());
+ newFormat.setBackground(Colour.RED);
+ c.setCellFormat(newFormat);
+
+ // Modify the contents of the merged cell
+ l = new Label(0, 49, "Modified merged cells");
+ sheet.addCell(l);
+
+ // Modify the chart data
+ Number n = (Number) sheet.getWritableCell(0, 70);
+ n.setValue(9);
+
+ n = (Number) sheet.getWritableCell(0, 71);
+ n.setValue(10);
+
+ n = (Number) sheet.getWritableCell(0, 73);
+ n.setValue(4);
+
+ // Add in a cross sheet formula
+ Formula f = new Formula(1, 80, "ROUND(COS(original!B10),2)");
+ sheet.addCell(f);
+
+ // Add in a formula from the named cells
+ f = new Formula(1, 83, "value1+value2");
+ sheet.addCell(f);
+
+ // Add in a function formula using named cells
+ f = new Formula(1, 84, "AVERAGE(value1,value1*4,value2)");
+ sheet.addCell(f);
+
+ // Copy sheet 1 to sheet 3
+ // w.copySheet(0, "copy", 2);
+
+ // Use the cell deep copy feature
+ Label label = new Label(0, 88, "Some copied cells", cf);
+ sheet.addCell(label);
+
+ label = new Label(0,89, "Number from B9");
+ sheet.addCell(label);
+
+ WritableCell wc = sheet.getWritableCell(1, 9).copyTo(1,89);
+ sheet.addCell(wc);
+
+ label = new Label(0, 90, "Label from B4 (modified format)");
+ sheet.addCell(label);
+
+ wc = sheet.getWritableCell(1, 3).copyTo(1,90);
+ sheet.addCell(wc);
+
+ label = new Label(0, 91, "Date from B17");
+ sheet.addCell(label);
+
+ wc = sheet.getWritableCell(1, 16).copyTo(1,91);
+ sheet.addCell(wc);
+
+ label = new Label(0, 92, "Boolean from E16");
+ sheet.addCell(label);
+
+ wc = sheet.getWritableCell(4, 15).copyTo(1,92);
+ sheet.addCell(wc);
+
+ label = new Label(0, 93, "URL from B40");
+ sheet.addCell(label);
+
+ wc = sheet.getWritableCell(1, 39).copyTo(1,93);
+ sheet.addCell(wc);
+
+ // Add some numbers for the formula copy
+ for (int i = 0 ; i < 6; i++)
+ {
+ Number number = new Number(1,94+i, i + 1 + i/8.0);
+ sheet.addCell(number);
+ }
+
+ label = new Label(0,100, "Formula from B27");
+ sheet.addCell(label);
+
+ wc = sheet.getWritableCell(1, 26).copyTo(1,100);
+ sheet.addCell(wc);
+
+ label = new Label(0,101, "A brand new formula");
+ sheet.addCell(label);
+
+ Formula formula = new Formula(1, 101, "SUM(B94:B96)");
+ sheet.addCell(formula);
+
+ label = new Label(0,102, "A copy of it");
+ sheet.addCell(label);
+
+ wc = sheet.getWritableCell(1,101).copyTo(1, 102);
+ sheet.addCell(wc);
+
+ // Remove the second image from the sheet
+ WritableImage wi = sheet.getImage(1);
+ sheet.removeImage(wi);
+
+ wi = new WritableImage(1, 116, 2, 9,
+ new File("resources/littlemoretonhall.png"));
+ sheet.addImage(wi);
+
+ // Add a list data validations
+ label = new Label(0, 151, "Added drop down validation");
+ sheet.addCell(label);
+
+ Blank b = new Blank(1, 151);
+ wcf = new WritableCellFeatures();
+ ArrayList al = new ArrayList();
+ al.add("The Fellowship of the Ring");
+ al.add("The Two Towers");
+ al.add("The Return of the King");
+ wcf.setDataValidationList(al);
+ b.setCellFeatures(wcf);
+ sheet.addCell(b);
+
+ // Add a number data validation
+ label = new Label(0, 152, "Added number validation 2.718 < x < 3.142");
+ sheet.addCell(label);
+ b = new Blank(1,152);
+ wcf = new WritableCellFeatures();
+ wcf.setNumberValidation(2.718, 3.142, wcf.BETWEEN);
+ b.setCellFeatures(wcf);
+ sheet.addCell(b);
+
+ // Modify the text in the first cell with a comment
+ cell = sheet.getWritableCell(0, 156);
+ l = (Label) cell;
+ l.setString("Label text modified");
+
+ cell = sheet.getWritableCell(0, 157);
+ wcf = cell.getWritableCellFeatures();
+ wcf.setComment("modified comment text");
+
+ cell = sheet.getWritableCell(0, 158);
+ wcf = cell.getWritableCellFeatures();
+ wcf.removeComment();
+ }
+}
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/demo/Write.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/demo/Write.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/demo/Write.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,1713 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.demo;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import jxl.CellReferenceHelper;
+import jxl.CellView;
+import jxl.HeaderFooter;
+import jxl.Range;
+import jxl.Workbook;
+import jxl.WorkbookSettings;
+import jxl.format.Alignment;
+import jxl.format.Border;
+import jxl.format.BorderLineStyle;
+import jxl.format.Colour;
+import jxl.format.Orientation;
+import jxl.format.PageOrder;
+import jxl.format.PageOrientation;
+import jxl.format.PaperSize;
+import jxl.format.ScriptStyle;
+import jxl.format.UnderlineStyle;
+import jxl.write.Blank;
+import jxl.write.Boolean;
+import jxl.write.DateFormat;
+import jxl.write.DateFormats;
+import jxl.write.DateTime;
+import jxl.write.Formula;
+import jxl.write.Label;
+import jxl.write.Number;
+import jxl.write.NumberFormat;
+import jxl.write.NumberFormats;
+import jxl.write.WritableCellFeatures;
+import jxl.write.WritableCellFormat;
+import jxl.write.WritableFont;
+import jxl.write.WritableHyperlink;
+import jxl.write.WritableImage;
+import jxl.write.WritableSheet;
+import jxl.write.WritableWorkbook;
+import jxl.write.WriteException;
+
+
+/**
+ * Demo class which writes a spreadsheet. This demo illustrates most of the
+ * features of the JExcelAPI, such as text, numbers, fonts, number formats and
+ * date formats
+ */
+public class Write
+{
+ /**
+ * The filename
+ */
+ private String filename;
+
+ /**
+ * The workbook
+ */
+ private WritableWorkbook workbook;
+
+ /**
+ * Constructor
+ *
+ * @param fn
+ */
+ public Write(String fn)
+ {
+ filename = fn;
+ }
+
+ /**
+ * Uses the JExcelAPI to create a spreadsheet
+ *
+ * @exception IOException
+ * @exception WriteException
+ */
+ public void write() throws IOException, WriteException
+ {
+ WorkbookSettings ws = new WorkbookSettings();
+ ws.setLocale(new Locale("en", "EN"));
+ workbook = Workbook.createWorkbook(new File(filename), ws);
+
+
+ WritableSheet s2 = workbook.createSheet("Number Formats", 0);
+ WritableSheet s3 = workbook.createSheet("Date Formats", 1);
+ WritableSheet s1 = workbook.createSheet("Label Formats", 2);
+ WritableSheet s4 = workbook.createSheet("Borders", 3);
+ WritableSheet s5 = workbook.createSheet("Labels", 4);
+ WritableSheet s6 = workbook.createSheet("Formulas", 5);
+ WritableSheet s7 = workbook.createSheet("Images", 6);
+ // WritableSheet s8 = workbook.createSheet
+ // ("'Illegal chars in name !*%^?': which exceeds max name length",7);
+
+ // Modify the colour palette to bright red for the lime colour
+ workbook.setColourRGB(Colour.LIME, 0xff, 0, 0);
+
+ // Add a named range to the workbook
+ workbook.addNameArea("namedrange", s4, 1, 11, 5, 14);
+ workbook.addNameArea("validation_range", s1, 4, 65, 9, 65);
+
+ // Add a print area to the "Labels" sheet
+ s5.getSettings().setPrintArea(4,4,15,35);
+
+ writeLabelFormatSheet(s1);
+ writeNumberFormatSheet(s2);
+ writeDateFormatSheet(s3);
+ writeBordersSheet(s4);
+ writeLabelsSheet(s5);
+ writeFormulaSheet(s6);
+ writeImageSheet(s7);
+
+ workbook.write();
+ workbook.close();
+ }
+
+ /**
+ * Writes out a sheet containing the various numerical formats
+ *
+ * @param s
+ */
+ private void writeNumberFormatSheet(WritableSheet s) throws WriteException
+ {
+ WritableCellFormat wrappedText = new WritableCellFormat
+ (WritableWorkbook.ARIAL_10_PT);
+ wrappedText.setWrap(true);
+
+ s.setColumnView(0,20);
+ s.setColumnView(4,20);
+ s.setColumnView(5,20);
+ s.setColumnView(6,20);
+
+ // Floats
+ Label l = new Label(0,0,"+/- Pi - default format", wrappedText);
+ s.addCell(l);
+
+ Number n = new Number(1,0,3.1415926535);
+ s.addCell(n);
+
+ n = new Number(2,0,-3.1415926535);
+ s.addCell(n);
+
+ l = new Label(0,1,"+/- Pi - integer format", wrappedText);
+ s.addCell(l);
+
+ WritableCellFormat cf1 = new WritableCellFormat(NumberFormats.INTEGER);
+ n = new Number(1,1,3.1415926535,cf1);
+ s.addCell(n);
+
+ n = new Number(2,1,-3.1415926535, cf1);
+ s.addCell(n);
+
+ l = new Label(0,2,"+/- Pi - float 2dps", wrappedText);
+ s.addCell(l);
+
+ WritableCellFormat cf2 = new WritableCellFormat(NumberFormats.FLOAT);
+ n = new Number(1,2,3.1415926535,cf2);
+ s.addCell(n);
+
+ n = new Number(2,2,-3.1415926535, cf2);
+ s.addCell(n);
+
+ l = new Label(0,3,"+/- Pi - custom 3dps",
+ wrappedText);
+ s.addCell(l);
+
+ NumberFormat dp3 = new NumberFormat("#.###");
+ WritableCellFormat dp3cell = new WritableCellFormat(dp3);
+ n = new Number(1,3,3.1415926535,dp3cell);
+ s.addCell(n);
+
+ n = new Number(2,3,-3.1415926535, dp3cell);
+ s.addCell(n);
+
+ l = new Label(0,4,"+/- Pi - custom &3.14",
+ wrappedText);
+ s.addCell(l);
+
+ NumberFormat pounddp2 = new NumberFormat(".00");
+ WritableCellFormat pounddp2cell = new WritableCellFormat(pounddp2);
+ n = new Number(1,4,3.1415926535,pounddp2cell);
+ s.addCell(n);
+
+ n = new Number(2,4,-3.1415926535, pounddp2cell);
+ s.addCell(n);
+
+ l = new Label(0,5,"+/- Pi - custom Text #.### Text",
+ wrappedText);
+ s.addCell(l);
+
+ NumberFormat textdp4 = new NumberFormat("Text#.####Text");
+ WritableCellFormat textdp4cell = new WritableCellFormat(textdp4);
+ n = new Number(1,5,3.1415926535, textdp4cell);
+ s.addCell(n);
+
+ n = new Number(2,5,-3.1415926535, textdp4cell);
+ s.addCell(n);
+
+ // Integers
+ l = new Label(4,0,"+/- Bilko default format");
+ s.addCell(l);
+ n = new Number(5, 0, 15042699);
+ s.addCell(n);
+ n = new Number(6, 0, -15042699);
+ s.addCell(n);
+
+ l = new Label(4,1,"+/- Bilko float format");
+ s.addCell(l);
+ WritableCellFormat cfi1 = new WritableCellFormat(NumberFormats.FLOAT);
+ n = new Number(5, 1, 15042699, cfi1);
+ s.addCell(n);
+ n = new Number(6, 1, -15042699, cfi1);
+ s.addCell(n);
+
+ l = new Label(4,2,"+/- Thousands separator");
+ s.addCell(l);
+ WritableCellFormat cfi2 = new WritableCellFormat
+ (NumberFormats.THOUSANDS_INTEGER);
+ n = new Number(5, 2, 15042699,cfi2 );
+ s.addCell(n);
+ n = new Number(6, 2, -15042699, cfi2);
+ s.addCell(n);
+
+ l = new Label(4,3,"+/- Accounting red - added 0.01");
+ s.addCell(l);
+ WritableCellFormat cfi3 = new WritableCellFormat
+ (NumberFormats.ACCOUNTING_RED_FLOAT);
+ n = new Number(5, 3, 15042699.01, cfi3);
+ s.addCell(n);
+ n = new Number(6, 3, -15042699.01, cfi3);
+ s.addCell(n);
+
+ l = new Label(4,4,"+/- Percent");
+ s.addCell(l);
+ WritableCellFormat cfi4 = new WritableCellFormat
+ (NumberFormats.PERCENT_INTEGER);
+ n = new Number(5, 4, 15042699, cfi4);
+ s.addCell(n);
+ n = new Number(6, 4, -15042699, cfi4);
+ s.addCell(n);
+
+ l = new Label(4,5,"+/- Exponential - 2dps");
+ s.addCell(l);
+ WritableCellFormat cfi5 = new WritableCellFormat
+ (NumberFormats.EXPONENTIAL);
+ n = new Number(5, 5, 15042699, cfi5);
+ s.addCell(n);
+ n = new Number(6, 5, -15042699, cfi5);
+ s.addCell(n);
+
+ l = new Label(4,6,"+/- Custom exponentional - 3dps", wrappedText);
+ s.addCell(l);
+ NumberFormat edp3 = new NumberFormat("0.000E0");
+ WritableCellFormat edp3Cell = new WritableCellFormat(edp3);
+ n = new Number(5,6,15042699,edp3Cell);
+ s.addCell(n);
+ n = new Number(6,6,-15042699,edp3Cell);
+ s.addCell(n);
+
+ l = new Label(4, 7, "Custom neg brackets", wrappedText);
+ s.addCell(l);
+ NumberFormat negbracks = new NumberFormat("#,##0;(#,##0)");
+ WritableCellFormat negbrackscell = new WritableCellFormat(negbracks);
+ n = new Number(5,7, 15042699, negbrackscell);
+ s.addCell(n);
+ n = new Number(6,7, -15042699, negbrackscell);
+ s.addCell(n);
+
+ l = new Label(4, 8, "Custom neg brackets 2", wrappedText);
+ s.addCell(l);
+ NumberFormat negbracks2 = new NumberFormat("#,##0;(#,##0)a");
+ WritableCellFormat negbrackscell2 = new WritableCellFormat(negbracks2);
+ n = new Number(5,8, 15042699, negbrackscell2);
+ s.addCell(n);
+ n = new Number(6,8, -15042699, negbrackscell2);
+ s.addCell(n);
+
+ l = new Label(4, 9, "Custom percent", wrappedText);
+ s.addCell(l);
+ NumberFormat cuspercent = new NumberFormat("0.0%");
+ WritableCellFormat cuspercentf = new WritableCellFormat(cuspercent);
+ n = new Number(5, 9, 3.14159265, cuspercentf);
+ s.addCell(n);
+
+
+ // Booleans
+ l = new Label(0,10, "Boolean - TRUE");
+ s.addCell(l);
+ Boolean b = new Boolean(1,10, true);
+ s.addCell(b);
+
+ l = new Label(0,11, "Boolean - FALSE");
+ s.addCell(l);
+ b = new Boolean(1,11,false);
+ s.addCell(b);
+
+ l = new Label(0, 12, "A hidden cell->");
+ s.addCell(l);
+ n = new Number(1, 12, 17, WritableWorkbook.HIDDEN_STYLE);
+ s.addCell(n);
+
+ // Currencies
+ l = new Label(4, 19, "Currency formats");
+ s.addCell(l);
+
+ l = new Label(4, 21, "UK Pound");
+ s.addCell(l);
+ NumberFormat poundCurrency =
+ new NumberFormat(NumberFormat.CURRENCY_POUND + " #,###.00",
+ NumberFormat.COMPLEX_FORMAT);
+ WritableCellFormat poundFormat = new WritableCellFormat(poundCurrency);
+ n = new Number(5, 21, 12345, poundFormat);
+ s.addCell(n);
+
+ l = new Label(4, 22, "Euro 1");
+ s.addCell(l);
+ NumberFormat euroPrefixCurrency =
+ new NumberFormat(NumberFormat.CURRENCY_EURO_PREFIX + " #,###.00",
+ NumberFormat.COMPLEX_FORMAT);
+ WritableCellFormat euroPrefixFormat =
+ new WritableCellFormat(euroPrefixCurrency);
+ n = new Number(5, 22, 12345, euroPrefixFormat);
+ s.addCell(n);
+
+ l = new Label(4, 23, "Euro 2");
+ s.addCell(l);
+ NumberFormat euroSuffixCurrency =
+ new NumberFormat("#,###.00" + NumberFormat.CURRENCY_EURO_SUFFIX,
+ NumberFormat.COMPLEX_FORMAT);
+ WritableCellFormat euroSuffixFormat =
+ new WritableCellFormat(euroSuffixCurrency);
+ n = new Number(5, 23, 12345, euroSuffixFormat);
+ s.addCell(n);
+
+ l = new Label(4, 24, "Dollar");
+ s.addCell(l);
+ NumberFormat dollarCurrency =
+ new NumberFormat(NumberFormat.CURRENCY_DOLLAR + " #,###.00",
+ NumberFormat.COMPLEX_FORMAT);
+ WritableCellFormat dollarFormat =
+ new WritableCellFormat(dollarCurrency);
+ n = new Number(5, 24, 12345, dollarFormat);
+ s.addCell(n);
+
+ l = new Label(4, 25, "Japanese Yen");
+ s.addCell(l);
+ NumberFormat japaneseYenCurrency =
+ new NumberFormat(NumberFormat.CURRENCY_JAPANESE_YEN + " #,###.00",
+ NumberFormat.COMPLEX_FORMAT);
+ WritableCellFormat japaneseYenFormat =
+ new WritableCellFormat(japaneseYenCurrency);
+ n = new Number(5, 25, 12345, japaneseYenFormat);
+ s.addCell(n);
+
+ l = new Label(4, 30, "Fraction formats");
+ s.addCell(l);
+
+ l = new Label(4,32, "One digit fraction format", wrappedText);
+ s.addCell(l);
+
+ WritableCellFormat fraction1digitformat =
+ new WritableCellFormat(NumberFormats.FRACTION_ONE_DIGIT);
+ n = new Number(5, 32, 3.18279, fraction1digitformat);
+ s.addCell(n);
+
+ l = new Label(4,33, "Two digit fraction format", wrappedText);
+ s.addCell(l);
+
+ WritableCellFormat fraction2digitformat =
+ new WritableCellFormat(NumberFormats.FRACTION_TWO_DIGITS);
+ n = new Number(5, 33, 3.18279, fraction2digitformat);
+ s.addCell(n);
+
+ l = new Label(4,34, "Three digit fraction format (improper)", wrappedText);
+ s.addCell(l);
+
+ NumberFormat fraction3digit1 =
+ new NumberFormat(NumberFormat.FRACTION_THREE_DIGITS,
+ NumberFormat.COMPLEX_FORMAT);
+ WritableCellFormat fraction3digitformat1 =
+ new WritableCellFormat(fraction3digit1);
+ n = new Number(5, 34, 3.18927, fraction3digitformat1);
+ s.addCell(n);
+
+ l = new Label(4,35, "Three digit fraction format (proper)", wrappedText);
+ s.addCell(l);
+
+ NumberFormat fraction3digit2 =
+ new NumberFormat("# " + NumberFormat.FRACTION_THREE_DIGITS,
+ NumberFormat.COMPLEX_FORMAT);
+ WritableCellFormat fraction3digitformat2 =
+ new WritableCellFormat(fraction3digit2);
+ n = new Number(5, 35, 3.18927, fraction3digitformat2);
+ s.addCell(n);
+
+ // Lots of numbers
+ for (int row = 0; row < 100; row++)
+ {
+ for (int col = 8; col < 108; col++)
+ {
+ n = new Number(col, row, col+row);
+ s.addCell(n);
+ }
+ }
+
+ // Lots of numbers
+ for (int row = 101; row < 3000; row++)
+ {
+ for (int col = 0; col < 25; col++)
+ {
+ n = new Number(col, row, col+row);
+ s.addCell(n);
+ }
+ }
+ }
+
+ /**
+ * Adds cells to the specified sheet which test the various date formats
+ *
+ * @param s
+ */
+ private void writeDateFormatSheet(WritableSheet s) throws WriteException
+ {
+ WritableCellFormat wrappedText = new WritableCellFormat
+ (WritableWorkbook.ARIAL_10_PT);
+ wrappedText.setWrap(true);
+
+ s.setColumnView(0, 20);
+ s.setColumnView(2, 20);
+ s.setColumnView(3, 20);
+ s.setColumnView(4, 20);
+
+ s.getSettings().setFitWidth(2);
+ s.getSettings().setFitHeight(2);
+
+ Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+ c.set(1975, 4, 31, 15, 21, 45);
+ c.set(Calendar.MILLISECOND, 660);
+ Date date = c.getTime();
+ c.set(1900, 0, 1, 0, 0, 0);
+ c.set(Calendar.MILLISECOND, 0);
+
+ Date date2 = c.getTime();
+ c.set(1970, 0, 1, 0, 0, 0);
+ Date date3 = c.getTime();
+ c.set(1918, 10, 11, 11, 0, 0);
+ Date date4 = c.getTime();
+ c.set(1900, 0, 2, 0, 0, 0);
+ Date date5 = c.getTime();
+ c.set(1901, 0, 1, 0, 0, 0);
+ Date date6 = c.getTime();
+ c.set(1900, 4, 31, 0, 0, 0);
+ Date date7 = c.getTime();
+ c.set(1900, 1, 1, 0, 0, 0);
+ Date date8 = c.getTime();
+ c.set(1900, 0, 31, 0, 0, 0);
+ Date date9 = c.getTime();
+ c.set(1900, 2, 1, 0, 0, 0);
+ Date date10 = c.getTime();
+ c.set(1900, 1, 27, 0, 0, 0);
+ Date date11 = c.getTime();
+ c.set(1900, 1, 28, 0, 0, 0);
+ Date date12 = c.getTime();
+ c.set(1980, 5, 31, 12, 0, 0);
+ Date date13 = c.getTime();
+ c.set(1066, 9, 14, 0, 0, 0);
+ Date date14 = c.getTime();
+
+ // Built in date formats
+ SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss.SSS");
+ sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
+ Label l = new Label(0,0,"All dates are " + sdf.format(date),
+ wrappedText);
+ s.addCell(l);
+
+ l = new Label(0,1,"Built in formats",
+ wrappedText);
+ s.addCell(l);
+
+ l = new Label(2, 1, "Custom formats");
+ s.addCell(l);
+
+ WritableCellFormat cf1 = new WritableCellFormat(DateFormats.FORMAT1);
+ DateTime dt = new DateTime(0,2,date, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT2);
+ dt = new DateTime(0,3,date, cf1,DateTime.GMT);
+ s.addCell(dt);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT3);
+ dt = new DateTime(0,4,date, cf1);
+ s.addCell(dt);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT4);
+ dt = new DateTime(0,5,date, cf1);
+ s.addCell(dt);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT5);
+ dt = new DateTime(0,6,date, cf1);
+ s.addCell(dt);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT6);
+ dt = new DateTime(0,7,date, cf1);
+ s.addCell(dt);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT7);
+ dt = new DateTime(0,8,date, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT8);
+ dt = new DateTime(0,9,date, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT9);
+ dt = new DateTime(0,10,date, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT10);
+ dt = new DateTime(0,11,date, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT11);
+ dt = new DateTime(0,12,date, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT12);
+ dt = new DateTime(0,13,date, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ // Custom formats
+ DateFormat df = new DateFormat("dd MM yyyy");
+ cf1 = new WritableCellFormat(df);
+ l = new Label(2, 2, "dd MM yyyy");
+ s.addCell(l);
+
+ dt = new DateTime(3, 2, date, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ df = new DateFormat("dd MMM yyyy");
+ cf1 = new WritableCellFormat(df);
+ l = new Label(2, 3, "dd MMM yyyy");
+ s.addCell(l);
+
+ dt = new DateTime(3, 3, date, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ df = new DateFormat("hh:mm");
+ cf1 = new WritableCellFormat(df);
+ l = new Label(2, 4, "hh:mm");
+ s.addCell(l);
+
+ dt = new DateTime(3, 4, date, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ df = new DateFormat("hh:mm:ss");
+ cf1 = new WritableCellFormat(df);
+ l = new Label(2, 5, "hh:mm:ss");
+ s.addCell(l);
+
+ dt = new DateTime(3, 5, date, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ df = new DateFormat("H:mm:ss a");
+ cf1 = new WritableCellFormat(df);
+ l = new Label(2, 5, "H:mm:ss a");
+ s.addCell(l);
+
+ dt = new DateTime(3, 5, date, cf1, DateTime.GMT);
+ s.addCell(dt);
+ dt = new DateTime(4, 5, date13, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ df = new DateFormat("mm:ss.SSS");
+ cf1 = new WritableCellFormat(df);
+ l = new Label(2, 6, "mm:ss.SSS");
+ s.addCell(l);
+
+ dt = new DateTime(3, 6, date, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ df = new DateFormat("hh:mm:ss a");
+ cf1 = new WritableCellFormat(df);
+ l = new Label(2, 7, "hh:mm:ss a");
+ s.addCell(l);
+
+ dt = new DateTime(4, 7, date13, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+
+ // Check out the zero date ie. 1 Jan 1900
+ l = new Label(0,16,"Zero date " + sdf.format(date2),
+ wrappedText);
+ s.addCell(l);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT9);
+ dt = new DateTime(0,17,date2, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ // Check out the zero date + 1 ie. 2 Jan 1900
+ l = new Label(3,16,"Zero date + 1 " + sdf.format(date5),
+ wrappedText);
+ s.addCell(l);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT9);
+ dt = new DateTime(3,17,date5, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ // Check out the 1 Jan 1901
+ l = new Label(3,19, sdf.format(date6),
+ wrappedText);
+ s.addCell(l);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT9);
+ dt = new DateTime(3,20,date6, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ // Check out the 31 May 1900
+ l = new Label(3,22, sdf.format(date7),
+ wrappedText);
+ s.addCell(l);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT9);
+ dt = new DateTime(3,23, date7, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ // Check out 1 Feb 1900
+ l = new Label(3,25, sdf.format(date8),
+ wrappedText);
+ s.addCell(l);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT9);
+ dt = new DateTime(3,26, date8, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ // Check out 31 Jan 1900
+ l = new Label(3,28, sdf.format(date9),
+ wrappedText);
+ s.addCell(l);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT9);
+ dt = new DateTime(3,29, date9, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ // Check out 31 Jan 1900
+ l = new Label(3,28, sdf.format(date9),
+ wrappedText);
+ s.addCell(l);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT9);
+ dt = new DateTime(3,29, date9, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ // Check out 1 Mar 1900
+ l = new Label(3,31, sdf.format(date10),
+ wrappedText);
+ s.addCell(l);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT9);
+ dt = new DateTime(3,32, date10, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ // Check out 27 Feb 1900
+ l = new Label(3,34, sdf.format(date11),
+ wrappedText);
+ s.addCell(l);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT9);
+ dt = new DateTime(3,35, date11, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ // Check out 28 Feb 1900
+ l = new Label(3,37, sdf.format(date12),
+ wrappedText);
+ s.addCell(l);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT9);
+ dt = new DateTime(3,38, date12, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ // Check out the zero date ie. 1 Jan 1970
+ l = new Label(0,19,"Zero UTC date " + sdf.format(date3),
+ wrappedText);
+ s.addCell(l);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT9);
+ dt = new DateTime(0,20,date3, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ // Check out the WWI armistice day ie. 11 am, Nov 11, 1918
+ l = new Label(0,22,"Armistice date " + sdf.format(date4),
+ wrappedText);
+ s.addCell(l);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT9);
+ dt = new DateTime(0,23,date4, cf1, DateTime.GMT);
+ s.addCell(dt);
+
+ // Check out the Battle of Hastings date Oct 14th, 1066
+ l = new Label(0,25, "Battle of Hastings " + sdf.format(date14),
+ wrappedText);
+ s.addCell(l);
+
+ cf1 = new WritableCellFormat(DateFormats.FORMAT2);
+ dt = new DateTime(0, 26, date14, cf1, DateTime.GMT);
+ s.addCell(dt);
+ }
+
+ /**
+ * Adds cells to the specified sheet which test the various label formatting
+ * styles, such as different fonts, different sizes and bold, underline etc.
+ *
+ * @param s1
+ */
+ private void writeLabelFormatSheet(WritableSheet s1) throws WriteException
+ {
+ s1.setColumnView(0, 60);
+
+ Label lr = new Label(0,0, "Arial Fonts");
+ s1.addCell(lr);
+
+ lr = new Label(1,0, "10pt");
+ s1.addCell(lr);
+
+ lr = new Label(2, 0, "Normal");
+ s1.addCell(lr);
+
+ lr = new Label(3, 0, "12pt");
+ s1.addCell(lr);
+
+ WritableFont arial12pt = new WritableFont(WritableFont.ARIAL, 12);
+ WritableCellFormat arial12format = new WritableCellFormat(arial12pt);
+ arial12format.setWrap(true);
+ lr = new Label(4, 0, "Normal", arial12format);
+ s1.addCell(lr);
+
+ WritableFont arial10ptBold = new WritableFont
+ (WritableFont.ARIAL, 10, WritableFont.BOLD);
+ WritableCellFormat arial10BoldFormat = new WritableCellFormat
+ (arial10ptBold);
+ lr = new Label(2, 2, "BOLD", arial10BoldFormat);
+ s1.addCell(lr);
+
+ WritableFont arial12ptBold = new WritableFont
+ (WritableFont.ARIAL, 12, WritableFont.BOLD);
+ WritableCellFormat arial12BoldFormat = new WritableCellFormat
+ (arial12ptBold);
+ lr = new Label(4, 2, "BOLD", arial12BoldFormat);
+ s1.addCell(lr);
+
+ WritableFont arial10ptItalic = new WritableFont
+ (WritableFont.ARIAL, 10, WritableFont.NO_BOLD, true);
+ WritableCellFormat arial10ItalicFormat = new WritableCellFormat
+ (arial10ptItalic);
+ lr = new Label(2, 4, "Italic", arial10ItalicFormat);
+ s1.addCell(lr);
+
+ WritableFont arial12ptItalic = new WritableFont
+ (WritableFont.ARIAL, 12, WritableFont.NO_BOLD, true);
+ WritableCellFormat arial12ptItalicFormat = new WritableCellFormat
+ (arial12ptItalic);
+ lr = new Label(4, 4, "Italic", arial12ptItalicFormat);
+ s1.addCell(lr);
+
+ WritableFont times10pt = new WritableFont(WritableFont.TIMES, 10);
+ WritableCellFormat times10format = new WritableCellFormat(times10pt);
+ lr = new Label(0, 7, "Times Fonts", times10format);
+ s1.addCell(lr);
+
+ lr = new Label(1, 7, "10pt", times10format);
+ s1.addCell(lr);
+
+ lr = new Label(2, 7, "Normal", times10format);
+ s1.addCell(lr);
+
+ lr = new Label(3, 7, "12pt", times10format);
+ s1.addCell(lr);
+
+ WritableFont times12pt = new WritableFont(WritableFont.TIMES, 12);
+ WritableCellFormat times12format = new WritableCellFormat(times12pt);
+ lr = new Label(4, 7, "Normal", times12format);
+ s1.addCell(lr);
+
+ WritableFont times10ptBold = new WritableFont
+ (WritableFont.TIMES, 10, WritableFont.BOLD);
+ WritableCellFormat times10BoldFormat = new WritableCellFormat
+ (times10ptBold);
+ lr = new Label(2, 9, "BOLD", times10BoldFormat);
+ s1.addCell(lr);
+
+ WritableFont times12ptBold = new WritableFont
+ (WritableFont.TIMES, 12, WritableFont.BOLD);
+ WritableCellFormat times12BoldFormat = new WritableCellFormat
+ (times12ptBold);
+ lr = new Label(4, 9, "BOLD", times12BoldFormat);
+ s1.addCell(lr);
+
+ // The underline styles
+ s1.setColumnView(6, 22);
+ s1.setColumnView(7, 22);
+ s1.setColumnView(8, 22);
+ s1.setColumnView(9, 22);
+
+ lr = new Label(0, 11, "Underlining");
+ s1.addCell(lr);
+
+ WritableFont arial10ptUnderline = new WritableFont
+ (WritableFont.ARIAL,
+ WritableFont.DEFAULT_POINT_SIZE,
+ WritableFont.NO_BOLD,
+ false,
+ UnderlineStyle.SINGLE);
+ WritableCellFormat arialUnderline = new WritableCellFormat
+ (arial10ptUnderline);
+ lr = new Label(6,11, "Underline", arialUnderline);
+ s1.addCell(lr);
+
+ WritableFont arial10ptDoubleUnderline = new WritableFont
+ (WritableFont.ARIAL,
+ WritableFont.DEFAULT_POINT_SIZE,
+ WritableFont.NO_BOLD,
+ false,
+ UnderlineStyle.DOUBLE);
+ WritableCellFormat arialDoubleUnderline = new WritableCellFormat
+ (arial10ptDoubleUnderline);
+ lr = new Label(7,11, "Double Underline", arialDoubleUnderline);
+ s1.addCell(lr);
+
+ WritableFont arial10ptSingleAcc = new WritableFont
+ (WritableFont.ARIAL,
+ WritableFont.DEFAULT_POINT_SIZE,
+ WritableFont.NO_BOLD,
+ false,
+ UnderlineStyle.SINGLE_ACCOUNTING);
+ WritableCellFormat arialSingleAcc = new WritableCellFormat
+ (arial10ptSingleAcc);
+ lr = new Label(8,11, "Single Accounting Underline", arialSingleAcc);
+ s1.addCell(lr);
+
+ WritableFont arial10ptDoubleAcc = new WritableFont
+ (WritableFont.ARIAL,
+ WritableFont.DEFAULT_POINT_SIZE,
+ WritableFont.NO_BOLD,
+ false,
+ UnderlineStyle.DOUBLE_ACCOUNTING);
+ WritableCellFormat arialDoubleAcc = new WritableCellFormat
+ (arial10ptDoubleAcc);
+ lr = new Label(9,11, "Double Accounting Underline", arialDoubleAcc);
+ s1.addCell(lr);
+
+ WritableFont times14ptBoldUnderline = new WritableFont
+ (WritableFont.TIMES,
+ 14,
+ WritableFont.BOLD,
+ false,
+ UnderlineStyle.SINGLE);
+ WritableCellFormat timesBoldUnderline = new WritableCellFormat
+ (times14ptBoldUnderline);
+ lr = new Label(6,12, "Times 14 Bold Underline", timesBoldUnderline);
+ s1.addCell(lr);
+
+ WritableFont arial18ptBoldItalicUnderline = new WritableFont
+ (WritableFont.ARIAL,
+ 18,
+ WritableFont.BOLD,
+ true,
+ UnderlineStyle.SINGLE);
+ WritableCellFormat arialBoldItalicUnderline = new WritableCellFormat
+ (arial18ptBoldItalicUnderline);
+ lr = new Label(6,13, "Arial 18 Bold Italic Underline",
+ arialBoldItalicUnderline);
+ s1.addCell(lr);
+
+ lr = new Label(0, 15, "Script styles");
+ s1.addCell(lr);
+
+ WritableFont superscript = new WritableFont
+ (WritableFont.ARIAL,
+ WritableFont.DEFAULT_POINT_SIZE,
+ WritableFont.NO_BOLD,
+ false,
+ UnderlineStyle.NO_UNDERLINE,
+ Colour.BLACK,
+ ScriptStyle.SUPERSCRIPT);
+ WritableCellFormat superscriptFormat = new WritableCellFormat
+ (superscript);
+ lr = new Label(1,15, "superscript", superscriptFormat);
+ s1.addCell(lr);
+
+ WritableFont subscript = new WritableFont
+ (WritableFont.ARIAL,
+ WritableFont.DEFAULT_POINT_SIZE,
+ WritableFont.NO_BOLD,
+ false,
+ UnderlineStyle.NO_UNDERLINE,
+ Colour.BLACK,
+ ScriptStyle.SUBSCRIPT);
+ WritableCellFormat subscriptFormat = new WritableCellFormat
+ (subscript);
+ lr = new Label(2,15, "subscript", subscriptFormat);
+ s1.addCell(lr);
+
+ lr = new Label(0, 17, "Colours");
+ s1.addCell(lr);
+
+ WritableFont red = new WritableFont(WritableFont.ARIAL,
+ WritableFont.DEFAULT_POINT_SIZE,
+ WritableFont.NO_BOLD,
+ false,
+ UnderlineStyle.NO_UNDERLINE,
+ Colour.RED);
+ WritableCellFormat redFormat = new WritableCellFormat(red);
+ lr = new Label(2, 17, "Red", redFormat);
+ s1.addCell(lr);
+
+ WritableFont blue = new WritableFont(WritableFont.ARIAL,
+ WritableFont.DEFAULT_POINT_SIZE,
+ WritableFont.NO_BOLD,
+ false,
+ UnderlineStyle.NO_UNDERLINE,
+ Colour.BLUE);
+ WritableCellFormat blueFormat = new WritableCellFormat(blue);
+ lr = new Label(2, 18, "Blue", blueFormat);
+ s1.addCell(lr);
+
+ WritableFont lime = new WritableFont(WritableFont.ARIAL);
+ lime.setColour(Colour.LIME);
+ WritableCellFormat limeFormat = new WritableCellFormat(lime);
+ limeFormat.setWrap(true);
+ lr = new Label(4, 18, "Modified palette - was lime, now red", limeFormat);
+ s1.addCell(lr);
+
+ WritableCellFormat greyBackground = new WritableCellFormat();
+ greyBackground.setWrap(true);
+ greyBackground.setBackground(Colour.GRAY_50);
+ lr = new Label(2, 19, "Grey background", greyBackground);
+ s1.addCell(lr);
+
+ WritableFont yellow = new WritableFont(WritableFont.ARIAL,
+ WritableFont.DEFAULT_POINT_SIZE,
+ WritableFont.NO_BOLD,
+ false,
+ UnderlineStyle.NO_UNDERLINE,
+ Colour.YELLOW);
+ WritableCellFormat yellowOnBlue = new WritableCellFormat(yellow);
+ yellowOnBlue.setWrap(true);
+ yellowOnBlue.setBackground(Colour.BLUE);
+ lr = new Label(2, 20, "Blue background, yellow foreground", yellowOnBlue);
+ s1.addCell(lr);
+
+ WritableCellFormat yellowOnBlack = new WritableCellFormat(yellow);
+ yellowOnBlack.setWrap(true);
+ yellowOnBlack.setBackground(Colour.PALETTE_BLACK);
+ lr = new Label(3, 20, "Black background, yellow foreground",
+ yellowOnBlack);
+ s1.addCell(lr);
+
+ lr = new Label(0, 22, "Null label");
+ s1.addCell(lr);
+
+ lr = new Label(2, 22, null);
+ s1.addCell(lr);
+
+ lr = new Label(0, 24,
+ "A very long label, more than 255 characters\012" +
+ "Rejoice O shores\012" +
+ "Sing O bells\012" +
+ "But I with mournful tread\012" +
+ "Walk the deck my captain lies\012" +
+ "Fallen cold and dead\012"+
+ "Summer surprised, coming over the Starnbergersee\012" +
+ "With a shower of rain. We stopped in the Colonnade\012" +
+ "A very long label, more than 255 characters\012" +
+ "Rejoice O shores\012" +
+ "Sing O bells\012" +
+ "But I with mournful tread\012" +
+ "Walk the deck my captain lies\012" +
+ "Fallen cold and dead\012"+
+ "Summer surprised, coming over the Starnbergersee\012" +
+ "With a shower of rain. We stopped in the Colonnade\012" + "A very long label, more than 255 characters\012" +
+ "Rejoice O shores\012" +
+ "Sing O bells\012" +
+ "But I with mournful tread\012" +
+ "Walk the deck my captain lies\012" +
+ "Fallen cold and dead\012"+
+ "Summer surprised, coming over the Starnbergersee\012" +
+ "With a shower of rain. We stopped in the Colonnade\012" + "A very long label, more than 255 characters\012" +
+ "Rejoice O shores\012" +
+ "Sing O bells\012" +
+ "But I with mournful tread\012" +
+ "Walk the deck my captain lies\012" +
+ "Fallen cold and dead\012"+
+ "Summer surprised, coming over the Starnbergersee\012" +
+ "With a shower of rain. We stopped in the Colonnade\012" +
+ "And sat and drank coffee an talked for an hour\012",
+ arial12format);
+ s1.addCell(lr);
+
+ WritableCellFormat vertical = new WritableCellFormat();
+ vertical.setOrientation(Orientation.VERTICAL);
+ lr = new Label(0, 26, "Vertical orientation", vertical);
+ s1.addCell(lr);
+
+
+ WritableCellFormat plus_90 = new WritableCellFormat();
+ plus_90.setOrientation(Orientation.PLUS_90);
+ lr = new Label(1, 26, "Plus 90", plus_90);
+ s1.addCell(lr);
+
+
+ WritableCellFormat minus_90 = new WritableCellFormat();
+ minus_90.setOrientation(Orientation.MINUS_90);
+ lr = new Label(2, 26, "Minus 90", minus_90);
+ s1.addCell(lr);
+
+ lr = new Label(0, 28, "Modified row height");
+ s1.addCell(lr);
+ s1.setRowView(28, 24*20);
+
+ lr = new Label(0, 29, "Collapsed row");
+ s1.addCell(lr);
+ s1.setRowView(29, true);
+
+ // Write hyperlinks
+ try
+ {
+ Label l = new Label(0, 30, "Hyperlink to home page");
+ s1.addCell(l);
+
+ URL url = new URL("http://www.andykhan.com/jexcelapi");
+ WritableHyperlink wh = new WritableHyperlink(0, 30, 8, 31, url);
+ s1.addHyperlink(wh);
+
+ // The below hyperlink clashes with above
+ WritableHyperlink wh2 = new WritableHyperlink(7, 30, 9, 31, url);
+ s1.addHyperlink(wh2);
+
+ l = new Label(4, 2, "File hyperlink to documentation");
+ s1.addCell(l);
+
+ File file = new File("../jexcelapi/docs/index.html");
+ wh = new WritableHyperlink(0, 32, 8, 32, file,
+ "JExcelApi Documentation");
+ s1.addHyperlink(wh);
+
+ // Add a hyperlink to another cell on this sheet
+ wh = new WritableHyperlink(0, 34, 8, 34,
+ "Link to another cell",
+ s1,
+ 0, 180, 1, 181);
+ s1.addHyperlink(wh);
+
+ file = new File("\\\\localhost\\file.txt");
+ wh = new WritableHyperlink(0, 36, 8, 36, file);
+ s1.addHyperlink(wh);
+
+ // Add a very long hyperlink
+ url = new URL("http://www.amazon.co.uk/exec/obidos/ASIN/0571058086"+
+ "/qid=1099836249/sr=1-3/ref=sr_1_11_3/202-6017285-1620664");
+ wh = new WritableHyperlink(0, 38, 0, 38, url);
+ s1.addHyperlink(wh);
+ }
+ catch (MalformedURLException e)
+ {
+ System.err.println(e.toString());
+ }
+
+ // Write out some merged cells
+ Label l = new Label(5, 35, "Merged cells", timesBoldUnderline);
+ s1.mergeCells(5, 35, 8, 37);
+ s1.addCell(l);
+
+ l = new Label(5, 38, "More merged cells");
+ s1.addCell(l);
+ Range r = s1.mergeCells(5, 38, 8, 41);
+ s1.insertRow(40);
+ s1.removeRow(39);
+ s1.unmergeCells(r);
+
+ // Merge cells and centre across them
+ WritableCellFormat wcf = new WritableCellFormat();
+ wcf.setAlignment(Alignment.CENTRE);
+ l = new Label(5, 42, "Centred across merged cells", wcf);
+ s1.addCell(l);
+ s1.mergeCells(5, 42, 10, 42);
+
+ wcf = new WritableCellFormat();
+ wcf.setBorder(Border.ALL, BorderLineStyle.THIN);
+ wcf.setBackground(Colour.GRAY_25);
+ l = new Label(3, 44, "Merged with border", wcf);
+ s1.addCell(l);
+ s1.mergeCells(3, 44, 4, 46);
+
+ // Clash some ranges - the second range will not be added
+ // Also merge some cells with two data items in the - the second data
+ // item will not be merged
+ /*
+ l = new Label(5, 16, "merged cells");
+ s1.addCell(l);
+
+ Label l5 = new Label(7, 17, "this label won't appear");
+ s1.addCell(l5);
+ s1.mergeCells(5, 16, 8, 18);
+
+ s1.mergeCells(5, 19, 6, 24);
+ s1.mergeCells(6, 18, 10, 19);
+ */
+
+ WritableFont courier10ptFont = new WritableFont(WritableFont.COURIER, 10);
+ WritableCellFormat courier10pt = new WritableCellFormat(courier10ptFont);
+ l = new Label(0, 49, "Courier fonts", courier10pt);
+ s1.addCell(l);
+
+ WritableFont tahoma12ptFont = new WritableFont(WritableFont.TAHOMA, 12);
+ WritableCellFormat tahoma12pt = new WritableCellFormat(tahoma12ptFont);
+ l = new Label(0, 50, "Tahoma fonts", tahoma12pt);
+ s1.addCell(l);
+
+ WritableFont.FontName wingdingsFont =
+ WritableFont.createFont("Wingdings 2");
+ WritableFont wingdings210ptFont = new WritableFont(wingdingsFont, 10);
+ WritableCellFormat wingdings210pt = new WritableCellFormat
+ (wingdings210ptFont);
+ l = new Label(0,51, "Bespoke Windgdings 2", wingdings210pt);
+ s1.addCell(l);
+
+ WritableCellFormat shrinkToFit = new WritableCellFormat(times12pt);
+ shrinkToFit.setShrinkToFit(true);
+ l = new Label(3,53, "Shrunk to fit", shrinkToFit);
+ s1.addCell(l);
+
+ l = new Label(3,55, "Some long wrapped text in a merged cell",
+ arial12format);
+ s1.addCell(l);
+ s1.mergeCells(3,55,4,55);
+
+ l = new Label(0, 57, "A cell with a comment");
+ WritableCellFeatures cellFeatures = new WritableCellFeatures();
+ cellFeatures.setComment("the cell comment");
+ l.setCellFeatures(cellFeatures);
+ s1.addCell(l);
+
+ l = new Label(0, 59,
+ "A cell with a long comment");
+ cellFeatures = new WritableCellFeatures();
+ cellFeatures.setComment("a very long cell comment indeed that won't " +
+ "fit inside a standard comment box, so a " +
+ "larger comment box is used instead",
+ 5, 6);
+ l.setCellFeatures(cellFeatures);
+ s1.addCell(l);
+
+ WritableCellFormat indented = new WritableCellFormat(times12pt);
+ indented.setIndentation(4);
+ l = new Label(0, 61, "Some indented text", indented);
+ s1.addCell(l);
+
+ l = new Label(0, 63, "Data validation: list");
+ s1.addCell(l);
+
+ Blank b = new Blank(1,63);
+ cellFeatures = new WritableCellFeatures();
+ ArrayList al = new ArrayList();
+ al.add("bagpuss");
+ al.add("clangers");
+ al.add("ivor the engine");
+ al.add("noggin the nog");
+ cellFeatures.setDataValidationList(al);
+ b.setCellFeatures(cellFeatures);
+ s1.addCell(b);
+
+ l = new Label(0, 64, "Data validation: number > 4.5");
+ s1.addCell(l);
+
+ b = new Blank(1,64);
+ cellFeatures = new WritableCellFeatures();
+ cellFeatures.setNumberValidation(4.5, WritableCellFeatures.GREATER_THAN);
+ b.setCellFeatures(cellFeatures);
+ s1.addCell(b);
+
+ l = new Label(0, 65, "Data validation: named range");
+ s1.addCell(l);
+
+ l = new Label(4, 65, "tiger");
+ s1.addCell(l);
+ l = new Label(5, 65, "sword");
+ s1.addCell(l);
+ l = new Label(6, 65, "honour");
+ s1.addCell(l);
+ l = new Label(7, 65, "company");
+ s1.addCell(l);
+ l = new Label(8, 65, "victory");
+ s1.addCell(l);
+ l = new Label(9, 65, "fortress");
+ s1.addCell(l);
+
+ b = new Blank(1,65);
+ cellFeatures = new WritableCellFeatures();
+ cellFeatures.setDataValidationRange("validation_range");
+ b.setCellFeatures(cellFeatures);
+ s1.addCell(b);
+
+ // Set the row grouping
+ s1.setRowGroup(39, 45, false);
+ // s1.setRowGroup(72, 74, true);
+ }
+
+ /**
+ * Adds cells to the specified sheet which test the various border
+ * styles
+ *
+ * @param s
+ */
+ private void writeBordersSheet(WritableSheet s) throws WriteException
+ {
+ s.getSettings().setProtected(true);
+
+ s.setColumnView(1, 15);
+ s.setColumnView(2, 15);
+ s.setColumnView(4, 15);
+ WritableCellFormat thickLeft = new WritableCellFormat();
+ thickLeft.setBorder(Border.LEFT, BorderLineStyle.THICK);
+ Label lr = new Label(1,0, "Thick left", thickLeft);
+ s.addCell(lr);
+
+ WritableCellFormat dashedRight = new WritableCellFormat();
+ dashedRight.setBorder(Border.RIGHT, BorderLineStyle.DASHED);
+ lr = new Label(2, 0, "Dashed right", dashedRight);
+ s.addCell(lr);
+
+ WritableCellFormat doubleTop = new WritableCellFormat();
+ doubleTop.setBorder(Border.TOP, BorderLineStyle.DOUBLE);
+ lr = new Label(1, 2, "Double top", doubleTop);
+ s.addCell(lr);
+
+ WritableCellFormat hairBottom = new WritableCellFormat();
+ hairBottom.setBorder(Border.BOTTOM, BorderLineStyle.HAIR);
+ lr = new Label(2, 2, "Hair bottom", hairBottom);
+ s.addCell(lr);
+
+ WritableCellFormat allThin = new WritableCellFormat();
+ allThin.setBorder(Border.ALL, BorderLineStyle.THIN);
+ lr = new Label(4, 2, "All thin", allThin);
+ s.addCell(lr);
+
+ WritableCellFormat twoBorders = new WritableCellFormat();
+ twoBorders.setBorder(Border.TOP, BorderLineStyle.THICK);
+ twoBorders.setBorder(Border.LEFT, BorderLineStyle.THICK);
+ lr = new Label(6,2, "Two borders", twoBorders);
+ s.addCell(lr);
+
+ // Create a cell in the middle of nowhere (out of the grow region)
+ lr = new Label(20, 20, "Dislocated cell - after a page break");
+ s.addCell(lr);
+
+ // Set the orientation and the margins
+ s.getSettings().setPaperSize(PaperSize.A3);
+ s.getSettings().setOrientation(PageOrientation.LANDSCAPE);
+ s.getSettings().setPageOrder(PageOrder.DOWN_THEN_RIGHT);
+ s.getSettings().setHeaderMargin(2);
+ s.getSettings().setFooterMargin(2);
+
+ s.getSettings().setTopMargin(3);
+ s.getSettings().setBottomMargin(3);
+
+ // Add a header and footera
+ HeaderFooter header = new HeaderFooter();
+ header.getCentre().append("Page Header");
+ s.getSettings().setHeader(header);
+
+ HeaderFooter footer = new HeaderFooter();
+ footer.getRight().append("page ");
+ footer.getRight().appendPageNumber();
+ s.getSettings().setFooter(footer);
+
+ // Add a page break and insert a couple of rows
+ s.addRowPageBreak(18);
+ s.insertRow(17);
+ s.insertRow(17);
+ s.removeRow(17);
+
+ // Add a page break off the screen
+ s.addRowPageBreak(30);
+
+ // Add a hidden column
+ lr = new Label(10, 1, "Hidden column");
+ s.addCell(lr);
+
+ lr = new Label(3, 8, "Hidden row");
+ s.addCell(lr);
+ s.setRowView(8, true);
+
+ WritableCellFormat allThickRed = new WritableCellFormat();
+ allThickRed.setBorder(Border.ALL, BorderLineStyle.THICK, Colour.RED);
+ lr = new Label(1, 5, "All thick red", allThickRed);
+ s.addCell(lr);
+
+ WritableCellFormat topBottomBlue = new WritableCellFormat();
+ topBottomBlue.setBorder(Border.TOP, BorderLineStyle.THIN, Colour.BLUE);
+ topBottomBlue.setBorder(Border.BOTTOM, BorderLineStyle.THIN, Colour.BLUE);
+ lr = new Label(4, 5, "Top and bottom blue", topBottomBlue);
+ s.addCell(lr);
+ }
+
+ /**
+ * Write out loads of labels, in order to test the shared string table
+ */
+ private void writeLabelsSheet(WritableSheet ws) throws WriteException
+ {
+ ws.getSettings().setProtected(true);
+ ws.getSettings().setPassword("jxl");
+ ws.getSettings().setVerticalFreeze(5);
+ ws.getSettings().setDefaultRowHeight(25*20);
+
+ WritableFont wf = new WritableFont(WritableFont.ARIAL, 12);
+ wf.setItalic(true);
+
+ WritableCellFormat wcf = new WritableCellFormat(wf);
+
+ CellView cv = new CellView();
+ cv.setSize(25 * 256);
+ cv.setFormat(wcf);
+ ws.setColumnView(0, cv);
+ ws.setColumnView(1, 15);
+
+ for (int i = 0; i < 61; i++)
+ {
+ Label l1 = new Label(0, i, "Common Label");
+ Label l2 = new Label(1, i, "Distinct label number " + i);
+ ws.addCell(l1);
+ ws.addCell(l2);
+ }
+
+ // Frig this test record - it appears exactly on the boundary of an SST
+ // continue record
+
+ Label l3 = new Label(0, 61, "Common Label", wcf);
+ Label l4 = new Label(1, 61, "1-1234567890", wcf);
+ Label l5 = new Label(2, 61, "2-1234567890", wcf);
+ ws.addCell(l3);
+ ws.addCell(l4);
+ ws.addCell(l5);
+
+ for (int i = 62; i < 200; i++)
+ {
+ Label l1 = new Label(0, i, "Common Label");
+ Label l2 = new Label(1, i, "Distinct label number " + i);
+ ws.addCell(l1);
+ ws.addCell(l2);
+ }
+
+ // Add in a last label which doesn't take the common format
+ wf = new WritableFont(WritableFont.TIMES, 10, WritableFont.BOLD);
+ wf.setColour(Colour.RED);
+ WritableCellFormat wcf2 = new WritableCellFormat(wf);
+ wcf2.setWrap(true);
+ Label l = new Label(0, 205, "Different format", wcf2);
+ ws.addCell(l);
+
+ // Add some labels to column 5 for autosizing
+ Label l6 = new Label(5, 2, "A column for autosizing", wcf2);
+ ws.addCell(l6);
+ l6 = new Label(5, 4, "Another label, longer this time and " +
+ "in a different font");
+ ws.addCell(l6);
+
+ CellView cf = new CellView();
+ cf.setAutosize(true);
+ ws.setColumnView(5, cf);
+ }
+
+ /**
+ * Test out the formula parser
+ */
+ private void writeFormulaSheet(WritableSheet ws) throws WriteException
+ {
+ // Add some cells to manipulate
+ Number nc = new Number(0,0,15);
+ ws.addCell(nc);
+
+ nc = new Number(0,1,16);
+ ws.addCell(nc);
+
+ nc = new Number(0,2,10);
+ ws.addCell(nc);
+
+ nc = new Number(0,3, 12);
+ ws.addCell(nc);
+
+ ws.setColumnView(2, 20);
+ WritableCellFormat wcf = new WritableCellFormat();
+ wcf.setAlignment(Alignment.RIGHT);
+ wcf.setWrap(true);
+ CellView cv = new CellView();
+ cv.setSize(25 * 256);
+ cv.setFormat(wcf);
+ ws.setColumnView(3, cv);
+
+ // Add in the formulas
+ Formula f = null;
+ Label l = null;
+
+ f = new Formula(2,0, "A1+A2");
+ ws.addCell(f);
+ l = new Label(3, 0, "a1+a2");
+ ws.addCell(l);
+
+ f = new Formula(2,1, "A2 * 3");
+ ws.addCell(f);
+ l = new Label(3,1, "A2 * 3");
+ ws.addCell(l);
+
+ f = new Formula(2,2, "A2+A1/2.5");
+ ws.addCell(f);
+ l = new Label(3,2, "A2+A1/2.5");
+ ws.addCell(l);
+
+ f = new Formula(2,3, "3+(a1+a2)/2.5");
+ ws.addCell(f);
+ l = new Label(3,3, "3+(a1+a2)/2.5");
+ ws.addCell(l);
+
+ f = new Formula(2,4, "(a1+a2)/2.5");
+ ws.addCell(f);
+ l = new Label(3,4, "(a1+a2)/2.5");
+ ws.addCell(l);
+
+ f = new Formula(2,5, "15+((a1+a2)/2.5)*17");
+ ws.addCell(f);
+ l = new Label(3,5, "15+((a1+a2)/2.5)*17");
+ ws.addCell(l);
+
+ f = new Formula(2, 6, "SUM(a1:a4)");
+ ws.addCell(f);
+ l = new Label(3, 6, "SUM(a1:a4)");
+ ws.addCell(l);
+
+ f = new Formula(2, 7, "SUM(a1:a4)/4");
+ ws.addCell(f);
+ l = new Label(3, 7, "SUM(a1:a4)/4");
+ ws.addCell(l);
+
+ f = new Formula(2, 8, "AVERAGE(A1:A4)");
+ ws.addCell(f);
+ l = new Label(3, 8, "AVERAGE(a1:a4)");
+ ws.addCell(l);
+
+ f = new Formula(2, 9, "MIN(5,4,1,2,3)");
+ ws.addCell(f);
+ l = new Label(3, 9, "MIN(5,4,1,2,3)");
+ ws.addCell(l);
+
+ f = new Formula(2, 10, "ROUND(3.14159265, 3)");
+ ws.addCell(f);
+ l = new Label(3, 10, "ROUND(3.14159265, 3)");
+ ws.addCell(l);
+
+ f = new Formula(2, 11, "MAX(SUM(A1:A2), A1*A2, POWER(A1, 2))");
+ ws.addCell(f);
+ l = new Label(3, 11, "MAX(SUM(A1:A2), A1*A2, POWER(A1, 2))");
+ ws.addCell(l);
+
+ f = new Formula(2,12, "IF(A2>A1, \"A2 bigger\", \"A1 bigger\")");
+ ws.addCell(f);
+ l = new Label(3,12, "IF(A2>A1, \"A2 bigger\", \"A1 bigger\")");
+ ws.addCell(l);
+
+ f = new Formula(2,13, "IF(A2<=A1, \"A2 smaller\", \"A1 smaller\")");
+ ws.addCell(f);
+ l = new Label(3,13, "IF(A2<=A1, \"A2 smaller\", \"A1 smaller\")");
+ ws.addCell(l);
+
+ f = new Formula(2,14, "IF(A3<=10, \"<= 10\")");
+ ws.addCell(f);
+ l = new Label(3,14, "IF(A3<=10, \"<= 10\")");
+ ws.addCell(l);
+
+ f = new Formula(2, 15, "SUM(1,2,3,4,5)");
+ ws.addCell(f);
+ l = new Label(3, 15, "SUM(1,2,3,4,5)");
+ ws.addCell(l);
+
+ f = new Formula(2, 16, "HYPERLINK(\"http://www.andykhan.com/jexcelapi\", \"JExcelApi Home Page\")");
+ ws.addCell(f);
+ l = new Label(3, 16, "HYPERLINK(\"http://www.andykhan.com/jexcelapi\", \"JExcelApi Home Page\")");
+ ws.addCell(l);
+
+ f = new Formula(2, 17, "3*4+5");
+ ws.addCell(f);
+ l = new Label(3, 17, "3*4+5");
+ ws.addCell(l);
+
+ f = new Formula(2, 18, "\"Plain text formula\"");
+ ws.addCell(f);
+ l = new Label(3, 18, "Plain text formula");
+ ws.addCell(l);
+
+ f = new Formula(2, 19, "SUM(a1,a2,-a3,a4)");
+ ws.addCell(f);
+ l = new Label(3, 19, "SUM(a1,a2,-a3,a4)");
+ ws.addCell(l);
+
+ f = new Formula(2, 20, "2*-(a1+a2)");
+ ws.addCell(f);
+ l = new Label(3, 20, "2*-(a1+a2)");
+ ws.addCell(l);
+
+ f = new Formula(2, 21, "'Number Formats'!B1/2");
+ ws.addCell(f);
+ l = new Label(3, 21, "'Number Formats'!B1/2");
+ ws.addCell(l);
+
+ f = new Formula(2, 22, "IF(F22=0, 0, F21/F22)");
+ ws.addCell(f);
+ l = new Label(3, 22, "IF(F22=0, 0, F21/F22)");
+ ws.addCell(l);
+
+ f = new Formula(2, 23, "RAND()");
+ ws.addCell(f);
+ l = new Label(3, 23, "RAND()");
+ ws.addCell(l);
+
+ StringBuffer buf = new StringBuffer();
+ buf.append("'");
+ buf.append(workbook.getSheet(0).getName());
+ buf.append("'!");
+ buf.append(CellReferenceHelper.getCellReference(9, 18));
+ buf.append("*25");
+ f = new Formula(2, 24, buf.toString());
+ ws.addCell(f);
+ l = new Label(3, 24, buf.toString());
+ ws.addCell(l);
+
+ wcf = new WritableCellFormat(DateFormats.DEFAULT);
+ f = new Formula(2, 25, "NOW()", wcf);
+ ws.addCell(f);
+ l = new Label(3, 25, "NOW()");
+ ws.addCell(l);
+
+ f = new Formula(2, 26, "$A$2+A3");
+ ws.addCell(f);
+ l = new Label(3, 26, "$A$2+A3");
+ ws.addCell(l);
+
+ f = new Formula(2, 27, "IF(COUNT(A1:A9,B1:B9)=0,\"\",COUNT(A1:A9,B1:B9))");
+ ws.addCell(f);
+ l = new Label(3, 27, "IF(COUNT(A1:A9,B1:B9)=0,\"\",COUNT(A1:A9,B1:B9))");
+ ws.addCell(l);
+
+ f = new Formula(2, 28, "SUM(A1,A2,A3,A4)");
+ ws.addCell(f);
+ l = new Label(3, 28, "SUM(A1,A2,A3,A4)");
+ ws.addCell(l);
+
+ l = new Label(1, 29, "a1");
+ ws.addCell(l);
+ f = new Formula(2, 29, "SUM(INDIRECT(ADDRESS(2,29)):A4)");
+ ws.addCell(f);
+ l = new Label(3, 29, "SUM(INDIRECT(ADDRESS(2,29):A4)");
+ ws.addCell(l);
+
+ f = new Formula(2, 30, "COUNTIF(A1:A4, \">=12\")");
+ ws.addCell(f);
+ l = new Label(3, 30, "COUNTIF(A1:A4, \">=12\")");
+ ws.addCell(l);
+
+ f = new Formula(2, 31, "MAX($A$1:$A$4)");
+ ws.addCell(f);
+ l = new Label(3, 31, "MAX($A$1:$A$4)");
+ ws.addCell(l);
+
+ f = new Formula(2, 32, "OR(A1,TRUE)");
+ ws.addCell(f);
+ l = new Label(3, 32, "OR(A1,TRUE)");
+ ws.addCell(l);
+
+ f = new Formula(2, 33, "ROWS(A1:C14)");
+ ws.addCell(f);
+ l = new Label(3, 33, "ROWS(A1:C14)");
+ ws.addCell(l);
+
+ f = new Formula(2, 34, "COUNTBLANK(A1:C14)");
+ ws.addCell(f);
+ l = new Label(3, 34, "COUNTBLANK(A1:C14)");
+ ws.addCell(l);
+
+ f = new Formula(2, 35, "IF(((F1=\"Not Found\")*(F2=\"Not Found\")*(F3=\"\")*(F4=\"\")*(F5=\"\")),1,0)");
+ ws.addCell(f);
+ l = new Label(3, 35, "IF(((F1=\"Not Found\")*(F2=\"Not Found\")*(F3=\"\")*(F4=\"\")*(F5=\"\")),1,0)");
+ ws.addCell(l);
+
+ f = new Formula(2, 36,
+ "HYPERLINK(\"http://www.amazon.co.uk/exec/obidos/ASIN/0571058086qid=1099836249/sr=1-3/ref=sr_1_11_3/202-6017285-1620664\", \"Long hyperlink\")");
+ ws.addCell(f);
+
+ f = new Formula(2, 37, "1234567+2699");
+ ws.addCell(f);
+ l = new Label(3, 37, "1234567+2699");
+ ws.addCell(l);
+
+ f = new Formula(2, 38, "IF(ISERROR(G25/G29),0,-1)");
+ ws.addCell(f);
+ l = new Label(3, 38, "IF(ISERROR(G25/G29),0,-1)");
+ ws.addCell(l);
+
+ f = new Formula(2, 39, "SEARCH(\"C\",D40)");
+ ws.addCell(f);
+ l = new Label(3, 39, "SEARCH(\"C\",D40)");
+ ws.addCell(l);
+
+ f = new Formula(2, 40, "#REF!");
+ ws.addCell(f);
+ l = new Label(3, 40, "#REF!");
+ ws.addCell(l);
+
+ nc = new Number (1,41, 79);
+ ws.addCell(nc);
+ f = new Formula(2, 41, "--B42");
+ ws.addCell(f);
+ l = new Label(3, 41, "--B42");
+ ws.addCell(l);
+
+ f = new Formula(2, 42, "CHOOSE(3,A1,A2,A3,A4");
+ ws.addCell(f);
+ l = new Label(3,42, "CHOOSE(3,A1,A2,A3,A4");
+ ws.addCell(l);
+
+ f = new Formula(2, 43, "A4-A3-A2");
+ ws.addCell(f);
+ l = new Label(3,43, "A4-A3-A2");
+ ws.addCell(l);
+
+ f = new Formula(2, 44, "F29+F34+F41+F48+F55+F62+F69+F76+F83+F90+F97+F104+F111+F118+F125+F132+F139+F146+F153+F160+F167+F174+F181+F188+F195+F202+F209+F216+F223+F230+F237+F244+F251+F258+F265+F272+F279+F286+F293+F300+F305+F308");
+ ws.addCell(f);
+ l = new Label(3, 44, "F29+F34+F41+F48+F55+F62+F69+F76+F83+F90+F97+F104+F111+F118+F125+F132+F139+F146+F153+F160+F167+F174+F181+F188+F195+F202+F209+F216+F223+F230+F237+F244+F251+F258+F265+F272+F279+F286+F293+F300+F305+F308");
+ ws.addCell(l);
+ // Errors
+ /*
+ f = new Formula(2, 25, "PLOP(15)"); // unknown function
+ ws.addCell(f);
+
+ f = new Formula(2, 26, "SUM(15,3"); // unmatched parentheses
+ ws.addCell(f);
+
+ f = new Formula(2, 27, "SUM15,3)"); // missing opening parentheses
+ ws.addCell(f);
+
+ f = new Formula(2, 28, "ROUND(3.14159)"); // missing args
+ ws.addCell(f);
+
+ f = new Formula(2, 29, "NONSHEET!A1"); // sheet not found
+ ws.addCell(f);
+ */
+ }
+
+ /**
+ * Write out the images
+ */
+ private void writeImageSheet(WritableSheet ws) throws WriteException
+ {
+ Label l = new Label(0, 0, "Weald & Downland Open Air Museum, Sussex");
+ ws.addCell(l);
+
+ WritableImage wi = new WritableImage
+ (0, 3, 5, 7, new File("resources/wealdanddownland.png"));
+ ws.addImage(wi);
+
+ l = new Label(0, 12, "Merchant Adventurers Hall, York");
+ ws.addCell(l);
+
+ wi = new WritableImage(5, 12, 4, 10,
+ new File("resources/merchantadventurers.png"));
+ ws.addImage(wi);
+
+ // An unsupported file type
+ /*
+ wi = new WritableImage(0, 60, 5, 5, new File("resources/somefile.gif"));
+ ws.addImage(wi);
+ */
+ }
+}
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/demo/WriteAccess.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/demo/WriteAccess.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/demo/WriteAccess.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,82 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.demo;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import jxl.WorkbookSettings;
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.read.biff.BiffException;
+import jxl.read.biff.BiffRecordReader;
+import jxl.read.biff.File;
+import jxl.read.biff.Record;
+
+/**
+ * Displays whatever generated the excel file (ie. the WriteAccess record)
+ */
+class WriteAccess
+{
+ private BiffRecordReader reader;
+
+ public WriteAccess(java.io.File file)
+ throws IOException, BiffException
+ {
+ WorkbookSettings ws = new WorkbookSettings();
+ FileInputStream fis = new FileInputStream(file);
+ File f = new File(fis, ws);
+ reader = new BiffRecordReader(f);
+
+ display(ws);
+ fis.close();
+ }
+
+ /**
+ * Dumps out the contents of the excel file
+ */
+ private void display(WorkbookSettings ws) throws IOException
+ {
+ Record r = null;
+ boolean found = false;
+ while (reader.hasNext() && !found)
+ {
+ r = reader.next();
+ if (r.getType() == Type.WRITEACCESS)
+ {
+ found = true;
+ }
+ }
+
+ if (!found)
+ {
+ System.err.println("Warning: could not find write access record");
+ return;
+ }
+
+ byte[] data = r.getData();
+
+ String s = null;
+
+ s = StringHelper.getString(data, data.length, 0, ws);
+
+ System.out.println(s);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/demo/XML.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/demo/XML.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/demo/XML.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,326 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.demo;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+
+import jxl.Cell;
+import jxl.CellType;
+import jxl.Sheet;
+import jxl.Workbook;
+import jxl.format.Border;
+import jxl.format.BorderLineStyle;
+import jxl.format.CellFormat;
+import jxl.format.Colour;
+import jxl.format.Font;
+import jxl.format.Pattern;
+
+/**
+ * Simple demo class which uses the api to present the contents
+ * of an excel 97 spreadsheet as an XML document, using a workbook
+ * and output stream of your choice
+ */
+public class XML
+{
+ /**
+ * The output stream to write to
+ */
+ private OutputStream out;
+
+ /**
+ * The encoding to write
+ */
+ private String encoding;
+
+ /**
+ * The workbook we are reading from
+ */
+ private Workbook workbook;
+
+ /**
+ * Constructor
+ *
+ * @param w The workbook to interrogate
+ * @param out The output stream to which the XML values are written
+ * @param enc The encoding used by the output stream. Null or
+ * unrecognized values cause the encoding to default to UTF8
+ * @param f Indicates whether the generated XML document should contain
+ * the cell format information
+ * @exception java.io.IOException
+ */
+ public XML(Workbook w, OutputStream out, String enc, boolean f)
+ throws IOException
+ {
+ encoding = enc;
+ workbook = w;
+ this.out = out;
+
+ if (encoding == null || !encoding.equals("UnicodeBig"))
+ {
+ encoding = "UTF8";
+ }
+
+ if (f)
+ {
+ writeFormattedXML();
+ }
+ else
+ {
+ writeXML();
+ }
+
+ }
+
+ /**
+ * Writes out the workbook data as XML, without formatting information
+ */
+ private void writeXML() throws IOException
+ {
+ try
+ {
+ OutputStreamWriter osw = new OutputStreamWriter(out, encoding);
+ BufferedWriter bw = new BufferedWriter(osw);
+
+ bw.write("");
+ bw.newLine();
+ bw.write("");
+ bw.newLine();
+ bw.newLine();
+ bw.write("");
+ bw.newLine();
+ for (int sheet = 0; sheet < workbook.getNumberOfSheets(); sheet++)
+ {
+ Sheet s = workbook.getSheet(sheet);
+
+ bw.write(" ");
+ bw.newLine();
+ bw.write(" ");
+ bw.newLine();
+
+ Cell[] row = null;
+
+ for (int i = 0 ; i < s.getRows() ; i++)
+ {
+ bw.write(" ");
+ bw.newLine();
+ row = s.getRow(i);
+
+ for (int j = 0 ; j < row.length; j++)
+ {
+ if (row[j].getType() != CellType.EMPTY)
+ {
+ bw.write(" ");
+ bw.write("");
+ bw.write("");
+ bw.newLine();
+ }
+ }
+ bw.write("
");
+ bw.newLine();
+ }
+ bw.write(" ");
+ bw.newLine();
+ }
+
+ bw.write(" ");
+ bw.newLine();
+
+ bw.flush();
+ bw.close();
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ System.err.println(e.toString());
+ }
+ }
+
+ /**
+ * Writes out the workbook data as XML, with formatting information
+ */
+ private void writeFormattedXML() throws IOException
+ {
+ try
+ {
+ OutputStreamWriter osw = new OutputStreamWriter(out, encoding);
+ BufferedWriter bw = new BufferedWriter(osw);
+
+ bw.write("");
+ bw.newLine();
+ bw.write("");
+ bw.newLine();
+ bw.newLine();
+ bw.write("");
+ bw.newLine();
+ for (int sheet = 0; sheet < workbook.getNumberOfSheets(); sheet++)
+ {
+ Sheet s = workbook.getSheet(sheet);
+
+ bw.write(" ");
+ bw.newLine();
+ bw.write(" ");
+ bw.newLine();
+
+ Cell[] row = null;
+ CellFormat format = null;
+ Font font = null;
+
+ for (int i = 0 ; i < s.getRows() ; i++)
+ {
+ bw.write(" ");
+ bw.newLine();
+ row = s.getRow(i);
+
+ for (int j = 0 ; j < row.length; j++)
+ {
+ // Remember that empty cells can contain format information
+ if ((row[j].getType() != CellType.EMPTY) ||
+ (row[j].getCellFormat() != null))
+ {
+ format = row[j].getCellFormat();
+ bw.write(" ");
+ bw.newLine();
+ bw.write(" ");
+ bw.write("");
+ bw.write(" ");
+ bw.newLine();
+
+ if (row[j].getCellFormat() != null)
+ {
+ bw.write(" ");
+ bw.newLine();
+
+ // The font information
+ font = format.getFont();
+ bw.write(" ");
+ bw.newLine();
+
+
+ // The cell background information
+ if (format.getBackgroundColour() != Colour.DEFAULT_BACKGROUND ||
+ format.getPattern() != Pattern.NONE)
+ {
+ bw.write(" ");
+ bw.newLine();
+ }
+
+
+ // The cell border, if it has one
+ if (format.getBorder(Border.TOP ) != BorderLineStyle.NONE ||
+ format.getBorder(Border.BOTTOM) != BorderLineStyle.NONE ||
+ format.getBorder(Border.LEFT) != BorderLineStyle.NONE ||
+ format.getBorder(Border.RIGHT) != BorderLineStyle.NONE)
+ {
+
+ bw.write(" ");
+ bw.newLine();
+ }
+
+ // The cell number/date format
+ if (!format.getFormat().getFormatString().equals(""))
+ {
+ bw.write(" ");
+ bw.newLine();
+ }
+
+ bw.write(" ");
+ bw.newLine();
+ }
+
+ bw.write(" ");
+ bw.newLine();
+ }
+ }
+ bw.write("
");
+ bw.newLine();
+ }
+ bw.write(" ");
+ bw.newLine();
+ }
+
+ bw.write(" ");
+ bw.newLine();
+
+ bw.flush();
+ bw.close();
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ System.err.println(e.toString());
+ }
+ }
+
+}
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/format/Alignment.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/Alignment.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/Alignment.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,126 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.format;
+
+/**
+ * Enumeration class which contains the various alignments for data within a
+ * cell
+ */
+public /*final*/ class Alignment
+{
+ /**
+ * The internal numerical repreentation of the alignment
+ */
+ private int value;
+
+ /**
+ * The string description of this alignment
+ */
+ private String string;
+
+ /**
+ * The list of alignments
+ */
+ private static Alignment[] alignments = new Alignment[0];
+
+ /**
+ * Private constructor
+ *
+ * @param val
+ * @param string
+ */
+ protected Alignment(int val,String s)
+ {
+ value = val;
+ string = s;
+
+ Alignment[] oldaligns = alignments;
+ alignments = new Alignment[oldaligns.length + 1];
+ System.arraycopy(oldaligns, 0, alignments, 0, oldaligns.length);
+ alignments[oldaligns.length] = this;
+ }
+
+ /**
+ * Gets the value of this alignment. This is the value that is written to
+ * the generated Excel file
+ *
+ * @return the binary value
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Gets the string description of this alignment
+ *
+ * @return the string description
+ */
+ public String getDescription()
+ {
+ return string;
+ }
+
+ /**
+ * Gets the alignment from the value
+ *
+ * @param val
+ * @return the alignment with that value
+ */
+ public static Alignment getAlignment(int val)
+ {
+ for (int i = 0 ; i < alignments.length ; i++)
+ {
+ if (alignments[i].getValue() == val)
+ {
+ return alignments[i];
+ }
+ }
+
+ return GENERAL;
+ }
+
+ /**
+ * The standard alignment
+ */
+ public static Alignment GENERAL = new Alignment(0, "general");
+ /**
+ * Data cells with this alignment will appear at the left hand edge of the
+ * cell
+ */
+ public static Alignment LEFT = new Alignment(1, "left");
+ /**
+ * Data in cells with this alignment will be centred
+ */
+ public static Alignment CENTRE = new Alignment(2, "centre");
+ /**
+ * Data in cells with this alignment will be right aligned
+ */
+ public static Alignment RIGHT = new Alignment(3, "right");
+ /**
+ * Data in cells with this alignment will fill the cell
+ */
+ public static Alignment FILL = new Alignment(4,"fill");
+ /**
+ * Data in cells with this alignment will be justified
+ */
+ public static Alignment JUSTIFY = new Alignment(5, "justify");
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/format/BoldStyle.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/BoldStyle.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/BoldStyle.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,81 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.format;
+
+/**
+ * Enumeration class containing the various bold styles for data
+ */
+public /*final*/ class BoldStyle
+{
+ /**
+ * The bold weight
+ */
+ private int value;
+
+ /**
+ * The description
+ */
+ private String string;
+
+ /**
+ * Constructor
+ *
+ * @param val
+ */
+ protected BoldStyle(int val, String s)
+ {
+ value = val;
+ string = s;
+ }
+
+ /**
+ * Gets the value of the bold weight. This is the value that will be
+ * written to the generated Excel file.
+ *
+ * @return the bold weight
+ */
+ public int getValue()
+ {
+ return value ;
+ }
+
+ /**
+ * Gets the string description of the bold style
+ */
+ public String getDescription()
+ {
+ return string;
+ }
+
+ /**
+ * Normal style
+ */
+ public static final BoldStyle NORMAL = new BoldStyle(0x190, "Normal");
+ /**
+ * Emboldened style
+ */
+ public static final BoldStyle BOLD = new BoldStyle(0x2bc, "Bold");
+}
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/format/Border.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/Border.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/Border.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,55 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.format;
+
+/**
+ * The location of a border
+ */
+public /*final*/ class Border
+{
+ /**
+ * The string description
+ */
+ private String string;
+
+ /**
+ * Constructor
+ */
+ protected Border(String s)
+ {
+ string = s;
+ }
+
+ /**
+ * Gets the description
+ */
+ public String getDescription()
+ {
+ return string;
+ }
+
+ public final static Border NONE = new Border("none");
+ public final static Border ALL = new Border("all");
+ public final static Border TOP = new Border("top");
+ public final static Border BOTTOM = new Border("bottom");
+ public final static Border LEFT = new Border("left");
+ public final static Border RIGHT = new Border("right");
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/format/BorderLineStyle.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/BorderLineStyle.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/BorderLineStyle.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,122 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.format;
+
+/**
+ * The border line style
+ */
+public /*final*/ class BorderLineStyle
+{
+ /**
+ * The value
+ */
+ private int value;
+
+ /**
+ * The string description
+ */
+ private String string;
+
+ /**
+ * The list of alignments
+ */
+ private static BorderLineStyle[] styles = new BorderLineStyle[0];
+
+
+ /**
+ * Constructor
+ */
+ protected BorderLineStyle(int val, String s)
+ {
+ value = val;
+ string = s;
+
+ BorderLineStyle[] oldstyles = styles;
+ styles = new BorderLineStyle[oldstyles.length + 1];
+ System.arraycopy(oldstyles, 0, styles, 0, oldstyles.length);
+ styles[oldstyles.length] = this;
+ }
+
+ /**
+ * Gets the value for this line style
+ *
+ * @return the value
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Gets the textual description
+ */
+ public String getDescription()
+ {
+ return string;
+ }
+
+ /**
+ * Gets the alignment from the value
+ *
+ * @param val
+ * @return the alignment with that value
+ */
+ public static BorderLineStyle getStyle(int val)
+ {
+ for (int i = 0 ; i < styles.length ; i++)
+ {
+ if (styles[i].getValue() == val)
+ {
+ return styles[i];
+ }
+ }
+
+ return NONE;
+ }
+
+ public final static BorderLineStyle NONE
+ = new BorderLineStyle(0, "none");
+ public final static BorderLineStyle THIN
+ = new BorderLineStyle(1, "thin");
+ public final static BorderLineStyle MEDIUM
+ = new BorderLineStyle(2, "medium");
+ public final static BorderLineStyle DASHED
+ = new BorderLineStyle(3, "dashed");
+ public final static BorderLineStyle DOTTED
+ = new BorderLineStyle(4, "dotted");
+ public final static BorderLineStyle THICK
+ = new BorderLineStyle(5, "thick");
+ public final static BorderLineStyle DOUBLE
+ = new BorderLineStyle(6, "double");
+ public final static BorderLineStyle HAIR
+ = new BorderLineStyle(7, "hair");
+ public final static BorderLineStyle MEDIUM_DASHED
+ = new BorderLineStyle(8, "medium dashed");
+ public final static BorderLineStyle DASH_DOT
+ = new BorderLineStyle(9, "dash dot");
+ public final static BorderLineStyle MEDIUM_DASH_DOT
+ = new BorderLineStyle(0xa, "medium dash dot");
+ public final static BorderLineStyle DASH_DOT_DOT
+ = new BorderLineStyle(0xb, "Dash dot dot");
+ public final static BorderLineStyle MEDIUM_DASH_DOT_DOT
+ = new BorderLineStyle(0xc, "Medium dash dot dot");
+ public final static BorderLineStyle SLANTED_DASH_DOT
+ = new BorderLineStyle(0xd, "Slanted dash dot");
+}
Index: 3rdParty_sources/jexcelapi/jxl/format/CellFormat.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/CellFormat.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/CellFormat.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,143 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.format;
+
+/**
+ * Interface for cell formats
+ */
+public interface CellFormat
+{
+ /**
+ * Gets the format used by this format
+ *
+ * @return the format
+ */
+ public Format getFormat();
+
+ /**
+ * Gets the font information used by this format
+ *
+ * @return the font
+ */
+ public Font getFont();
+
+ /**
+ * Gets whether or not the contents of this cell are wrapped
+ *
+ * @return TRUE if this cell's contents are wrapped, FALSE otherwise
+ */
+ public boolean getWrap();
+
+ /**
+ * Gets the horizontal cell alignment
+ *
+ * @return the alignment
+ */
+ public Alignment getAlignment();
+
+ /**
+ * Gets the vertical cell alignment
+ *
+ * @return the alignment
+ */
+ public VerticalAlignment getVerticalAlignment();
+
+ /**
+ * Gets the orientation
+ *
+ * @return the orientation
+ */
+ public Orientation getOrientation();
+
+ /**
+ * Gets the line style for the given cell border
+ * If a border type of ALL or NONE is specified, then a line style of
+ * NONE is returned
+ *
+ * @param border the cell border we are interested in
+ * @return the line style of the specified border
+ */
+ public BorderLineStyle getBorder(Border border);
+
+ /**
+ * Gets the line style for the given cell border
+ * If a border type of ALL or NONE is specified, then a line style of
+ * NONE is returned
+ *
+ * @param border the cell border we are interested in
+ * @return the line style of the specified border
+ */
+ public BorderLineStyle getBorderLine(Border border);
+
+ /**
+ * Gets the colour for the given cell border
+ * If a border type of ALL or NONE is specified, then a line style of
+ * NONE is returned
+ * If the specified cell does not have an associated line style, then
+ * the colour the line would be is still returned
+ *
+ * @param border the cell border we are interested in
+ * @return the line style of the specified border
+ */
+ public Colour getBorderColour(Border border);
+
+ /**
+ * Determines if this cell format has any borders at all. Used to
+ * set the new borders when merging a group of cells
+ *
+ * @return TRUE if this cell has any borders, FALSE otherwise
+ */
+ public boolean hasBorders();
+
+ /**
+ * Gets the background colour used by this cell
+ *
+ * @return the foreground colour
+ */
+ public Colour getBackgroundColour();
+
+ /**
+ * Gets the pattern used by this cell format
+ *
+ * @return the background pattern
+ */
+ public Pattern getPattern();
+
+ /**
+ * Gets the indentation of the cell text
+ *
+ * @return the indentation
+ */
+ public int getIndentation();
+
+ /**
+ * Gets the shrink to fit flag
+ *
+ * @return TRUE if this format is shrink to fit, FALSE otherise
+ */
+ public boolean isShrinkToFit();
+
+ /**
+ * Accessor for whether a particular cell is locked
+ *
+ * @return TRUE if this cell is locked, FALSE otherwise
+ */
+ public boolean isLocked();
+}
Index: 3rdParty_sources/jexcelapi/jxl/format/Colour.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/Colour.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/Colour.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,256 @@
+/*********************************************************************
+ *
+ * Copyright (C) 2002 Andrew Khan
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ***************************************************************************/
+
+package jxl.format;
+
+/**
+ * Enumeration class which contains the various colours available within
+ * the standard Excel colour palette
+ *
+ */
+public /*final*/ class Colour
+{
+ /**
+ * The internal numerical representation of the colour
+ */
+ private int value;
+
+ /**
+ * The default RGB value
+ */
+ private RGB rgb;
+
+ /**
+ * The display string for the colour. Used when presenting the
+ * format information
+ */
+ private String string;
+
+ /**
+ * The list of internal colours
+ */
+ private static Colour[] colours = new Colour[0];
+
+ /**
+ * Private constructor
+ *
+ * @param val
+ * @param s the display string
+ * @param r the default red value
+ * @param g the default green value
+ * @param b the default blue value
+ */
+ protected Colour(int val, String s, int r, int g, int b)
+ {
+ value = val;
+ string = s;
+ rgb = new RGB(r,g,b);
+
+ Colour[] oldcols = colours;
+ colours = new Colour[oldcols.length + 1];
+ System.arraycopy(oldcols, 0, colours, 0, oldcols.length);
+ colours[oldcols.length] = this;
+ }
+
+ /**
+ * Gets the value of this colour. This is the value that is written to
+ * the generated Excel file
+ *
+ * @return the binary value
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Gets the string description for display purposes
+ *
+ * @return the string description
+ */
+ public String getDescription()
+ {
+ return string;
+ }
+
+ /**
+ * Gets the default red content of this colour. Used when writing the
+ * default colour palette
+ *
+ * @return the red content of this colour
+ * @deprecated use getDefaultRGB instead
+ */
+ public int getDefaultRed()
+ {
+ return rgb.getRed();
+ }
+
+ /**
+ * Gets the default green content of this colour. Used when writing the
+ * default colour palette
+ *
+ * @return the green content of this colour
+ * @deprecated use getDefaultRGB instead
+ */
+ public int getDefaultGreen()
+ {
+ return rgb.getGreen();
+ }
+
+ /**
+ * Gets the default blue content of this colour. Used when writing the
+ * default colour palette
+ *
+ * @return the blue content of this colour
+ * @deprecated use getDefaultRGB instead
+ */
+ public int getDefaultBlue()
+ {
+ return rgb.getBlue();
+ }
+
+ /**
+ * Returns the default RGB of the colour
+ *
+ * @return the default RGB
+ */
+ public RGB getDefaultRGB()
+ {
+ return rgb;
+ }
+
+ /**
+ * Gets the internal colour from the value
+ *
+ * @param val
+ * @return the colour with that value
+ */
+ public static Colour getInternalColour(int val)
+ {
+ for (int i = 0 ; i < colours.length ; i++)
+ {
+ if (colours[i].getValue() == val)
+ {
+ return colours[i];
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ /**
+ * Returns all available colours - used when generating the default palette
+ *
+ * @return all available colours
+ */
+ public static Colour[] getAllColours()
+ {
+ return colours;
+ }
+
+ // Major colours
+ public final static Colour UNKNOWN =
+ new Colour(0x7fee, "unknown", 0, 0, 0);
+ public final static Colour BLACK =
+ new Colour(0x7fff, "black", 0, 0, 0);
+ public final static Colour WHITE =
+ new Colour(0x9, "white", 0xff, 0xff, 0xff);
+ public final static Colour DEFAULT_BACKGROUND1
+ = new Colour(0x0, "default background", 0xff, 0xff, 0xff);
+ public final static Colour DEFAULT_BACKGROUND
+ = new Colour(0xc0, "default background", 0xff, 0xff, 0xff);
+ public final static Colour PALETTE_BLACK =
+ new Colour(0x8, "black", 0x1, 0, 0);
+ // the first item in the colour palette
+
+ // Other colours
+ public final static Colour RED = new Colour(0xa, "red",0xff,0,0);
+ public final static Colour BRIGHT_GREEN = new Colour(0xb, "bright green",0,0xff,0);
+ public final static Colour BLUE = new Colour(0xc, "blue",0,0,0xff); public final static Colour YELLOW = new Colour(0xd, "yellow",0xff,0xff,0);
+ public final static Colour PINK = new Colour(0xe, "pink",0xff,0,0xff);
+ public final static Colour TURQUOISE = new Colour(0xf, "turquoise",0,0xff,0xff);
+ public final static Colour DARK_RED = new Colour(0x10, "dark red",0x80,0,0);
+ public final static Colour GREEN = new Colour(0x11, "green",0,0x80,0);
+ public final static Colour DARK_BLUE = new Colour(0x12, "dark blue",0,0,0x80);
+ public final static Colour DARK_YELLOW = new Colour(0x13, "dark yellow",0x80,0x80,0);
+ public final static Colour VIOLET = new Colour(0x14, "violet",0x80,0x80,0);
+ public final static Colour TEAL = new Colour(0x15, "teal",0,0x80,0x80);
+ public final static Colour GREY_25_PERCENT = new Colour(0x16 ,"grey 25%",0xc0,0xc0,0xc0);
+ public final static Colour GREY_50_PERCENT = new Colour(0x17, "grey 50%",0x80,0x80,0x80);
+ public final static Colour PERIWINKLE = new Colour(0x18, "periwinkle%",0x99, 0x99, 0xff);
+ public final static Colour PLUM2 = new Colour(0x19, "plum",0x99, 0x33, 0x66);
+ public final static Colour IVORY = new Colour(0x1a, "ivory",0xff, 0xff, 0xcc);
+ public final static Colour LIGHT_TURQUOISE2= new Colour(0x1b, "light turquoise",0xcc, 0xff, 0xff);
+ public final static Colour DARK_PURPLE = new Colour(0x1c, "dark purple",0x66, 0x0, 0x66);
+ public final static Colour CORAL = new Colour(0x1d, "coral",0xff, 0x80, 0x80);
+ public final static Colour OCEAN_BLUE = new Colour(0x1e, "ocean blue",0x0, 0x66, 0xcc);
+ public final static Colour ICE_BLUE = new Colour(0x1f, "ice blue",0xcc, 0xcc, 0xff);
+ public final static Colour DARK_BLUE2 = new Colour(0x20, "dark blue",0,0,0x80);
+ public final static Colour PINK2 = new Colour(0x21, "pink",0xff,0,0xff);
+ public final static Colour YELLOW2 = new Colour(0x22, "yellow",0xff,0xff,0x0);
+ public final static Colour TURQOISE2 = new Colour(0x23, "turqoise",0x0,0xff,0xff);
+ public final static Colour VIOLET2 = new Colour(0x24, "violet",0x80,0x0,0x80);
+ public final static Colour DARK_RED2 = new Colour(0x25, "dark red",0x80,0x0,0x0);
+ public final static Colour TEAL2 = new Colour(0x26, "teal",0x0,0x80,0x80);
+ public final static Colour BLUE2 = new Colour(0x27, "blue",0x0,0x0,0xff);
+ public final static Colour SKY_BLUE = new Colour(0x28, "sky blue",0,0xcc,0xff);
+ public final static Colour LIGHT_TURQUOISE
+ = new Colour(0x29, "light turquoise",0xcc,0xff,0xff);
+ public final static Colour LIGHT_GREEN = new Colour(0x2a, "light green",0xcc,0xff,0xcc);
+ public final static Colour VERY_LIGHT_YELLOW
+ = new Colour(0x2b, "very light yellow",0xff,0xff,0x99);
+ public final static Colour PALE_BLUE = new Colour(0x2c, "pale blue",0x99,0xcc,0xff);
+ public final static Colour ROSE = new Colour(0x2d, "rose",0xff,0x99,0xcc);
+ public final static Colour LAVENDER = new Colour(0x2e, "lavender",0xcc,0x99,0xff);
+ public final static Colour TAN = new Colour(0x2f, "tan",0xff,0xcc,0x99);
+ public final static Colour LIGHT_BLUE = new Colour(0x30, "light blue", 0x33, 0x66, 0xff);
+ public final static Colour AQUA = new Colour(0x31, "aqua",0x33,0xcc,0xcc);
+ public final static Colour LIME = new Colour(0x32, "lime",0x99,0xcc,0);
+ public final static Colour GOLD = new Colour(0x33, "gold",0xff,0xcc,0);
+ public final static Colour LIGHT_ORANGE
+ = new Colour(0x34, "light orange",0xff,0x99,0);
+ public final static Colour ORANGE = new Colour(0x35, "orange",0xff,0x66,0);
+ public final static Colour BLUE_GREY = new Colour(0x36, "blue grey",0x66,0x66,0xcc);
+ public final static Colour GREY_40_PERCENT = new Colour(0x37, "grey 40%",0x96,0x96,0x96);
+ public final static Colour DARK_TEAL = new Colour(0x38, "dark teal",0,0x33,0x66);
+ public final static Colour SEA_GREEN = new Colour(0x39, "sea green",0x33,0x99,0x66);
+ public final static Colour DARK_GREEN = new Colour(0x3a, "dark green",0,0x33,0);
+ public final static Colour OLIVE_GREEN = new Colour(0x3b, "olive green",0x33,0x33,0);
+ public final static Colour BROWN = new Colour(0x3c, "brown",0x99,0x33,0);
+ public final static Colour PLUM = new Colour(0x3d, "plum",0x99,0x33,0x66);
+ public final static Colour INDIGO = new Colour(0x3e, "indigo",0x33,0x33,0x99);
+ public final static Colour GREY_80_PERCENT = new Colour(0x3f, "grey 80%",0x33,0x33,0x33);
+ public final static Colour AUTOMATIC = new Colour(0x40, "automatic", 0xff, 0xff, 0xff);
+
+ // Colours added for backwards compatibility
+ public final static Colour GRAY_80 = GREY_80_PERCENT;
+ public final static Colour GRAY_50 = GREY_50_PERCENT;
+ public final static Colour GRAY_25 = GREY_25_PERCENT;
+}
+
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/format/Font.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/Font.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/Font.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,83 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.format;
+
+/**
+ * Interface which exposes the user font display information to the user
+ */
+public interface Font
+{
+ /**
+ * Gets the name of this font
+ *
+ * @return the name of this font
+ */
+ public String getName();
+
+ /**
+ * Gets the point size for this font, if the font hasn't been initialized
+ *
+ * @return the point size
+ */
+ public int getPointSize();
+
+ /**
+ * Gets the bold weight for this font
+ *
+ * @return the bold weight for this font
+ */
+ public int getBoldWeight();
+
+ /**
+ * Returns the italic flag
+ *
+ * @return TRUE if this font is italic, FALSE otherwise
+ */
+ public boolean isItalic();
+
+ /**
+ * Returns the strike-out flag
+ *
+ * @return TRUE if this font is struck-out, FALSE otherwise
+ */
+ public boolean isStruckout();
+
+ /**
+ * Gets the underline style for this font
+ *
+ * @return the underline style
+ */
+ public UnderlineStyle getUnderlineStyle();
+
+ /**
+ * Gets the colour for this font
+ *
+ * @return the colour
+ */
+ public Colour getColour();
+
+ /**
+ * Gets the script style
+ *
+ * @return the script style
+ */
+ public ScriptStyle getScriptStyle();
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/format/Format.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/Format.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/Format.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,41 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.format;
+
+/**
+ * Exposes the cell formatting information
+ */
+public interface Format
+{
+ /**
+ * Accesses the excel format string which is applied to the cell
+ * Note that this is the string that excel uses, and not the java
+ * equivalent
+ *
+ * @return the cell format string
+ */
+ public String getFormatString();
+}
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/format/Orientation.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/Orientation.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/Orientation.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,139 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.format;
+
+/**
+ * Enumeration type which describes the orientation of data within a cell
+ */
+public final class Orientation
+{
+ /**
+ * The internal binary value which gets written to the generated Excel file
+ */
+ private int value;
+
+ /**
+ * The textual description
+ */
+ private String string;
+
+ /**
+ * The list of alignments
+ */
+ private static Orientation[] orientations = new Orientation[0];
+
+ /**
+ * Constructor
+ *
+ * @param val
+ */
+ protected Orientation(int val, String s)
+ {
+ value = val; string = s;
+
+ Orientation[] oldorients = orientations;
+ orientations = new Orientation[oldorients.length + 1];
+ System.arraycopy(oldorients, 0, orientations, 0, oldorients.length);
+ orientations[oldorients.length] = this;
+ }
+
+ /**
+ * Accessor for the binary value
+ *
+ * @return the internal binary value
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Gets the textual description
+ */
+ public String getDescription()
+ {
+ return string;
+ }
+
+ /**
+ * Gets the alignment from the value
+ *
+ * @param val
+ * @return the alignment with that value
+ */
+ public static Orientation getOrientation(int val)
+ {
+ for (int i = 0 ; i < orientations.length ; i++)
+ {
+ if (orientations[i].getValue() == val)
+ {
+ return orientations[i];
+ }
+ }
+
+ return HORIZONTAL;
+ }
+
+
+ /**
+ * Cells with this specified orientation will be horizontal
+ */
+ public static Orientation HORIZONTAL = new Orientation(0, "horizontal");
+ /**
+ * Cells with this specified orientation have their data
+ * presented vertically
+ */
+ public static Orientation VERTICAL = new Orientation(0xff, "vertical");
+ /**
+ * Cells with this specified orientation will have their data
+ * presented with a rotation of 90 degrees upwards
+ */
+ public static Orientation PLUS_90 = new Orientation(90, "up 90");
+ /**
+ * Cells with this specified orientation will have their data
+ * presented with a rotation of 90 degrees downwards
+ */
+ public static Orientation MINUS_90 = new Orientation(180, "down 90");
+ /**
+ * Cells with this specified orientation will have their data
+ * presented with a rotation 45 degrees upwards
+ */
+ public static Orientation PLUS_45 = new Orientation(45, "up 45");
+ /**
+ * Cells with this specified orientation will have their data
+ * presented with a rotation 45 degrees downwards
+ */
+ public static Orientation MINUS_45 = new Orientation(135, "down 45");
+ /**
+ * Cells with this specified orientation will have their text stacked
+ * downwards, but not rotated
+ */
+ public static Orientation STACKED = new Orientation(255, "stacked");
+
+}
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/format/PageOrder.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/PageOrder.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/PageOrder.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,43 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.format;
+
+/**
+ * Enumeration type which describes the page orientation
+ */
+public class PageOrder
+{
+ /**
+ * Constructor
+ */
+ private PageOrder()
+ {
+ }
+
+ /**
+ * Top to Down then Right.
+ */
+ public static PageOrder DOWN_THEN_RIGHT = new PageOrder();
+
+ /**
+ * Left to Right then Down.
+ */
+ public static PageOrder RIGHT_THEN_DOWN = new PageOrder();
+}
Index: 3rdParty_sources/jexcelapi/jxl/format/PageOrientation.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/PageOrientation.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/PageOrientation.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,52 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.format;
+
+/**
+ * Enumeration type which describes the page orientation
+ */
+public final class PageOrientation
+{
+ /**
+ * Constructor
+ */
+ private PageOrientation()
+ {
+ }
+
+
+ /**
+ * Portrait orientation
+ */
+ public static PageOrientation PORTRAIT = new PageOrientation();
+ /**
+ * Landscape orientation
+ */
+ public static PageOrientation LANDSCAPE = new PageOrientation();
+}
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/format/PaperSize.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/PaperSize.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/PaperSize.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,334 @@
+/*********************************************************************
+ *
+ * Copyright (C) 2002 Andrew Khan
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ***************************************************************************/
+
+package jxl.format;
+
+/**
+ * Enumeration type which contains the available excel paper sizes and their
+ * codes
+ */
+public final class PaperSize
+{
+ private static final int LAST_PAPER_SIZE = 89;
+ /**
+ * The excel encoding
+ */
+ private int val;
+
+ /**
+ * The paper sizes
+ */
+ private static PaperSize[] paperSizes = new PaperSize[LAST_PAPER_SIZE + 1];
+
+ /**
+ * Constructor
+ */
+ private PaperSize(int v, boolean growArray)
+ {
+ val = v;
+
+ if (v >= paperSizes.length && growArray)
+ {
+ // Grow the array and add this to it
+ PaperSize[] newarray = new PaperSize[v + 1];
+ System.arraycopy(paperSizes, 0, newarray, 0, paperSizes.length);
+ paperSizes = newarray;
+ }
+ if (v < paperSizes.length)
+ {
+ paperSizes[v] = this;
+ }
+ }
+
+ /**
+ * Constructor
+ */
+ private PaperSize(int v)
+ {
+ this(v, true);
+ }
+
+ /**
+ * Accessor for the internal binary value association with this paper size
+ *
+ * @return the internal value
+ */
+ public int getValue()
+ {
+ return val;
+ }
+
+ /**
+ * Gets the paper size for a specific value
+ *
+ * @param val the value
+ * @return the paper size
+ */
+ public static PaperSize getPaperSize(int val)
+ {
+ PaperSize p = val > paperSizes.length - 1 ? null : paperSizes[val];
+ return p == null ? new PaperSize(val, false) : p;
+ }
+
+ /** US Letter 8.5 x 11" */
+ public static final PaperSize UNDEFINED = new PaperSize(0);
+
+ /** US Letter 8.5 x 11" */
+ public static final PaperSize LETTER = new PaperSize(1);
+
+ /** Letter small 8.5" � 11" */
+ public static final PaperSize LETTER_SMALL = new PaperSize(2);
+
+ /** Tabloid 11" x 17" */
+ public static final PaperSize TABLOID = new PaperSize(3);
+
+ /** Leger 17" x 11" */
+ public static final PaperSize LEDGER = new PaperSize(4);
+
+ /** US Legal 8.5" x 14" */
+ public static final PaperSize LEGAL = new PaperSize(5);
+
+ /** Statement 5.5" x 8.5" */
+ public static final PaperSize STATEMENT = new PaperSize(6);
+
+ /** Executive 7.25" x 10.5" */
+ public static final PaperSize EXECUTIVE = new PaperSize(7);
+
+ /** A3 297mm x 420mm */
+ public static final PaperSize A3 = new PaperSize(8);
+
+ /** A4 210mm x 297mm */
+ public static final PaperSize A4 = new PaperSize(9);
+
+ /** A4 Small 210mm x 297 mm */
+ public static final PaperSize A4_SMALL = new PaperSize(10);
+
+ /** A5 148mm x 210mm */
+ public static final PaperSize A5 = new PaperSize(11);
+
+ /** B4 (JIS) 257mm x 364mm */
+ public static final PaperSize B4 = new PaperSize(12);
+
+ /** B5 (JIS) 182mm x 257mm */
+ public static final PaperSize B5 = new PaperSize(13);
+
+ /** Folio 8.5" x 13" */
+ public static final PaperSize FOLIO = new PaperSize(14);
+
+ /** Quarto 215mm x 275mm */
+ public static final PaperSize QUARTO = new PaperSize(15);
+
+ /** 10" x 14" */
+ public static final PaperSize SIZE_10x14 = new PaperSize(16);
+
+ /** 11" x 17" */
+ public static final PaperSize SIZE_10x17 = new PaperSize(17);
+
+ /** NOTE 8.5" x 11" */
+ public static final PaperSize NOTE = new PaperSize(18);
+
+ /** Envelope #9 3 7/8" x 8 7/8" */
+ public static final PaperSize ENVELOPE_9 = new PaperSize(19);
+
+ /** Envelope #10 4 1/8" x 9.5" */
+ public static final PaperSize ENVELOPE_10 = new PaperSize(20);
+
+ /** Envelope #11 4.5" x 10 3/8" */
+ public static final PaperSize ENVELOPE_11 = new PaperSize(21);
+
+ /** Envelope #12 4.75" x 11" */
+ public static final PaperSize ENVELOPE_12 = new PaperSize(22);
+
+ /** Envelope #14 5" x 11.5" */
+ public static final PaperSize ENVELOPE_14 = new PaperSize(23);
+
+ /** C 17" x 22" */
+ public static final PaperSize C = new PaperSize(24);
+
+ /** D 22" x 34" */
+ public static final PaperSize D = new PaperSize(25);
+
+ /** E 34" x 44" */
+ public static final PaperSize E = new PaperSize(26);
+
+ /** Envelope DL 110mm � 220mm */
+ public static final PaperSize ENVELOPE_DL = new PaperSize(27);
+
+ /** Envelope C5 162mm � 229mm */
+ public static final PaperSize ENVELOPE_C5 = new PaperSize(28);
+
+ /** Envelope C3 324mm � 458mm */
+ public static final PaperSize ENVELOPE_C3 = new PaperSize(29);
+
+ /** Envelope C4 229mm � 324mm */
+ public static final PaperSize ENVELOPE_C4 = new PaperSize(30);
+
+ /** Envelope C6 114mm � 162mm */
+ public static final PaperSize ENVELOPE_C6 = new PaperSize(31);
+
+ /** Envelope C6/C5 114mm � 229mm */
+ public static final PaperSize ENVELOPE_C6_C5 = new PaperSize(32);
+
+ /** B4 (ISO) 250mm � 353mm */
+ public static final PaperSize B4_ISO = new PaperSize(33);
+
+ /** B5 (ISO) 176mm � 250mm */
+ public static final PaperSize B5_ISO = new PaperSize(34);
+
+ /** B6 (ISO) 125mm � 176mm */
+ public static final PaperSize B6_ISO = new PaperSize(35);
+
+ /** Envelope Italy 110mm � 230mm */
+ public static final PaperSize ENVELOPE_ITALY = new PaperSize(36);
+
+ /** Envelope Monarch 3 7/8" � 7.5" */
+ public static final PaperSize ENVELOPE_MONARCH = new PaperSize(37);
+
+ /** 6.75 Envelope 3 5/8" � 6.5" */
+ public static final PaperSize ENVELOPE_6_75 = new PaperSize(38);
+
+ /** US Standard Fanfold 14 7/8" � 11" */
+ public static final PaperSize US_FANFOLD = new PaperSize(39);
+
+ /** German Std. Fanfold 8.5" � 12" */
+ public static final PaperSize GERMAN_FANFOLD = new PaperSize(40);
+
+ /** German Legal Fanfold 8.5" � 13" */
+ public static final PaperSize GERMAN_LEGAL_FANFOLD = new PaperSize(41);
+
+ /** B4 (ISO) 250mm � 353mm */
+ public static final PaperSize B4_ISO_2 = new PaperSize(42);
+
+ /** Japanese Postcard 100mm � 148mm */
+ public static final PaperSize JAPANESE_POSTCARD = new PaperSize(43);
+
+ /** 9�11 9" � 11" */
+ public static final PaperSize SIZE_9x11 = new PaperSize(44);
+
+ /** 10�11 10" � 11" */
+ public static final PaperSize SIZE_10x11 = new PaperSize(45);
+
+ /** 15�11 15" � 11" */
+ public static final PaperSize SIZE_15x11 = new PaperSize(46);
+
+ /** Envelope Invite 220mm � 220mm */
+ public static final PaperSize ENVELOPE_INVITE = new PaperSize(47);
+
+ /* 48 & 49 Undefined */
+
+ /** Letter Extra 9.5" � 12" */
+ public static final PaperSize LETTER_EXTRA = new PaperSize(50);
+
+ /** Legal Extra 9.5" � 15" */
+ public static final PaperSize LEGAL_EXTRA = new PaperSize(51);
+
+ /** Tabloid Extra 11 11/16" � 18" */
+ public static final PaperSize TABLOID_EXTRA = new PaperSize(52);
+
+ /** A4 Extra 235mm � 322mm */
+ public static final PaperSize A4_EXTRA = new PaperSize(53);
+
+ /** Letter Transverse 8.5" � 11" */
+ public static final PaperSize LETTER_TRANSVERSE = new PaperSize(54);
+
+ /** A4 Transverse 210mm � 297mm */
+ public static final PaperSize A4_TRANSVERSE = new PaperSize(55);
+
+ /** Letter Extra Transv. 9.5" � 12" */
+ public static final PaperSize LETTER_EXTRA_TRANSVERSE = new PaperSize(56);
+
+ /** Super A/A4 227mm � 356mm */
+ public static final PaperSize SUPER_A_A4 = new PaperSize(57);
+
+ /** Super B/A3 305mm � 487mm */
+ public static final PaperSize SUPER_B_A3 = new PaperSize(58);
+
+ /** Letter Plus 8.5" x 12 11/16" */
+ public static final PaperSize LETTER_PLUS = new PaperSize(59);
+
+ /** A4 Plus 210mm � 330mm */
+ public static final PaperSize A4_PLUS = new PaperSize(60);
+
+ /** A5 Transverse 148mm � 210mm */
+ public static final PaperSize A5_TRANSVERSE = new PaperSize(61);
+
+ /** B5 (JIS) Transverse 182mm � 257mm */
+ public static final PaperSize B5_TRANSVERSE = new PaperSize(62);
+
+ /** A3 Extra 322mm � 445mm */
+ public static final PaperSize A3_EXTRA = new PaperSize(63);
+
+ /** A5 Extra 174mm � 235mm */
+ public static final PaperSize A5_EXTRA = new PaperSize(64);
+
+ /** B5 (ISO) Extra 201mm � 276mm */
+ public static final PaperSize B5_EXTRA = new PaperSize(65);
+
+ /** A2 420mm � 594mm */
+ public static final PaperSize A2 = new PaperSize(66);
+
+ /** A3 Transverse 297mm � 420mm */
+ public static final PaperSize A3_TRANSVERSE = new PaperSize(67);
+
+ /** A3 Extra Transverse 322mm � 445mm */
+ public static final PaperSize A3_EXTRA_TRANSVERSE = new PaperSize(68);
+
+ /** Dbl. Japanese Postcard 200mm � 148mm */
+ public static final PaperSize DOUBLE_JAPANESE_POSTCARD = new PaperSize(69);
+
+ /** A6 105mm � 148mm */
+ public static final PaperSize A6 = new PaperSize(70);
+
+ /* 71 - 74 undefined */
+
+ /** Letter Rotated 11" � 8.5" */
+ public static final PaperSize LETTER_ROTATED = new PaperSize(75);
+
+ /** A3 Rotated 420mm � 297mm */
+ public static final PaperSize A3_ROTATED = new PaperSize(76);
+
+ /** A4 Rotated 297mm � 210mm */
+ public static final PaperSize A4_ROTATED = new PaperSize(77);
+
+ /** A5 Rotated 210mm � 148mm */
+ public static final PaperSize A5_ROTATED = new PaperSize(78);
+
+ /** B4 (JIS) Rotated 364mm � 257mm */
+ public static final PaperSize B4_ROTATED = new PaperSize(79);
+
+ /** B5 (JIS) Rotated 257mm � 182mm */
+ public static final PaperSize B5_ROTATED = new PaperSize(80);
+
+ /** Japanese Postcard Rot. 148mm � 100mm */
+ public static final PaperSize JAPANESE_POSTCARD_ROTATED = new PaperSize(81);
+
+ /** Dbl. Jap. Postcard Rot. 148mm � 200mm */
+ public static final PaperSize DOUBLE_JAPANESE_POSTCARD_ROTATED = new PaperSize(82);
+
+ /** A6 Rotated 148mm � 105mm */
+ public static final PaperSize A6_ROTATED = new PaperSize(83);
+
+ /* 84 - 87 undefined */
+
+ /** B6 (JIS) 128mm � 182mm */
+ public static final PaperSize B6 = new PaperSize(88);
+
+ /** B6 (JIS) Rotated 182mm � 128mm */
+ public static final PaperSize B6_ROTATED = new PaperSize(89);
+}
Index: 3rdParty_sources/jexcelapi/jxl/format/Pattern.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/Pattern.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/Pattern.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,133 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.format;
+
+
+/**
+ * Enumeration class which contains the various patterns available within
+ * the standard Excel pattern palette
+ */
+public /*final*/ class Pattern
+{
+ /**
+ * The internal numerical representation of the colour
+ */
+ private int value;
+
+ /**
+ * The textual description
+ */
+ private String string;
+
+ /**
+ * The list of patterns
+ */
+ private static Pattern[] patterns = new Pattern[0];
+
+ /**
+ * Private constructor
+ *
+ * @param val
+ * @param s
+ */
+ protected Pattern(int val, String s)
+ {
+ value = val;
+ string = s;
+
+ Pattern[] oldcols = patterns;
+ patterns = new Pattern[oldcols.length + 1];
+ System.arraycopy(oldcols, 0, patterns, 0, oldcols.length);
+ patterns[oldcols.length] = this;
+ }
+
+ /**
+ * Gets the value of this pattern. This is the value that is written to
+ * the generated Excel file
+ *
+ * @return the binary value
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Gets the textual description
+ *
+ * @return the string
+ */
+ public String getDescription()
+ {
+ return string;
+ }
+
+ /**
+ * Gets the pattern from the value
+ *
+ * @param val
+ * @return the pattern with that value
+ */
+ public static Pattern getPattern(int val)
+ {
+ for (int i = 0 ; i < patterns.length ; i++)
+ {
+ if (patterns[i].getValue() == val)
+ {
+ return patterns[i];
+ }
+ }
+
+ return NONE;
+ }
+
+ public final static Pattern NONE = new Pattern(0x0, "None");
+ public final static Pattern SOLID = new Pattern(0x1, "Solid");
+
+ public final static Pattern GRAY_50 = new Pattern(0x2, "Gray 50%");
+ public final static Pattern GRAY_75 = new Pattern(0x3, "Gray 75%");
+ public final static Pattern GRAY_25 = new Pattern(0x4, "Gray 25%");
+
+ public final static Pattern PATTERN1 = new Pattern(0x5, "Pattern 1");
+ public final static Pattern PATTERN2 = new Pattern(0x6, "Pattern 2");
+ public final static Pattern PATTERN3 = new Pattern(0x7, "Pattern 3");
+ public final static Pattern PATTERN4 = new Pattern(0x8, "Pattern 4");
+ public final static Pattern PATTERN5 = new Pattern(0x9, "Pattern 5");
+ public final static Pattern PATTERN6 = new Pattern(0xa, "Pattern 6");
+ public final static Pattern PATTERN7 = new Pattern(0xb, "Pattern 7");
+ public final static Pattern PATTERN8 = new Pattern(0xc, "Pattern 8");
+ public final static Pattern PATTERN9 = new Pattern(0xd, "Pattern 9");
+ public final static Pattern PATTERN10 = new Pattern(0xe, "Pattern 10");
+ public final static Pattern PATTERN11 = new Pattern(0xf, "Pattern 11");
+ public final static Pattern PATTERN12 = new Pattern(0x10, "Pattern 12");
+ public final static Pattern PATTERN13 = new Pattern(0x11, "Pattern 13");
+ public final static Pattern PATTERN14 = new Pattern(0x12, "Pattern 14");
+}
+
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/format/RGB.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/RGB.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/RGB.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,87 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+
+package jxl.format;
+
+/**
+ * A structure which contains the RGB values for a particular colour
+ */
+public final class RGB
+{
+ /**
+ * The red component of this colour
+ */
+ private int red;
+
+ /**
+ * The green component of this colour
+ */
+ private int green;
+
+ /**
+ * The blue component of this colour
+ */
+ private int blue;
+
+ /**
+ * Constructor
+ *
+ * @param r the red component
+ * @param g the green component
+ * @param b the blue component
+ */
+ public RGB(int r, int g, int b)
+ {
+ red = r;
+ green = g;
+ blue = b;
+ }
+
+ /**
+ * Accessor for the red component
+ *
+ * @return the red component of the colour, between 0 and 255
+ */
+ public int getRed()
+ {
+ return red;
+ }
+
+ /**
+ * Accessor for the green component
+ *
+ * @return the green component of the colour, between 0 and 255
+ */
+ public int getGreen()
+ {
+ return green;
+ }
+
+ /**
+ * Accessor for the blue component
+ *
+ * @return the blue component of the colour, between 0 and 255
+ */
+ public int getBlue()
+ {
+ return blue;
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/format/ScriptStyle.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/ScriptStyle.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/ScriptStyle.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,120 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.format;
+
+/**
+ * Enumeration class which contains the various script styles available
+ * within the standard Excel ScriptStyle palette
+ *
+ */
+public final class ScriptStyle
+{
+ /**
+ * The internal numerical representation of the ScriptStyle
+ */
+ private int value;
+
+ /**
+ * The display string for the script style. Used when presenting the
+ * format information
+ */
+ private String string;
+
+ /**
+ * The list of ScriptStyles
+ */
+ private static ScriptStyle[] styles = new ScriptStyle[0];
+
+
+ /**
+ * Private constructor
+ *
+ * @param val
+ * @param s the display string
+ */
+ protected ScriptStyle(int val, String s)
+ {
+ value = val;
+ string = s;
+
+ ScriptStyle[] oldstyles = styles;
+ styles = new ScriptStyle[oldstyles.length + 1];
+ System.arraycopy(oldstyles, 0, styles, 0, oldstyles.length);
+ styles[oldstyles.length] = this;
+ }
+
+ /**
+ * Gets the value of this style. This is the value that is written to
+ * the generated Excel file
+ *
+ * @return the binary value
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Gets the string description for display purposes
+ *
+ * @return the string description
+ */
+ public String getDescription()
+ {
+ return string;
+ }
+
+ /**
+ * Gets the ScriptStyle from the value
+ *
+ * @param val
+ * @return the ScriptStyle with that value
+ */
+ public static ScriptStyle getStyle(int val)
+ {
+ for (int i = 0 ; i < styles.length ; i++)
+ {
+ if (styles[i].getValue() == val)
+ {
+ return styles[i];
+ }
+ }
+
+ return NORMAL_SCRIPT;
+ }
+
+ // The script styles
+ public static final ScriptStyle NORMAL_SCRIPT = new ScriptStyle(0, "normal");
+ public static final ScriptStyle SUPERSCRIPT = new ScriptStyle(1, "super");
+ public static final ScriptStyle SUBSCRIPT = new ScriptStyle(2, "sub");
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/format/UnderlineStyle.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/UnderlineStyle.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/UnderlineStyle.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,128 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.format;
+
+/**
+ * Enumeration class which contains the various underline styles available
+ * within the standard Excel UnderlineStyle palette
+ *
+ */
+public final class UnderlineStyle
+{
+ /**
+ * The internal numerical representation of the UnderlineStyle
+ */
+ private int value;
+
+ /**
+ * The display string for the underline style. Used when presenting the
+ * format information
+ */
+ private String string;
+
+ /**
+ * The list of UnderlineStyles
+ */
+ private static UnderlineStyle[] styles = new UnderlineStyle[0];
+
+ /**
+ * Private constructor
+ *
+ * @param val
+ * @param s the display string
+ */
+ protected UnderlineStyle(int val, String s)
+ {
+ value = val;
+ string = s;
+
+ UnderlineStyle[] oldstyles = styles;
+ styles = new UnderlineStyle[oldstyles.length + 1];
+ System.arraycopy(oldstyles, 0, styles, 0, oldstyles.length);
+ styles[oldstyles.length] = this;
+ }
+
+ /**
+ * Gets the value of this style. This is the value that is written to
+ * the generated Excel file
+ *
+ * @return the binary value
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Gets the string description for display purposes
+ *
+ * @return the string description
+ */
+ public String getDescription()
+ {
+ return string;
+ }
+
+ /**
+ * Gets the UnderlineStyle from the value
+ *
+ * @param val
+ * @return the UnderlineStyle with that value
+ */
+ public static UnderlineStyle getStyle(int val)
+ {
+ for (int i = 0 ; i < styles.length ; i++)
+ {
+ if (styles[i].getValue() == val)
+ {
+ return styles[i];
+ }
+ }
+
+ return NO_UNDERLINE;
+ }
+
+ // The underline styles
+ public static final UnderlineStyle NO_UNDERLINE =
+ new UnderlineStyle(0, "none");
+
+ public static final UnderlineStyle SINGLE =
+ new UnderlineStyle(1, "single");
+
+ public static final UnderlineStyle DOUBLE =
+ new UnderlineStyle(2, "double");
+
+ public static final UnderlineStyle SINGLE_ACCOUNTING =
+ new UnderlineStyle(0x21, "single accounting");
+
+ public static final UnderlineStyle DOUBLE_ACCOUNTING =
+ new UnderlineStyle(0x22, "double accounting");
+}
+
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/format/VerticalAlignment.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/format/VerticalAlignment.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/format/VerticalAlignment.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,117 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.format;
+
+/**
+ * Enumeration type which describes the vertical alignment of data within a cell
+ */
+public /*final*/ class VerticalAlignment
+{
+ /**
+ * The internal binary value which gets written to the generated Excel file
+ */
+ private int value;
+
+ /**
+ * The textual description
+ */
+ private String string;
+
+ /**
+ * The list of alignments
+ */
+ private static VerticalAlignment[] alignments = new VerticalAlignment[0];
+
+ /**
+ * Constructor
+ *
+ * @param val
+ */
+ protected VerticalAlignment(int val, String s)
+ {
+ value = val;
+ string = s;
+
+ VerticalAlignment[] oldaligns = alignments;
+ alignments = new VerticalAlignment[oldaligns.length + 1];
+ System.arraycopy(oldaligns, 0, alignments, 0, oldaligns.length);
+ alignments[oldaligns.length] = this;
+ }
+
+ /**
+ * Accessor for the binary value
+ *
+ * @return the internal binary value
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Gets the textual description
+ */
+ public String getDescription()
+ {
+ return string;
+ }
+
+ /**
+ * Gets the alignment from the value
+ *
+ * @param val
+ * @return the alignment with that value
+ */
+ public static VerticalAlignment getAlignment(int val)
+ {
+ for (int i = 0 ; i < alignments.length ; i++)
+ {
+ if (alignments[i].getValue() == val)
+ {
+ return alignments[i];
+ }
+ }
+
+ return BOTTOM;
+ }
+
+
+ /**
+ * Cells with this specified vertical alignment will have their data
+ * aligned at the top
+ */
+ public static VerticalAlignment TOP = new VerticalAlignment(0, "top");
+ /**
+ * Cells with this specified vertical alignment will have their data
+ * aligned centrally
+ */
+ public static VerticalAlignment CENTRE = new VerticalAlignment(1, "centre");
+ /**
+ * Cells with this specified vertical alignment will have their data
+ * aligned at the bottom
+ */
+ public static VerticalAlignment BOTTOM = new VerticalAlignment(2, "bottom");
+ /**
+ * Cells with this specified vertical alignment will have their data
+ * justified
+ */
+ public static VerticalAlignment JUSTIFY = new VerticalAlignment(3, "Justify");
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/BOFRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/BOFRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/BOFRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,170 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * A Beginning Of File record, found at the commencement of all substreams
+ * within a biff8 file
+ */
+public class BOFRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(BOFRecord.class);
+
+ /**
+ * The code used for biff8 files
+ */
+ private static final int Biff8 = 0x600;
+ /**
+ * The code used for biff8 files
+ */
+ private static final int Biff7 = 0x500;
+ /**
+ * The code used for workbook globals
+ */
+ private static final int WorkbookGlobals = 0x5;
+ /**
+ * The code used for worksheets
+ */
+ private static final int Worksheet = 0x10;
+ /**
+ * The code used for charts
+ */
+ private static final int Chart = 0x20;
+ /**
+ * The code used for macro sheets
+ */
+ private static final int MacroSheet = 0x40;
+
+ /**
+ * The biff version of this substream
+ */
+ private int version;
+ /**
+ * The type of this substream
+ */
+ private int substreamType;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ */
+ BOFRecord(Record t)
+ {
+ super(t);
+ byte[] data = getRecord().getData();
+ version = IntegerHelper.getInt(data[0], data[1]);
+ substreamType = IntegerHelper.getInt(data[2], data[3]);
+ }
+
+ /**
+ * Interrogates this object to see if it is a biff8 substream
+ *
+ * @return TRUE if this substream is biff8, false otherwise
+ */
+ public boolean isBiff8()
+ {
+ return version == Biff8;
+ }
+
+ /**
+ * Interrogates this object to see if it is a biff7 substream
+ *
+ * @return TRUE if this substream is biff7, false otherwise
+ */
+ public boolean isBiff7()
+ {
+ return version == Biff7;
+ }
+
+
+ /**
+ * Interrogates this substream to see if it represents the commencement of
+ * the workbook globals substream
+ *
+ * @return TRUE if this is the commencement of a workbook globals substream,
+ * FALSE otherwise
+ */
+ boolean isWorkbookGlobals()
+ {
+ return substreamType == WorkbookGlobals;
+ }
+
+ /**
+ * Interrogates the substream to see if it is the commencement of a worksheet
+ *
+ * @return TRUE if this substream is the beginning of a worksheet, FALSE
+ * otherwise
+ */
+ public boolean isWorksheet()
+ {
+ return substreamType == Worksheet;
+ }
+
+ /**
+ * Interrogates the substream to see if it is the commencement of a worksheet
+ *
+ * @return TRUE if this substream is the beginning of a worksheet, FALSE
+ * otherwise
+ */
+ public boolean isMacroSheet()
+ {
+ return substreamType == MacroSheet;
+ }
+
+ /**
+ * Interrogates the substream to see if it is a chart
+ *
+ * @return TRUE if this substream is the beginning of a worksheet, FALSE
+ * otherwise
+ */
+ public boolean isChart()
+ {
+ return substreamType == Chart;
+ }
+
+ /**
+ * Gets the length of the data portion of this record
+ * Used to adjust when reading sheets which contain just a chart
+ * @return the length of the data portion of this record
+ */
+ int getLength()
+ {
+ return getRecord().getLength();
+ }
+
+}
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/BaseSharedFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/BaseSharedFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/BaseSharedFormulaRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,174 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.formula.ExternalSheet;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+
+/**
+ * A base class for shared formula records
+ */
+public abstract class BaseSharedFormulaRecord extends CellValue
+ implements FormulaData
+{
+ /**
+ * The formula as an excel string
+ */
+ private String formulaString;
+
+ /**
+ * The position of the next record in the file. Used when looking for
+ * for subsequent records eg. a string value
+ */
+ private int filePos;
+
+ /**
+ * The array of parsed tokens
+ */
+ private byte[] tokens;
+
+ /**
+ * The external sheet
+ */
+ private ExternalSheet externalSheet;
+
+ /**
+ * The name table
+ */
+ private WorkbookMethods nameTable;
+
+ /**
+ * Constructs this number
+ *
+ * @param t the record
+ * @param fr the formatting records
+ * @param es the external sheet
+ * @param nt the name table
+ * @param si the sheet
+ * @param pos the position of the next record in the file
+ */
+ public BaseSharedFormulaRecord(Record t,
+ FormattingRecords fr,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ SheetImpl si,
+ int pos)
+ {
+ super(t, fr, si);
+ externalSheet = es;
+ nameTable = nt;
+ filePos = pos;
+ }
+
+ /**
+ * Gets the formula as an excel string
+ *
+ * @return the formula as an excel string
+ * @exception FormulaException
+ */
+ public String getFormula() throws FormulaException
+ {
+ if (formulaString == null)
+ {
+ FormulaParser fp = new FormulaParser
+ (tokens, this, externalSheet, nameTable,
+ getSheet().getWorkbook().getSettings());
+ fp.parse();
+ formulaString = fp.getFormula();
+ }
+
+ return formulaString;
+ }
+
+ /**
+ * Called by the shared formula record to set the tokens for
+ * this formula
+ *
+ * @param t the tokens
+ */
+ void setTokens(byte[] t)
+ {
+ tokens = t;
+ }
+
+ /**
+ * Accessor for the tokens which make up this formula
+ *
+ * @return the tokens
+ */
+ protected final byte[] getTokens()
+ {
+ return tokens;
+ }
+
+ /**
+ * Access for the external sheet
+ *
+ * @return the external sheet
+ */
+ protected final ExternalSheet getExternalSheet()
+ {
+ return externalSheet;
+ }
+
+ /**
+ * Access for the name table
+ *
+ * @return the name table
+ */
+ protected final WorkbookMethods getNameTable()
+ {
+ return nameTable;
+ }
+
+ /**
+ * In case the shared formula is not added for any reason, we need
+ * to expose the raw record data , in order to try again
+ *
+ * @return the record data from the base class
+ */
+ public Record getRecord()
+ {
+ return super.getRecord();
+ }
+
+ /**
+ * Accessor for the position of the next record
+ *
+ * @return the position of the next record
+ */
+ final int getFilePos()
+ {
+ return filePos;
+ }
+}
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/BiffException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/BiffException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/BiffException.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,99 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.JXLException;
+
+/**
+ * Exception thrown when reading a biff file
+ */
+public class BiffException extends JXLException
+{
+ /**
+ * Inner class containing the various error messages
+ */
+ private static class BiffMessage
+ {
+ /**
+ * The formatted message
+ */
+ public String message;
+ /**
+ * Constructs this exception with the specified message
+ *
+ * @param m the messageA
+ */
+ BiffMessage(String m)
+ {
+ message = m;
+ }
+ }
+
+ /**
+ */
+ static final BiffMessage unrecognizedBiffVersion =
+ new BiffMessage("Unrecognized biff version");
+
+ /**
+ */
+ static final BiffMessage expectedGlobals =
+ new BiffMessage("Expected globals");
+
+ /**
+ */
+ static final BiffMessage excelFileTooBig =
+ new BiffMessage("Warning: not all of the excel file could be read");
+
+ /**
+ */
+ static final BiffMessage excelFileNotFound =
+ new BiffMessage("The input file was not found");
+
+ /**
+ */
+ static final BiffMessage unrecognizedOLEFile =
+ new BiffMessage("Unable to recognize OLE stream");
+
+ /**
+ */
+ static final BiffMessage streamNotFound =
+ new BiffMessage("Compound file does not contain the specified stream");
+
+ /**
+ */
+ static final BiffMessage passwordProtected =
+ new BiffMessage("The workbook is password protected");
+
+ /**
+ */
+ static final BiffMessage corruptFileFormat =
+ new BiffMessage("The file format is corrupt");
+
+
+ /**
+ * Constructs this exception with the specified message
+ *
+ * @param m the message
+ */
+ public BiffException(BiffMessage m)
+ {
+ super(m.message);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/BiffRecordReader.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/BiffRecordReader.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/BiffRecordReader.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,79 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+/**
+ * Serves up Record objects from a biff file. This object is used by the
+ * demo programs BiffDump and ... only and has no influence whatsoever on
+ * the JExcelApi reading and writing of excel sheets
+ */
+public class BiffRecordReader
+{
+ /**
+ * The biff file
+ */
+ private File file;
+
+ /**
+ * The current record retrieved
+ */
+ private Record record;
+
+ /**
+ * Constructor
+ *
+ * @param f the biff file
+ */
+ public BiffRecordReader(File f)
+ {
+ file = f;
+ }
+
+ /**
+ * Sees if there are any more records to read
+ *
+ * @return TRUE if there are more records, FALSE otherwise
+ */
+ public boolean hasNext()
+ {
+ return file.hasNext();
+ }
+
+ /**
+ * Gets the next record
+ *
+ * @return the next record
+ */
+ public Record next()
+ {
+ record = file.next();
+ return record;
+ }
+
+ /**
+ * Gets the position of the current record in the biff file
+ *
+ * @return the position
+ */
+ public int getPos()
+ {
+ return file.getPos() - record.getLength() - 4;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/BlankCell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/BlankCell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/BlankCell.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,65 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.CellType;
+import jxl.biff.FormattingRecords;
+
+/**
+ * A blank cell. Despite the fact that this cell has no contents, it
+ * has formatting information applied to it
+ */
+public class BlankCell extends CellValue
+{
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param fr the available formats
+ * @param si the sheet
+ */
+ BlankCell(Record t, FormattingRecords fr, SheetImpl si)
+ {
+ super(t, fr, si);
+ }
+
+ /**
+ * Returns the contents of this cell as an empty string
+ *
+ * @return the value formatted into a string
+ */
+ public String getContents()
+ {
+ return "";
+ }
+
+ /**
+ * Accessor for the cell type
+ *
+ * @return the cell type
+ */
+ public CellType getType()
+ {
+ return CellType.EMPTY;
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/BooleanFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/BooleanFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/BooleanFormulaRecord.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,167 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Assert;
+
+import jxl.BooleanCell;
+import jxl.BooleanFormulaCell;
+import jxl.CellType;
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.formula.ExternalSheet;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+
+/**
+ * A boolean formula's last calculated value
+ */
+class BooleanFormulaRecord extends CellValue
+ implements BooleanCell, FormulaData, BooleanFormulaCell
+{
+ /**
+ * The boolean value of this cell. If this cell represents an error,
+ * this will be false
+ */
+ private boolean value;
+
+ /**
+ * A handle to the class needed to access external sheets
+ */
+ private ExternalSheet externalSheet;
+
+ /**
+ * A handle to the name table
+ */
+ private WorkbookMethods nameTable;
+
+ /**
+ * The formula as an excel string
+ */
+ private String formulaString;
+
+ /**
+ * The raw data
+ */
+ private byte[] data;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param fr the formatting records
+ * @param si the sheet
+ * @param es the sheet
+ * @param nt the name table
+ */
+ public BooleanFormulaRecord(Record t, FormattingRecords fr,
+ ExternalSheet es, WorkbookMethods nt,
+ SheetImpl si)
+ {
+ super(t, fr, si);
+ externalSheet = es;
+ nameTable = nt;
+ value = false;
+
+ data = getRecord().getData();
+
+ Assert.verify(data[6] != 2);
+
+ value = data[8] == 1 ? true : false;
+ }
+
+ /**
+ * Interface method which Gets the boolean value stored in this cell. If
+ * this cell contains an error, then returns FALSE. Always query this cell
+ * type using the accessor method isError() prior to calling this method
+ *
+ * @return TRUE if this cell contains TRUE, FALSE if it contains FALSE or
+ * an error code
+ */
+ public boolean getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the numerical value as a string
+ *
+ * @return The numerical value of the formula as a string
+ */
+ public String getContents()
+ {
+ // return Boolean.toString(value) - only available in 1.4 or later
+ return (new Boolean(value)).toString();
+ }
+
+ /**
+ * Returns the cell type
+ *
+ * @return The cell type
+ */
+ public CellType getType()
+ {
+ return CellType.BOOLEAN_FORMULA;
+ }
+
+ /**
+ * Gets the raw bytes for the formula. This will include the
+ * parsed tokens array
+ *
+ * @return the raw record data
+ */
+ public byte[] getFormulaData() throws FormulaException
+ {
+ if (!getSheet().getWorkbookBof().isBiff8())
+ {
+ throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
+ }
+
+ // Lop off the standard information
+ byte[] d = new byte[data.length - 6];
+ System.arraycopy(data, 6, d, 0, data.length - 6);
+
+ return d;
+ }
+
+ /**
+ * Gets the formula as an excel string
+ *
+ * @return the formula as an excel string
+ * @exception FormulaException
+ */
+ public String getFormula() throws FormulaException
+ {
+ if (formulaString == null)
+ {
+ byte[] tokens = new byte[data.length - 22];
+ System.arraycopy(data, 22, tokens, 0, tokens.length);
+ FormulaParser fp = new FormulaParser
+ (tokens, this, externalSheet, nameTable,
+ getSheet().getWorkbook().getSettings());
+ fp.parse();
+ formulaString = fp.getFormula();
+ }
+
+ return formulaString;
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/BooleanRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/BooleanRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/BooleanRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,130 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Assert;
+
+import jxl.BooleanCell;
+import jxl.CellType;
+import jxl.biff.FormattingRecords;
+
+/**
+ * A boolean cell last calculated value
+ */
+class BooleanRecord extends CellValue implements BooleanCell
+{
+ /**
+ * Indicates whether this cell contains an error or a boolean
+ */
+ private boolean error;
+
+ /**
+ * The boolean value of this cell. If this cell represents an error,
+ * this will be false
+ */
+ private boolean value;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param fr the formatting records
+ * @param si the sheet
+ */
+ public BooleanRecord(Record t, FormattingRecords fr, SheetImpl si)
+ {
+ super(t, fr, si);
+ error = false;
+ value = false;
+
+ byte[] data = getRecord().getData();
+
+ error = (data[7] == 1);
+
+ if (!error)
+ {
+ value = data[6] == 1 ? true : false;
+ }
+ }
+
+ /**
+ * Interface method which queries whether this cell contains an error.
+ * Returns TRUE if it does, otherwise returns FALSE.
+ *
+ * @return TRUE if this cell is an error, FALSE otherwise
+ */
+ public boolean isError()
+ {
+ return error;
+ }
+
+ /**
+ * Interface method which Gets the boolean value stored in this cell. If
+ * this cell contains an error, then returns FALSE. Always query this cell
+ * type using the accessor method isError() prior to calling this method
+ *
+ * @return TRUE if this cell contains TRUE, FALSE if it contains FALSE or
+ * an error code
+ */
+ public boolean getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the numerical value as a string
+ *
+ * @return The numerical value of the formula as a string
+ */
+ public String getContents()
+ {
+ Assert.verify(!isError());
+
+ // return Boolean.toString(value) - only available in 1.4 or later
+ return (new Boolean(value)).toString();
+ }
+
+ /**
+ * Returns the cell type
+ *
+ * @return The cell type
+ */
+ public CellType getType()
+ {
+ return CellType.BOOLEAN;
+ }
+
+ /**
+ * A special case which overrides the method in the subclass to get
+ * hold of the raw data
+ *
+ * @return the record
+ */
+ public Record getRecord()
+ {
+ return super.getRecord();
+ }
+}
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/BottomMarginRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/BottomMarginRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/BottomMarginRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,38 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.Type;
+
+/**
+ * Record for the left margin settings
+ */
+class BottomMarginRecord extends MarginRecord
+{
+ /**
+ * Constructor
+ *
+ * @param r the record
+ */
+ BottomMarginRecord(Record r)
+ {
+ super(Type.BOTTOMMARGIN, r);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/BoundsheetRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/BoundsheetRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/BoundsheetRecord.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,156 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.WorkbookSettings;
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+import jxl.biff.StringHelper;
+
+/**
+ * A boundsheet record, which contains the worksheet name
+ */
+class BoundsheetRecord extends RecordData
+{
+ /**
+ * The offset into the sheet
+ */
+ private int offset;
+ /**
+ * The type of sheet this is
+ */
+ private byte typeFlag;
+ /**
+ * The visibility flag
+ */
+ private byte visibilityFlag;
+ /**
+ * The length of the worksheet name
+ */
+ private int length;
+ /**
+ * The worksheet name
+ */
+ private String name;
+
+ /**
+ * Dummy indicators for overloading the constructor
+ */
+ private static class Biff7 {};
+ public static Biff7 biff7 = new Biff7();
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param s the workbook settings
+ */
+ public BoundsheetRecord(Record t, WorkbookSettings s)
+ {
+ super(t);
+ byte[] data = getRecord().getData();
+ offset = IntegerHelper.getInt(data[0], data[1], data[2], data[3]);
+ typeFlag = data[5];
+ visibilityFlag = data[4];
+ length = data[6];
+
+ if (data[7] == 0)
+ {
+ // Standard ASCII encoding
+ byte[] bytes = new byte[length];
+ System.arraycopy(data, 8, bytes, 0, length);
+ name = StringHelper.getString(bytes, length, 0, s);
+ }
+ else
+ {
+ // little endian Unicode encoding
+ byte[] bytes = new byte[length * 2];
+ System.arraycopy(data, 8, bytes, 0, length * 2);
+ name = StringHelper.getUnicodeString(bytes, length, 0);
+ }
+ }
+
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param biff7 a dummy value to tell the record to interpret the
+ * data as biff7
+ */
+ public BoundsheetRecord(Record t, Biff7 biff7)
+ {
+ super(t);
+ byte[] data = getRecord().getData();
+ offset = IntegerHelper.getInt(data[0], data[1], data[2], data[3]);
+ typeFlag = data[5];
+ visibilityFlag = data[4];
+ length = data[6];
+ byte[] bytes = new byte[length];
+ System.arraycopy(data, 7, bytes, 0, length);
+ name = new String(bytes);
+ }
+
+ /**
+ * Accessor for the worksheet name
+ *
+ * @return the worksheet name
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Accessor for the hidden flag
+ *
+ * @return TRUE if this is a hidden sheet, FALSE otherwise
+ */
+ public boolean isHidden()
+ {
+ return visibilityFlag != 0;
+ }
+
+ /**
+ * Accessor to determine if this is a worksheet, or some other nefarious
+ * type of object
+ *
+ * @return TRUE if this is a worksheet, FALSE otherwise
+ */
+ public boolean isSheet()
+ {
+ return typeFlag == 0;
+ }
+
+ /**
+ * Accessor to determine if this is a chart
+ *
+ * @return TRUE if this is a chart, FALSE otherwise
+ */
+ public boolean isChart()
+ {
+ return typeFlag == 2;
+ }
+
+}
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/ButtonPropertySetRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/ButtonPropertySetRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/ButtonPropertySetRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,57 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.biff.RecordData;
+
+/**
+ * Data associated with a button property set
+ */
+public class ButtonPropertySetRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger =
+ Logger.getLogger(ButtonPropertySetRecord.class);
+
+
+ /**
+ * Constructor
+ *
+ * @param t the record
+ */
+ ButtonPropertySetRecord(Record t)
+ {
+ super(t);
+ }
+
+ /**
+ * Accessor for the binary data
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return getRecord().getData();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/CalcModeRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/CalcModeRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/CalcModeRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,64 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * A calculation mode record
+ */
+class CalcModeRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(CalcModeRecord.class);
+
+ /**
+ * The calculation mode
+ */
+ private boolean automatic;
+
+ /**
+ * Constructor
+ *
+ * @param t the record
+ */
+ public CalcModeRecord(Record t)
+ {
+ super(t);
+ byte[] data = t.getData();
+ int mode = IntegerHelper.getInt(data[0], data[1]);
+ automatic = (mode == 1);
+ }
+
+ /**
+ * Accessor for the calculation mode
+ *
+ * @return the calculation mode
+ */
+ public boolean isAutomatic()
+ {
+ return automatic;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/CellFeaturesAccessor.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/CellFeaturesAccessor.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/CellFeaturesAccessor.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,42 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.CellFeatures;
+
+/**
+ * Allows the setting of the cell features in this package only
+ */
+interface CellFeaturesAccessor
+{
+ /**
+ * Sets the cell features
+ *
+ * @param cf the cell features
+ */
+ public void setCellFeatures(CellFeatures cf);
+
+ /**
+ * Convenience function (due to casting) to get the cell features
+ *
+ * @return the cell features
+ */
+ public CellFeatures getCellFeatures();
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/CellValue.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/CellValue.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/CellValue.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,210 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.Cell;
+import jxl.CellFeatures;
+import jxl.biff.FormattingRecords;
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+import jxl.biff.XFRecord;
+import jxl.format.CellFormat;
+
+/**
+ * Abstract class for all records which actually contain cell values
+ */
+public abstract class CellValue extends RecordData
+ implements Cell, CellFeaturesAccessor
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(CellValue.class);
+
+ /**
+ * The row number of this cell record
+ */
+ private int row;
+
+ /**
+ * The column number of this cell record
+ */
+ private int column;
+
+ /**
+ * The XF index
+ */
+ private int xfIndex;
+
+ /**
+ * A handle to the formatting records, so that we can
+ * retrieve the formatting information
+ */
+ private FormattingRecords formattingRecords;
+
+ /**
+ * A lazy initialize flag for the cell format
+ */
+ private boolean initialized;
+
+ /**
+ * The cell format
+ */
+ private XFRecord format;
+
+ /**
+ * A handle back to the sheet
+ */
+ private SheetImpl sheet;
+
+ /**
+ * The cell features
+ */
+ private CellFeatures features;
+
+ /**
+ * Constructs this object from the raw cell data
+ *
+ * @param t the raw cell data
+ * @param fr the formatting records
+ * @param si the sheet containing this cell
+ */
+ protected CellValue(Record t, FormattingRecords fr, SheetImpl si)
+ {
+ super(t);
+ byte[] data = getRecord().getData();
+ row = IntegerHelper.getInt(data[0], data[1]);
+ column = IntegerHelper.getInt(data[2], data[3]);
+ xfIndex = IntegerHelper.getInt(data[4], data[5]);
+ sheet = si;
+ formattingRecords = fr;
+ initialized = false;
+ }
+
+ /**
+ * Interface method which returns the row number of this cell
+ *
+ * @return the zero base row number
+ */
+ public final int getRow()
+ {
+ return row;
+ }
+
+ /**
+ * Interface method which returns the column number of this cell
+ *
+ * @return the zero based column number
+ */
+ public final int getColumn()
+ {
+ return column;
+ }
+
+ /**
+ * Gets the XFRecord corresponding to the index number. Used when
+ * copying a spreadsheet
+ *
+ * @return the xf index for this cell
+ */
+ public final int getXFIndex()
+ {
+ return xfIndex;
+ }
+
+ /**
+ * Gets the CellFormat object for this cell. Used by the WritableWorkbook
+ * API
+ *
+ * @return the CellFormat used for this cell
+ */
+ public CellFormat getCellFormat()
+ {
+ if (!initialized)
+ {
+ format = formattingRecords.getXFRecord(xfIndex);
+ initialized = true;
+ }
+
+ return format;
+ }
+
+ /**
+ * Determines whether or not this cell has been hidden
+ *
+ * @return TRUE if this cell has been hidden, FALSE otherwise
+ */
+ public boolean isHidden()
+ {
+ ColumnInfoRecord cir = sheet.getColumnInfo(column);
+
+ if (cir != null && (cir.getWidth() == 0 || cir.getHidden()))
+ {
+ return true;
+ }
+
+ RowRecord rr = sheet.getRowInfo(row);
+
+ if (rr != null && (rr.getRowHeight() == 0 || rr.isCollapsed()))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Accessor for the sheet
+ *
+ * @return the sheet
+ */
+ protected SheetImpl getSheet()
+ {
+ return sheet;
+ }
+
+ /**
+ * Accessor for the cell features
+ *
+ * @return the cell features or NULL if this cell doesn't have any
+ */
+ public CellFeatures getCellFeatures()
+ {
+ return features;
+ }
+
+ /**
+ * Sets the cell features during the reading process
+ *
+ * @param cf the cell features
+ */
+ public void setCellFeatures(CellFeatures cf)
+ {
+ if (features != null)
+ {
+ logger.warn("current cell features not null - overwriting");
+ }
+
+ features = cf;
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/CentreRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/CentreRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/CentreRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,56 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan, Adam Caldwell
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * Record which indicates the whether the horizontal center option has been set
+ */
+class CentreRecord extends RecordData
+{
+ /**
+ * The centre flag
+ */
+ private boolean centre;
+
+ /**
+ * Constructor
+ *
+ * @param t the record to constructfrom
+ */
+ public CentreRecord(Record t)
+ {
+ super(t);
+ byte[] data = getRecord().getData();
+ centre = IntegerHelper.getInt(data[0], data[1]) != 0;
+ }
+
+ /**
+ * Accessor for the centre flag
+ *
+ * @return Returns the centre flag.
+ */
+ public boolean isCentre()
+ {
+ return centre;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/CodepageRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/CodepageRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/CodepageRecord.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,63 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * A codepage record
+ */
+class CodepageRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(CodepageRecord.class);
+
+ /**
+ * The character encoding
+ */
+ private int characterSet;
+
+ /**
+ * Constructor
+ *
+ * @param t the record
+ */
+ public CodepageRecord(Record t)
+ {
+ super(t);
+ byte[] data = t.getData();
+ characterSet = IntegerHelper.getInt(data[0], data[1]);
+ }
+
+ /**
+ * Accessor for the encoding
+ *
+ * @return the character encoding
+ */
+ public int getCharacterSet()
+ {
+ return characterSet;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/ColumnInfoRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/ColumnInfoRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/ColumnInfoRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,164 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+import jxl.biff.Type;
+
+/**
+ * Contains the display info data which affects the entire columns
+ */
+public class ColumnInfoRecord extends RecordData
+{
+ /**
+ * The raw data
+ */
+ private byte[] data;
+
+ /**
+ * The start for which to apply the format information
+ */
+ private int startColumn;
+
+ /**
+ * The end column for which to apply the format information
+ */
+ private int endColumn;
+
+ /**
+ * The index to the XF record, which applies to each cell in this column
+ */
+ private int xfIndex;
+
+ /**
+ * The width of the column in 1/256 of a character
+ */
+ private int width;
+
+ /**
+ * A hidden flag
+ */
+ private boolean hidden;
+
+ /**
+ * The column's outline level
+ */
+ private int outlineLevel;
+
+ /**
+ * The column collapsed flag
+ */
+ private boolean collapsed;
+
+ /**
+ * Constructor which creates this object from the binary data
+ *
+ * @param t the record
+ */
+ ColumnInfoRecord(Record t)
+ {
+ super(Type.COLINFO);
+
+ data = t.getData();
+
+ startColumn = IntegerHelper.getInt(data[0], data[1]);
+ endColumn = IntegerHelper.getInt(data[2], data[3]);
+ width = IntegerHelper.getInt(data[4], data[5]);
+ xfIndex = IntegerHelper.getInt(data[6], data[7]);
+
+ int options = IntegerHelper.getInt(data[8], data[9]);
+ hidden = ((options & 0x1) != 0);
+ outlineLevel = ((options & 0x700) >> 8);
+ collapsed = ((options & 0x1000) != 0);
+ }
+
+ /**
+ * Accessor for the start column of this range
+ *
+ * @return the start column index
+ */
+ public int getStartColumn()
+ {
+ return startColumn;
+ }
+
+ /**
+ * Accessor for the end column of this range
+ *
+ * @return the end column index
+ */
+ public int getEndColumn()
+ {
+ return endColumn;
+ }
+
+ /**
+ * Accessor for the column format index
+ *
+ * @return the format index
+ */
+ public int getXFIndex()
+ {
+ return xfIndex;
+ }
+
+ /**
+ * Accessor for the column's outline level
+ *
+ * @return the column's outline level
+ */
+ public int getOutlineLevel()
+ {
+ return outlineLevel;
+ }
+
+ /**
+ * Accessor for whether the column is collapsed
+ *
+ * @return the column's collapsed state
+ */
+ public boolean getCollapsed()
+ {
+ return collapsed;
+ }
+
+ /**
+ * Accessor for the width of the column
+ *
+ * @return the width
+ */
+ public int getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Accessor for the hidden flag. Used when copying sheets
+ *
+ * @return TRUE if the columns are hidden, FALSE otherwise
+ */
+ public boolean getHidden()
+ {
+ return hidden;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/CompoundFile.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/CompoundFile.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/CompoundFile.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,609 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.BaseCompoundFile;
+import jxl.biff.IntegerHelper;
+
+/**
+ * Reads in and defrags an OLE compound compound file
+ * (Made public only for the PropertySets demo)
+ */
+public final class CompoundFile extends BaseCompoundFile
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(CompoundFile.class);
+
+ /**
+ * The original OLE stream, organized into blocks, which can
+ * appear at any physical location in the file
+ */
+ private byte[] data;
+ /**
+ * The number of blocks it takes to store the big block depot
+ */
+ private int numBigBlockDepotBlocks;
+ /**
+ * The start block of the small block depot
+ */
+ private int sbdStartBlock;
+ /**
+ * The start block of the root entry
+ */
+ private int rootStartBlock;
+ /**
+ * The header extension block
+ */
+ private int extensionBlock;
+ /**
+ * The number of header extension blocks
+ */
+ private int numExtensionBlocks;
+ /**
+ * The root entry
+ */
+ private byte[] rootEntry;
+ /**
+ * The sequence of blocks which comprise the big block chain
+ */
+ private int[] bigBlockChain;
+ /**
+ * The sequence of blocks which comprise the small block chain
+ */
+ private int[] smallBlockChain;
+ /**
+ * The chain of blocks which comprise the big block depot
+ */
+ private int[] bigBlockDepotBlocks;
+ /**
+ * The list of property sets
+ */
+ private ArrayList propertySets;
+
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings settings;
+
+ /**
+ * The property storage root entry
+ */
+ private PropertyStorage rootEntryPropertyStorage;
+
+ /**
+ * Initializes the compound file
+ *
+ * @param d the raw data of the ole stream
+ * @param ws the workbook settings
+ * @exception BiffException
+ */
+ public CompoundFile(byte[] d, WorkbookSettings ws) throws BiffException
+ {
+ super();
+ data = d;
+ settings = ws;
+
+ // First verify the OLE identifier
+ for (int i = 0; i < IDENTIFIER.length; i++)
+ {
+ if (data[i] != IDENTIFIER[i])
+ {
+ throw new BiffException(BiffException.unrecognizedOLEFile);
+ }
+ }
+
+ propertySets = new ArrayList();
+ numBigBlockDepotBlocks = IntegerHelper.getInt
+ (data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS],
+ data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS + 1],
+ data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS + 2],
+ data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS + 3]);
+ sbdStartBlock = IntegerHelper.getInt
+ (data[SMALL_BLOCK_DEPOT_BLOCK_POS],
+ data[SMALL_BLOCK_DEPOT_BLOCK_POS + 1],
+ data[SMALL_BLOCK_DEPOT_BLOCK_POS + 2],
+ data[SMALL_BLOCK_DEPOT_BLOCK_POS + 3]);
+ rootStartBlock = IntegerHelper.getInt
+ (data[ROOT_START_BLOCK_POS],
+ data[ROOT_START_BLOCK_POS + 1],
+ data[ROOT_START_BLOCK_POS + 2],
+ data[ROOT_START_BLOCK_POS + 3]);
+ extensionBlock = IntegerHelper.getInt
+ (data[EXTENSION_BLOCK_POS],
+ data[EXTENSION_BLOCK_POS + 1],
+ data[EXTENSION_BLOCK_POS + 2],
+ data[EXTENSION_BLOCK_POS + 3]);
+ numExtensionBlocks = IntegerHelper.getInt
+ (data[NUM_EXTENSION_BLOCK_POS],
+ data[NUM_EXTENSION_BLOCK_POS + 1],
+ data[NUM_EXTENSION_BLOCK_POS + 2],
+ data[NUM_EXTENSION_BLOCK_POS + 3]);
+
+ bigBlockDepotBlocks = new int[numBigBlockDepotBlocks];
+
+ int pos = BIG_BLOCK_DEPOT_BLOCKS_POS;
+
+ int bbdBlocks = numBigBlockDepotBlocks;
+
+ if (numExtensionBlocks != 0)
+ {
+ bbdBlocks = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS) / 4;
+ }
+
+ for (int i = 0; i < bbdBlocks; i++)
+ {
+ bigBlockDepotBlocks[i] = IntegerHelper.getInt
+ (d[pos], d[pos + 1], d[pos + 2], d[pos + 3]);
+ pos += 4;
+ }
+
+ for (int j = 0; j < numExtensionBlocks; j++)
+ {
+ pos = (extensionBlock + 1) * BIG_BLOCK_SIZE;
+ int blocksToRead = Math.min(numBigBlockDepotBlocks - bbdBlocks,
+ BIG_BLOCK_SIZE / 4 - 1);
+
+ for (int i = bbdBlocks; i < bbdBlocks + blocksToRead; i++)
+ {
+ bigBlockDepotBlocks[i] = IntegerHelper.getInt
+ (d[pos], d[pos + 1], d[pos + 2], d[pos + 3]);
+ pos += 4;
+ }
+
+ bbdBlocks += blocksToRead;
+ if (bbdBlocks < numBigBlockDepotBlocks)
+ {
+ extensionBlock = IntegerHelper.getInt
+ (d[pos], d[pos + 1], d[pos + 2], d[pos + 3]);
+ }
+ }
+
+ readBigBlockDepot();
+ readSmallBlockDepot();
+
+ rootEntry = readData(rootStartBlock);
+ readPropertySets();
+ }
+
+ /**
+ * Reads the big block depot entries
+ */
+ private void readBigBlockDepot()
+ {
+ int pos = 0;
+ int index = 0;
+ bigBlockChain = new int[numBigBlockDepotBlocks * BIG_BLOCK_SIZE / 4];
+
+ for (int i = 0; i < numBigBlockDepotBlocks; i++)
+ {
+ pos = (bigBlockDepotBlocks[i] + 1) * BIG_BLOCK_SIZE;
+
+ for (int j = 0; j < BIG_BLOCK_SIZE / 4; j++)
+ {
+ bigBlockChain[index] = IntegerHelper.getInt
+ (data[pos], data[pos + 1], data[pos + 2], data[pos + 3]);
+ pos += 4;
+ index++;
+ }
+ }
+ }
+
+ /**
+ * Reads the small block chain's depot entries
+ */
+ private void readSmallBlockDepot()
+ {
+ int pos = 0;
+ int index = 0;
+ int sbdBlock = sbdStartBlock;
+ smallBlockChain = new int[0];
+
+ // Some non-excel generators specify -1 for an empty small block depot
+ // simply warn and return
+ if (sbdBlock == -1)
+ {
+ logger.warn("invalid small block depot number");
+ return;
+ }
+
+ while (sbdBlock != -2)
+ {
+ // Allocate some more space to the small block chain
+ int[] oldChain = smallBlockChain;
+ smallBlockChain = new int[smallBlockChain.length + BIG_BLOCK_SIZE / 4];
+ System.arraycopy(oldChain, 0, smallBlockChain, 0, oldChain.length);
+
+ pos = (sbdBlock + 1) * BIG_BLOCK_SIZE;
+
+ for (int j = 0; j < BIG_BLOCK_SIZE / 4; j++)
+ {
+ smallBlockChain[index] = IntegerHelper.getInt
+ (data[pos], data[pos + 1], data[pos + 2], data[pos + 3]);
+ pos += 4;
+ index++;
+ }
+
+ sbdBlock = bigBlockChain[sbdBlock];
+ }
+ }
+
+ /**
+ * Reads all the property sets
+ */
+ private void readPropertySets()
+ {
+ int offset = 0;
+ byte[] d = null;
+
+ while (offset < rootEntry.length)
+ {
+ d = new byte[PROPERTY_STORAGE_BLOCK_SIZE];
+ System.arraycopy(rootEntry, offset, d, 0, d.length);
+ PropertyStorage ps = new PropertyStorage(d);
+
+ // sometimes the MAC Operating system leaves some property storage
+ // names blank. Contributed by Jacky
+ if (ps.name == null || ps.name.length() == 0)
+ {
+ if (ps.type == ROOT_ENTRY_PS_TYPE)
+ {
+ ps.name = ROOT_ENTRY_NAME;
+ logger.warn("Property storage name for " + ps.type +
+ " is empty - setting to " + ROOT_ENTRY_NAME);
+ }
+ else
+ {
+ if (ps.size != 0)
+ {
+ logger.warn("Property storage type " + ps.type +
+ " is non-empty and has no associated name");
+ }
+ }
+ }
+ propertySets.add(ps);
+ if (ps.name.equalsIgnoreCase(ROOT_ENTRY_NAME))
+ {
+ rootEntryPropertyStorage = ps;
+ }
+ offset += PROPERTY_STORAGE_BLOCK_SIZE;
+ }
+
+ if (rootEntryPropertyStorage == null)
+ {
+ rootEntryPropertyStorage = (PropertyStorage) propertySets.get(0);
+ }
+ }
+
+ /**
+ * Gets the defragmented stream from this ole compound file
+ *
+ * @param streamName the stream name to get
+ * @return the defragmented ole stream
+ * @exception BiffException
+ */
+ public byte[] getStream(String streamName) throws BiffException
+ {
+ PropertyStorage ps = findPropertyStorage(streamName,
+ rootEntryPropertyStorage);
+
+ // Property set can't be found from the direct hierarchy, so just
+ // search on the name
+ if (ps == null)
+ {
+ ps = getPropertyStorage(streamName);
+ }
+
+ if (ps.size >= SMALL_BLOCK_THRESHOLD ||
+ streamName.equalsIgnoreCase(ROOT_ENTRY_NAME))
+ {
+ return getBigBlockStream(ps);
+ }
+ else
+ {
+ return getSmallBlockStream(ps);
+ }
+ }
+
+ /**
+ * Gets the defragmented stream from this ole compound file. Used when
+ * copying workbooks with macros
+ *
+ * @param psIndex the property storage index
+ * @return the defragmented ole stream
+ * @exception BiffException
+ */
+ public byte[] getStream(int psIndex) throws BiffException
+ {
+ PropertyStorage ps = getPropertyStorage(psIndex);
+
+ if (ps.size >= SMALL_BLOCK_THRESHOLD ||
+ ps.name.equalsIgnoreCase(ROOT_ENTRY_NAME))
+ {
+ return getBigBlockStream(ps);
+ }
+ else
+ {
+ return getSmallBlockStream(ps);
+ }
+ }
+
+ /**
+ * Recursively searches the property storages in hierarchy order
+ * for the appropriate name. This is the public version which is
+ * invoked from the writable version
+ * when copying a sheet with addition property sets.
+ */
+ public PropertyStorage findPropertyStorage(String name)
+ {
+ return findPropertyStorage(name, rootEntryPropertyStorage);
+ }
+
+ /**
+ * Recursively searches the property storages in hierarchy order
+ * for the appropriate name.
+ */
+ private PropertyStorage findPropertyStorage(String name,
+ PropertyStorage base)
+ {
+ if (base.child == -1)
+ {
+ return null;
+ }
+
+ // Get the child
+ PropertyStorage child = getPropertyStorage(base.child);
+ if (child.name.equalsIgnoreCase(name))
+ {
+ return child;
+ }
+
+ // Find the previous property storages on the same level
+ PropertyStorage prev = child;
+ while (prev.previous != -1)
+ {
+ prev = getPropertyStorage(prev.previous);
+ if (prev.name.equalsIgnoreCase(name))
+ {
+ return prev;
+ }
+ }
+
+ // Find the next property storages on the same level
+ PropertyStorage next = child;
+ while (next.next != -1)
+ {
+ next = getPropertyStorage(next.next);
+ if (next.name.equalsIgnoreCase(name))
+ {
+ return next;
+ }
+ }
+
+ return findPropertyStorage(name, child);
+ }
+
+ /**
+ * Gets the property set with the specified name
+ * @param name the property storage name
+ * @return the property storage record
+ * @exception BiffException
+ * @deprecated remove me
+ */
+ private PropertyStorage getPropertyStorage(String name)
+ throws BiffException
+ {
+ // Find the workbook property
+ Iterator i = propertySets.iterator();
+ boolean found = false;
+ boolean multiple = false;
+ PropertyStorage ps = null;
+ while (i.hasNext())
+ {
+ PropertyStorage ps2 = (PropertyStorage) i.next();
+ if (ps2.name.equalsIgnoreCase(name))
+ {
+ multiple = found == true ? true : false;
+ found = true;
+ ps = ps2;
+ }
+ }
+
+ if (multiple)
+ {
+ logger.warn("found multiple copies of property set " + name);
+ }
+
+ if (!found)
+ {
+ throw new BiffException(BiffException.streamNotFound);
+ }
+
+ return ps;
+ }
+
+ /**
+ * Gets the property set with the specified name
+ * @param index the index of the property storage
+ * @return the property storage record
+ */
+ private PropertyStorage getPropertyStorage(int index)
+ {
+ return (PropertyStorage) propertySets.get(index);
+ }
+
+ /**
+ * Build up the resultant stream using the big blocks
+ *
+ * @param ps the property storage
+ * @return the big block stream
+ */
+ private byte[] getBigBlockStream(PropertyStorage ps)
+ {
+ int numBlocks = ps.size / BIG_BLOCK_SIZE;
+ if (ps.size % BIG_BLOCK_SIZE != 0)
+ {
+ numBlocks++;
+ }
+
+ byte[] streamData = new byte[numBlocks * BIG_BLOCK_SIZE];
+
+ int block = ps.startBlock;
+
+ int count = 0;
+ int pos = 0;
+ while (block != -2 && count < numBlocks)
+ {
+ pos = (block + 1) * BIG_BLOCK_SIZE;
+ System.arraycopy(data, pos, streamData,
+ count * BIG_BLOCK_SIZE, BIG_BLOCK_SIZE);
+ count++;
+ block = bigBlockChain[block];
+ }
+
+ if (block != -2 && count == numBlocks)
+ {
+ logger.warn("Property storage size inconsistent with block chain.");
+ }
+
+ return streamData;
+ }
+
+ /**
+ * Build up the resultant stream using the small blocks
+ * @param ps the property storage
+ * @return the data
+ * @exception BiffException
+ */
+ private byte[] getSmallBlockStream(PropertyStorage ps)
+ throws BiffException
+ {
+ /*
+ PropertyStorage rootps = null;
+ try
+ {
+ rootps = getPropertyStorage(ROOT_ENTRY_NAME);
+ }
+ catch (BiffException e)
+ {
+ rootps = (PropertyStorage) propertySets.get(0);
+ }
+ */
+
+ byte[] rootdata = readData(rootEntryPropertyStorage.startBlock);
+ byte[] sbdata = new byte[0];
+
+ int block = ps.startBlock;
+ int pos = 0;
+
+ while (block != -2)
+ {
+ // grow the array
+ byte[] olddata = sbdata;
+ sbdata = new byte[olddata.length + SMALL_BLOCK_SIZE];
+ System.arraycopy(olddata, 0, sbdata, 0, olddata.length);
+
+ // Copy in the new data
+ pos = block * SMALL_BLOCK_SIZE;
+ System.arraycopy(rootdata, pos, sbdata,
+ olddata.length, SMALL_BLOCK_SIZE);
+ block = smallBlockChain[block];
+
+ if (block == -1)
+ {
+ logger.warn("Incorrect terminator for small block stream " + ps.name);
+ block = -2; // kludge to force the loop termination
+ }
+ }
+
+ return sbdata;
+ }
+
+ /**
+ * Reads the block chain from the specified block and returns the
+ * data as a continuous stream of bytes
+ *
+ * @param bl the block number
+ * @return the data
+ */
+ private byte[] readData(int bl) throws BiffException
+ {
+ int block = bl;
+ int pos = 0;
+ byte[] entry = new byte[0];
+
+ while (block != -2)
+ {
+ // Grow the array
+ byte[] oldEntry = entry;
+ entry = new byte[oldEntry.length + BIG_BLOCK_SIZE];
+ System.arraycopy(oldEntry, 0, entry, 0, oldEntry.length);
+ pos = (block + 1) * BIG_BLOCK_SIZE;
+ System.arraycopy(data, pos, entry,
+ oldEntry.length, BIG_BLOCK_SIZE);
+ if (bigBlockChain[block] == block)
+ {
+ throw new BiffException(BiffException.corruptFileFormat);
+ }
+ block = bigBlockChain[block];
+ }
+ return entry;
+ }
+
+ /**
+ * Gets the number of property sets
+ * @return the number of property sets
+ */
+ public int getNumberOfPropertySets()
+ {
+ return propertySets.size();
+ }
+
+ /**
+ * Gets the property set. Invoked when copying worksheets with macros.
+ * Simply calls the private counterpart
+ *
+ * @param ps the property set name
+ * @return the property set with the given name
+ */
+ public PropertyStorage getPropertySet(int index)
+ {
+ return getPropertyStorage(index);
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/CountryRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/CountryRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/CountryRecord.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,88 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * Contains the cell dimensions of this worksheet
+ */
+public class CountryRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(CountryRecord.class);
+
+ /**
+ * The user interface language
+ */
+ private int language;
+
+ /**
+ * The regional settings
+ */
+ private int regionalSettings;
+
+ /**
+ * Constructs the dimensions from the raw data
+ *
+ * @param t the raw data
+ */
+ public CountryRecord(Record t)
+ {
+ super(t);
+ byte[] data = t.getData();
+
+ language = IntegerHelper.getInt(data[0], data[1]);
+ regionalSettings = IntegerHelper.getInt(data[2], data[3]);
+ }
+
+ /**
+ * Accessor for the language code
+ *
+ * @return the language code
+ */
+ public int getLanguageCode()
+ {
+ return language;
+ }
+
+ /**
+ * Accessor for the regional settings code
+ *
+ * @return the regional settings code
+ */
+ public int getRegionalSettingsCode()
+ {
+ return regionalSettings;
+ }
+
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/DateFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/DateFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/DateFormulaRecord.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,151 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.text.NumberFormat;
+
+import jxl.CellType;
+import jxl.DateCell;
+import jxl.DateFormulaCell;
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.formula.ExternalSheet;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+
+/**
+ * A date formula's last calculated value
+ */
+class DateFormulaRecord extends DateRecord
+ implements DateCell, FormulaData, DateFormulaCell
+{
+ /**
+ * The formula as an excel string
+ */
+ private String formulaString;
+
+ /**
+ * A handle to the class needed to access external sheets
+ */
+ private ExternalSheet externalSheet;
+
+ /**
+ * A handle to the name table
+ */
+ private WorkbookMethods nameTable;
+
+ /**
+ * The raw data
+ */
+ private byte[] data;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the basic number formula record
+ * @param fr the formatting records
+ * @param es the external sheet
+ * @param nt the name table
+ * @param nf flag indicating whether the 1904 date system is in use
+ * @param si the sheet
+ */
+ public DateFormulaRecord(NumberFormulaRecord t, FormattingRecords fr,
+ ExternalSheet es, WorkbookMethods nt,
+ boolean nf, SheetImpl si) throws FormulaException
+ {
+ super(t, t.getXFIndex(), fr, nf, si);
+
+ externalSheet = es;
+ nameTable = nt;
+ data = t.getFormulaData();
+ }
+
+ /**
+ * Returns the cell type
+ *
+ * @return The cell type
+ */
+ public CellType getType()
+ {
+ return CellType.DATE_FORMULA;
+ }
+
+ /**
+ * Gets the raw bytes for the formula. This will include the
+ * parsed tokens array. Used when copying spreadsheets
+ *
+ * @return the raw record data
+ */
+ public byte[] getFormulaData() throws FormulaException
+ {
+ if (!getSheet().getWorkbookBof().isBiff8())
+ {
+ throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
+ }
+
+ // Data is already the formula data, so don't do any more manipulation
+ return data;
+ }
+
+ /**
+ * Gets the formula as an excel string
+ *
+ * @return the formula as an excel string
+ * @exception FormulaException
+ */
+ public String getFormula() throws FormulaException
+ {
+ // Note that the standard information was lopped off by the NumberFormula
+ // record when creating this formula
+ if (formulaString == null)
+ {
+ byte[] tokens = new byte[data.length - 16];
+ System.arraycopy(data, 16, tokens, 0, tokens.length);
+ FormulaParser fp = new FormulaParser
+ (tokens, this, externalSheet, nameTable,
+ getSheet().getWorkbook().getSettings());
+ fp.parse();
+ formulaString = fp.getFormula();
+ }
+
+ return formulaString;
+ }
+
+ /**
+ * Interface method which returns the value
+ *
+ * @return the last calculated value of the formula
+ */
+ public double getValue()
+ {
+ return 0;
+ }
+
+ /**
+ * Dummy implementation in order to adhere to the NumberCell interface
+ *
+ * @return NULL
+ */
+ public NumberFormat getNumberFormat()
+ {
+ return null;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/DateRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/DateRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/DateRecord.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,351 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.CellFeatures;
+import jxl.CellType;
+import jxl.DateCell;
+import jxl.NumberCell;
+import jxl.biff.FormattingRecords;
+import jxl.format.CellFormat;
+
+/**
+ * A date which is stored in the cell
+ */
+class DateRecord implements DateCell, CellFeaturesAccessor
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(DateRecord.class);
+
+ /**
+ * The date represented within this cell
+ */
+ private Date date;
+ /**
+ * The row number of this cell record
+ */
+ private int row;
+ /**
+ * The column number of this cell record
+ */
+ private int column;
+
+ /**
+ * Indicates whether this is a full date, or merely a time
+ */
+ private boolean time;
+
+ /**
+ * The format to use when displaying this cell's contents as a string
+ */
+ private DateFormat format;
+
+ /**
+ * The raw cell format
+ */
+ private CellFormat cellFormat;
+
+ /**
+ * The index to the XF Record
+ */
+ private int xfIndex;
+
+ /**
+ * A handle to the formatting records
+ */
+ private FormattingRecords formattingRecords;
+
+ /**
+ * A handle to the sheet
+ */
+ private SheetImpl sheet;
+
+ /**
+ * The cell features
+ */
+ private CellFeatures features;
+
+
+ /**
+ * A flag to indicate whether this objects formatting things have
+ * been initialized
+ */
+ private boolean initialized;
+
+ // The default formats used when returning the date as a string
+ private static final SimpleDateFormat dateFormat =
+ new SimpleDateFormat("dd MMM yyyy");
+
+ private static final SimpleDateFormat timeFormat =
+ new SimpleDateFormat("HH:mm:ss");
+
+ // The number of days between 1 Jan 1900 and 1 March 1900. Excel thinks
+ // the day before this was 29th Feb 1900, but it was 28th Feb 1900.
+ // I guess the programmers thought nobody would notice that they
+ // couldn't be bothered to program this dating anomaly properly
+ private static final int nonLeapDay = 61;
+
+ private static final TimeZone gmtZone = TimeZone.getTimeZone("GMT");
+
+ // The number of days between 01 Jan 1900 and 01 Jan 1970 - this gives
+ // the UTC offset
+ private static final int utcOffsetDays = 25569;
+
+ // The number of days between 01 Jan 1904 and 01 Jan 1970 - this gives
+ // the UTC offset using the 1904 date system
+ private static final int utcOffsetDays1904 = 24107;
+
+ // The number of milliseconds in a day
+ private static final long secondsInADay = 24 * 60 * 60;
+ private static final long msInASecond = 1000;
+ private static final long msInADay = secondsInADay * msInASecond;
+
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param num the numerical representation of this
+ * @param xfi the java equivalent of the excel date format
+ * @param fr the formatting records
+ * @param nf flag indicating whether we are using the 1904 date system
+ * @param si the sheet
+ */
+ public DateRecord(NumberCell num,
+ int xfi, FormattingRecords fr,
+ boolean nf, SheetImpl si)
+ {
+ row = num.getRow();
+ column = num.getColumn();
+ xfIndex = xfi;
+ formattingRecords = fr;
+ sheet = si;
+ initialized = false;
+
+ format = formattingRecords.getDateFormat(xfIndex);
+
+ // This value represents the number of days since 01 Jan 1900
+ double numValue = num.getValue();
+
+ if (Math.abs(numValue) < 1)
+ {
+ if (format == null)
+ {
+ format = timeFormat;
+ }
+ time = true;
+ }
+ else
+ {
+ if (format == null)
+ {
+ format = dateFormat;
+ }
+ time = false;
+ }
+
+ // Work round a bug in excel. Excel seems to think there is a date
+ // called the 29th Feb, 1900 - but in actual fact this was not a leap year.
+ // Therefore for values less than 61 in the 1900 date system,
+ // add one to the numeric value
+ if (!nf && !time && numValue < nonLeapDay)
+ {
+ numValue += 1;
+ }
+
+ // Get rid of any timezone adjustments - we are not interested
+ // in automatic adjustments
+ format.setTimeZone(gmtZone);
+
+ // Convert this to the number of days since 01 Jan 1970
+ int offsetDays = nf ? utcOffsetDays1904 : utcOffsetDays;
+ double utcDays = numValue - offsetDays;
+
+ // Convert this into utc by multiplying by the number of milliseconds
+ // in a day. Use the round function prior to ms conversion due
+ // to a rounding feature of Excel (contributed by Jurgen
+ long utcValue = Math.round(utcDays * secondsInADay) * msInASecond;
+
+ date = new Date(utcValue);
+ }
+
+ /**
+ * Interface method which returns the row number of this cell
+ *
+ * @return the zero base row number
+ */
+ public final int getRow()
+ {
+ return row;
+ }
+
+ /**
+ * Interface method which returns the column number of this cell
+ *
+ * @return the zero based column number
+ */
+ public final int getColumn()
+ {
+ return column;
+ }
+
+ /**
+ * Gets the date
+ *
+ * @return the date
+ */
+ public Date getDate()
+ {
+ return date;
+ }
+
+ /**
+ * Gets the cell contents as a string. This method will use the java
+ * equivalent of the excel formatting string
+ *
+ * @return the label
+ */
+ public String getContents()
+ {
+ return format.format(date);
+ }
+
+ /**
+ * Accessor for the cell type
+ *
+ * @return the cell type
+ */
+ public CellType getType()
+ {
+ return CellType.DATE;
+ }
+
+ /**
+ * Indicates whether the date value contained in this cell refers to a date,
+ * or merely a time
+ *
+ * @return TRUE if the value refers to a time
+ */
+ public boolean isTime()
+ {
+ return time;
+ }
+
+ /**
+ * Gets the DateFormat used to format the cell. This will normally be
+ * the format specified in the excel spreadsheet, but in the event of any
+ * difficulty parsing this, it will revert to the default date/time format.
+ *
+ * @return the DateFormat object used to format the date in the original
+ * excel cell
+ */
+ public DateFormat getDateFormat()
+ {
+ Assert.verify(format != null);
+
+ return format;
+ }
+
+ /**
+ * Gets the CellFormat object for this cell. Used by the WritableWorkbook
+ * API
+ *
+ * @return the CellFormat used for this cell
+ */
+ public CellFormat getCellFormat()
+ {
+ if (!initialized)
+ {
+ cellFormat = formattingRecords.getXFRecord(xfIndex);
+ initialized = true;
+ }
+
+ return cellFormat;
+ }
+
+ /**
+ * Determines whether or not this cell has been hidden
+ *
+ * @return TRUE if this cell has been hidden, FALSE otherwise
+ */
+ public boolean isHidden()
+ {
+ ColumnInfoRecord cir = sheet.getColumnInfo(column);
+
+ if (cir != null && cir.getWidth() == 0)
+ {
+ return true;
+ }
+
+ RowRecord rr = sheet.getRowInfo(row);
+
+ if (rr != null && (rr.getRowHeight() == 0 || rr.isCollapsed()))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Accessor for the sheet
+ *
+ * @return the containing sheet
+ */
+ protected final SheetImpl getSheet()
+ {
+ return sheet;
+ }
+
+ /**
+ * Accessor for the cell features
+ *
+ * @return the cell features or NULL if this cell doesn't have any
+ */
+ public CellFeatures getCellFeatures()
+ {
+ return features;
+ }
+
+ /**
+ * Sets the cell features
+ *
+ * @param cf the cell features
+ */
+ public void setCellFeatures(CellFeatures cf)
+ {
+ features = cf;
+ }
+
+}
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/DefaultColumnWidthRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/DefaultColumnWidthRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/DefaultColumnWidthRecord.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,65 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * Contains the default column width for cells in this sheet
+ */
+class DefaultColumnWidthRecord extends RecordData
+{
+ /**
+ * The default columns width, in characters
+ */
+ private int width;
+
+ /**
+ * Constructs the def col width from the raw data
+ *
+ * @param t the raw data
+ */
+ public DefaultColumnWidthRecord(Record t)
+ {
+ super(t);
+ byte[] data = t.getData();
+
+ width = IntegerHelper.getInt(data[0], data[1]);
+ }
+
+
+ /**
+ * Accessor for the default width
+ *
+ * @return the width
+ */
+ public int getWidth()
+ {
+ return width;
+ }
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/DefaultRowHeightRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/DefaultRowHeightRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/DefaultRowHeightRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,67 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * Contains the default column width for cells in this sheet
+ */
+class DefaultRowHeightRecord extends RecordData
+{
+ /**
+ * The default row height, in 1/20ths of a point
+ */
+ private int height;
+
+ /**
+ * Constructs the def col width from the raw data
+ *
+ * @param t the raw data
+ */
+ public DefaultRowHeightRecord(Record t)
+ {
+ super(t);
+ byte[] data = t.getData();
+
+ if (data.length > 2)
+ {
+ height = IntegerHelper.getInt(data[2], data[3]);
+ }
+ }
+
+ /**
+ * Accessor for the default height
+ *
+ * @return the height
+ */
+ public int getHeight()
+ {
+ return height;
+ }
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/DimensionRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/DimensionRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/DimensionRecord.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,135 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * Contains the cell dimensions of this worksheet
+ */
+class DimensionRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(DimensionRecord.class);
+
+ /**
+ * The number of rows in this sheet
+ */
+ private int numRows;
+ /**
+ * The number of columns in this worksheet
+ */
+ private int numCols;
+
+ /**
+ * Dummy indicators for overloading the constructor
+ */
+ private static class Biff7 {};
+ public static Biff7 biff7 = new Biff7();
+
+ /**
+ * Constructs the dimensions from the raw data
+ *
+ * @param t the raw data
+ */
+ public DimensionRecord(Record t)
+ {
+ super(t);
+ byte[] data = t.getData();
+
+ // Sometimes, if the spreadsheet is being generated by dodgy VB modules,
+ // even though the excel format is biff8, the dimension record is
+ // generated in the old biff 7 format. This horrible if construct
+ // handles that eventuality
+ if (data.length == 10)
+ {
+ read10ByteData(data);
+ }
+ else
+ {
+ read14ByteData(data);
+ }
+ }
+
+ /**
+ * Constructs the dimensions from the raw data
+ *
+ * @param t the raw data
+ * @param biff7 an indicator to initialise this record for biff 7 format
+ */
+ public DimensionRecord(Record t, Biff7 biff7)
+ {
+ super(t);
+ byte[] data = t.getData();
+ read10ByteData(data);
+ }
+
+ /**
+ * Reads in the data for data records of length 10
+ * @param data the data to read
+ */
+ private void read10ByteData(byte[] data)
+ {
+ numRows = IntegerHelper.getInt(data[2], data[3]);
+ numCols = IntegerHelper.getInt(data[6], data[7]);
+ }
+
+ /**
+ * Reads in the data for data records of length 14
+ * @param data the data to read
+ */
+ private void read14ByteData(byte[] data)
+ {
+ numRows = IntegerHelper.getInt(data[4], data[5], data[6], data[7]);
+ numCols = IntegerHelper.getInt(data[10], data[11]);
+ }
+
+ /**
+ * Accessor for the number of rows in this sheet
+ *
+ * @return the number of rows
+ */
+ public int getNumberOfRows()
+ {
+ return numRows;
+ }
+
+ /**
+ * Accessor for the number of columns in this sheet
+ *
+ * @return the number of columns
+ */
+ public int getNumberOfColumns()
+ {
+ return numCols;
+ }
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/ErrorFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/ErrorFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/ErrorFormulaRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,175 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Assert;
+
+import jxl.CellType;
+import jxl.ErrorCell;
+import jxl.ErrorFormulaCell;
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.formula.ExternalSheet;
+import jxl.biff.formula.FormulaErrorCode;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+
+/**
+ * An error resulting from the calculation of a formula
+ */
+class ErrorFormulaRecord extends CellValue
+ implements ErrorCell, FormulaData, ErrorFormulaCell
+{
+ /**
+ * The error code of this cell
+ */
+ private int errorCode;
+
+ /**
+ * A handle to the class needed to access external sheets
+ */
+ private ExternalSheet externalSheet;
+
+ /**
+ * A handle to the name table
+ */
+ private WorkbookMethods nameTable;
+
+ /**
+ * The formula as an excel string
+ */
+ private String formulaString;
+
+ /**
+ * The raw data
+ */
+ private byte[] data;
+
+ /**
+ * The error code
+ */
+ private FormulaErrorCode error;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param fr the formatting records
+ * @param es the external sheet
+ * @param nt the name table
+ * @param si the sheet
+ */
+ public ErrorFormulaRecord(Record t, FormattingRecords fr, ExternalSheet es,
+ WorkbookMethods nt,
+ SheetImpl si)
+ {
+ super(t, fr, si);
+
+ externalSheet = es;
+ nameTable = nt;
+ data = getRecord().getData();
+
+ Assert.verify(data[6] == 2);
+
+ errorCode = data[8];
+ }
+
+ /**
+ * Interface method which gets the error code for this cell. If this cell
+ * does not represent an error, then it returns 0. Always use the
+ * method isError() to determine this prior to calling this method
+ *
+ * @return the error code if this cell contains an error, 0 otherwise
+ */
+ public int getErrorCode()
+ {
+ return errorCode;
+ }
+
+ /**
+ * Returns the numerical value as a string
+ *
+ * @return The numerical value of the formula as a string
+ */
+ public String getContents()
+ {
+ if (error == null)
+ {
+ error = FormulaErrorCode.getErrorCode(errorCode);
+ }
+
+ return error != FormulaErrorCode.UNKNOWN ?
+ error.getDescription() : "ERROR " + errorCode;
+ }
+
+ /**
+ * Returns the cell type
+ *
+ * @return The cell type
+ */
+ public CellType getType()
+ {
+ return CellType.FORMULA_ERROR;
+ }
+
+ /**
+ * Gets the raw bytes for the formula. This will include the
+ * parsed tokens array
+ *
+ * @return the raw record data
+ */
+ public byte[] getFormulaData() throws FormulaException
+ {
+ if (!getSheet().getWorkbookBof().isBiff8())
+ {
+ throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
+ }
+
+ // Lop off the standard information
+ byte[] d = new byte[data.length - 6];
+ System.arraycopy(data, 6, d, 0, data.length - 6);
+
+ return d;
+ }
+
+ /**
+ * Gets the formula as an excel string
+ *
+ * @return the formula as an excel string
+ * @exception FormulaException
+ */
+ public String getFormula() throws FormulaException
+ {
+ if (formulaString == null)
+ {
+ byte[] tokens = new byte[data.length - 22];
+ System.arraycopy(data, 22, tokens, 0, tokens.length);
+ FormulaParser fp = new FormulaParser
+ (tokens, this, externalSheet, nameTable,
+ getSheet().getWorkbook().getSettings());
+ fp.parse();
+ formulaString = fp.getFormula();
+ }
+
+ return formulaString;
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/ErrorRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/ErrorRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/ErrorRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,85 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.CellType;
+import jxl.ErrorCell;
+import jxl.biff.FormattingRecords;
+
+/**
+ * A cell containing an error code. This will usually be the result
+ * of some error during the calculation of a formula
+ */
+class ErrorRecord extends CellValue implements ErrorCell
+{
+ /**
+ * The error code if this cell evaluates to an error, otherwise zer0
+ */
+ private int errorCode;
+
+ /**
+ * Constructs this object
+ *
+ * @param t the raw data
+ * @param fr the formatting records
+ * @param si the sheet
+ */
+ public ErrorRecord(Record t, FormattingRecords fr, SheetImpl si)
+ {
+ super(t, fr, si);
+
+ byte[] data = getRecord().getData();
+
+ errorCode = data[6];
+ }
+
+ /**
+ * Interface method which gets the error code for this cell. If this cell
+ * does not represent an error, then it returns 0. Always use the
+ * method isError() to determine this prior to calling this method
+ *
+ * @return the error code if this cell contains an error, 0 otherwise
+ */
+ public int getErrorCode()
+ {
+ return errorCode;
+ }
+
+ /**
+ * Returns the numerical value as a string
+ *
+ * @return The numerical value of the formula as a string
+ */
+ public String getContents()
+ {
+ return "ERROR " + errorCode;
+ }
+
+ /**
+ * Returns the cell type
+ *
+ * @return The cell type
+ */
+ public CellType getType()
+ {
+ return CellType.ERROR;
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/ExternalNameRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/ExternalNameRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/ExternalNameRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,108 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+import jxl.biff.StringHelper;
+
+
+/**
+ * A row record
+ */
+public class ExternalNameRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(ExternalNameRecord.class);
+
+ /**
+ * The name
+ */
+ private String name;
+
+ /**
+ * Add in function flag
+ */
+ private boolean addInFunction;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param ws the workbook settings
+ */
+ ExternalNameRecord(Record t, WorkbookSettings ws)
+ {
+ super(t);
+
+ byte[] data = getRecord().getData();
+ int options = IntegerHelper.getInt(data[0], data[1]);
+
+ if (options == 0)
+ {
+ addInFunction = true;
+ }
+
+ if (!addInFunction)
+ {
+ return;
+ }
+
+ int length = data[6];
+
+ boolean unicode = (data[7] != 0);
+
+ if (unicode)
+ {
+ name = StringHelper.getUnicodeString(data, length, 8);
+ }
+ else
+ {
+ name = StringHelper.getString(data, length, 8, ws);
+ }
+ }
+
+ /**
+ * Queries whether this name record refers to an external record
+ *
+ * @return TRUE if this name record is an add in function, FALSE otherwise
+ */
+ public boolean isAddInFunction()
+ {
+ return addInFunction;
+ }
+
+ /**
+ * Gets the name
+ *
+ * @return the name
+ */
+ public String getName()
+ {
+ return name;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/ExternalSheetRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/ExternalSheetRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/ExternalSheetRecord.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,191 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * An Externsheet record, containing the details of externally references
+ * workbooks
+ */
+public class ExternalSheetRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(ExternalSheetRecord.class);
+
+ /**
+ * Dummy indicators for overloading the constructor
+ */
+ private static class Biff7 {};
+ public static Biff7 biff7 = new Biff7();
+
+ /**
+ * An XTI structure
+ */
+ private static class XTI
+ {
+ /**
+ * the supbook index
+ */
+ int supbookIndex;
+ /**
+ * the first tab
+ */
+ int firstTab;
+ /**
+ * the last tab
+ */
+ int lastTab;
+
+ /**
+ * Constructor
+ *
+ * @param s the supbook index
+ * @param f the first tab
+ * @param l the last tab
+ */
+ XTI(int s, int f, int l)
+ {
+ supbookIndex = s;
+ firstTab = f;
+ lastTab = l;
+ }
+ }
+
+ /**
+ * The array of XTI structures
+ */
+ private XTI[] xtiArray;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param ws the workbook settings
+ */
+ ExternalSheetRecord(Record t, WorkbookSettings ws)
+ {
+ super(t);
+ byte[] data = getRecord().getData();
+
+ int numxtis = IntegerHelper.getInt(data[0], data[1]);
+
+ if (data.length < numxtis * 6 + 2)
+ {
+ xtiArray = new XTI[0];
+ logger.warn("Could not process external sheets. Formulas may " +
+ "be compromised.");
+ return;
+ }
+
+ xtiArray = new XTI[numxtis];
+
+ int pos = 2;
+ for (int i = 0; i < numxtis; i++)
+ {
+ int s = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ int f = IntegerHelper.getInt(data[pos + 2], data[pos + 3]);
+ int l = IntegerHelper.getInt(data[pos + 4], data[pos + 5]);
+ xtiArray[i] = new XTI(s, f, l);
+ pos += 6;
+ }
+ }
+
+ /**
+ * Constructs this object from the raw data in biff 7 format.
+ * Does nothing here
+ *
+ * @param t the raw data
+ * @param settings the workbook settings
+ * @param dummy dummy override to identify biff7 funcionality
+ */
+ ExternalSheetRecord(Record t, WorkbookSettings settings, Biff7 dummy)
+ {
+ super(t);
+
+ logger.warn("External sheet record for Biff 7 not supported");
+ }
+
+ /**
+ * Accessor for the number of external sheet records
+ * @return the number of XTI records
+ */
+ public int getNumRecords()
+ {
+ return xtiArray != null ? xtiArray.length : 0;
+ }
+ /**
+ * Gets the supbook index for the specified external sheet
+ *
+ * @param index the index of the supbook record
+ * @return the supbook index
+ */
+ public int getSupbookIndex(int index)
+ {
+ return xtiArray[index].supbookIndex;
+ }
+
+ /**
+ * Gets the first tab index for the specified external sheet
+ *
+ * @param index the index of the supbook record
+ * @return the first tab index
+ */
+ public int getFirstTabIndex(int index)
+ {
+ return xtiArray[index].firstTab;
+ }
+
+ /**
+ * Gets the last tab index for the specified external sheet
+ *
+ * @param index the index of the supbook record
+ * @return the last tab index
+ */
+ public int getLastTabIndex(int index)
+ {
+ return xtiArray[index].lastTab;
+ }
+
+ /**
+ * Used when copying a workbook to access the raw external sheet data
+ *
+ * @return the raw external sheet data
+ */
+ public byte[] getData()
+ {
+ return getRecord().getData();
+ }
+}
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/File.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/File.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/File.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,328 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.BaseCompoundFile;
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+
+/**
+ * File containing the data from the binary stream
+ */
+public class File
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(File.class);
+
+ /**
+ * The data from the excel 97 file
+ */
+ private byte[] data;
+ /**
+ * The current position within the file
+ */
+ private int filePos;
+ /**
+ * The saved pos
+ */
+ private int oldPos;
+ /**
+ * The initial file size
+ */
+ private int initialFileSize;
+ /**
+ * The amount to increase the growable array by
+ */
+ private int arrayGrowSize;
+ /**
+ * A handle to the compound file. This is only preserved when the
+ * copying of PropertySets is enabled
+ */
+ private CompoundFile compoundFile;
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings workbookSettings;
+
+ /**
+ * Constructs a file from the input stream
+ *
+ * @param is the input stream
+ * @param ws the workbook settings
+ * @exception IOException
+ * @exception BiffException
+ */
+ public File(InputStream is, WorkbookSettings ws)
+ throws IOException, BiffException
+ {
+ // Initialize the file sizing parameters from the settings
+ workbookSettings = ws;
+ initialFileSize = workbookSettings.getInitialFileSize();
+ arrayGrowSize = workbookSettings.getArrayGrowSize();
+
+ byte[] d = new byte[initialFileSize];
+ int bytesRead = is.read(d);
+ int pos = bytesRead;
+
+ // Handle thread interruptions, in case the user keeps pressing
+ // the Submit button from a browser. Thanks to Mike Smith for this
+ if (Thread.currentThread().isInterrupted())
+ {
+ throw new InterruptedIOException();
+ }
+
+ while (bytesRead != -1)
+ {
+ if (pos >= d.length)
+ {
+ // Grow the array
+ byte[] newArray = new byte[d.length + arrayGrowSize];
+ System.arraycopy(d, 0, newArray, 0, d.length);
+ d = newArray;
+ }
+ bytesRead = is.read(d, pos, d.length - pos);
+ pos += bytesRead;
+
+ if (Thread.currentThread().isInterrupted())
+ {
+ throw new InterruptedIOException();
+ }
+ }
+
+ bytesRead = pos + 1;
+
+ // Perform file reading checks and throw exceptions as necessary
+ if (bytesRead == 0)
+ {
+ throw new BiffException(BiffException.excelFileNotFound);
+ }
+
+ CompoundFile cf = new CompoundFile(d, ws);
+ try
+ {
+ data = cf.getStream("workbook");
+ }
+ catch (BiffException e)
+ {
+ // this might be in excel 95 format - try again
+ data = cf.getStream("book");
+ }
+
+ if (!workbookSettings.getPropertySetsDisabled() &&
+ (cf.getNumberOfPropertySets() >
+ BaseCompoundFile.STANDARD_PROPERTY_SETS.length))
+ {
+ compoundFile = cf;
+ }
+
+ cf = null;
+
+ if (!workbookSettings.getGCDisabled())
+ {
+ System.gc();
+ }
+
+ // Uncomment the following lines to send the pure workbook stream
+ // (ie. a defragged ole stream) to an output file
+
+// FileOutputStream fos = new FileOutputStream("defraggedxls");
+// fos.write(data);
+// fos.close();
+
+ }
+
+ /**
+ * Constructs a file from already defragged binary data. Useful for
+ * displaying subportions of excel streams. This is only used during
+ * special runs of the "BiffDump" demo program and should not be invoked
+ * as part of standard JExcelApi parsing
+ *
+ * @param d the already parsed data
+ */
+ public File(byte[] d)
+ {
+ data = d;
+ }
+
+ /**
+ * Returns the next data record and increments the pointer
+ *
+ * @return the next data record
+ */
+ Record next()
+ {
+ Record r = new Record(data, filePos, this);
+ return r;
+ }
+
+ /**
+ * Peek ahead to the next record, without incrementing the file position
+ *
+ * @return the next record
+ */
+ Record peek()
+ {
+ int tempPos = filePos;
+ Record r = new Record(data, filePos, this);
+ filePos = tempPos;
+ return r;
+ }
+
+ /**
+ * Skips forward the specified number of bytes
+ *
+ * @param bytes the number of bytes to skip forward
+ */
+ public void skip(int bytes)
+ {
+ filePos += bytes;
+ }
+
+ /**
+ * Copies the bytes into a new array and returns it.
+ *
+ * @param pos the position to read from
+ * @param length the number of bytes to read
+ * @return The bytes read
+ */
+ public byte[] read(int pos, int length)
+ {
+ byte[] ret = new byte[length];
+ try
+ {
+ System.arraycopy(data, pos, ret, 0, length);
+ }
+ catch (ArrayIndexOutOfBoundsException e)
+ {
+ logger.error("Array index out of bounds at position " + pos +
+ " record length " + length);
+ throw e;
+ }
+ return ret;
+ }
+
+ /**
+ * Gets the position in the stream
+ *
+ * @return the position in the stream
+ */
+ public int getPos()
+ {
+ return filePos;
+ }
+
+ /**
+ * Saves the current position and temporarily sets the position to be the
+ * new one. The original position may be restored usind the restorePos()
+ * method. This is used when reading in the cell values of the sheet - an
+ * addition in 1.6 for memory allocation reasons.
+ *
+ * These methods are used by the SheetImpl.readSheet() when it is reading
+ * in all the cell values
+ *
+ * @param p the temporary position
+ */
+ public void setPos(int p)
+ {
+ oldPos = filePos;
+ filePos = p;
+ }
+
+ /**
+ * Restores the original position
+ *
+ * These methods are used by the SheetImpl.readSheet() when it is reading
+ * in all the cell values
+ */
+ public void restorePos()
+ {
+ filePos = oldPos;
+ }
+
+ /**
+ * Moves to the first bof in the file
+ */
+ private void moveToFirstBof()
+ {
+ boolean bofFound = false;
+ while (!bofFound)
+ {
+ int code = IntegerHelper.getInt(data[filePos], data[filePos + 1]);
+ if (code == Type.BOF.value)
+ {
+ bofFound = true;
+ }
+ else
+ {
+ skip(128);
+ }
+ }
+ }
+
+ /**
+ * "Closes" the biff file
+ *
+ * @deprecated As of version 1.6 use workbook.close() instead
+ */
+ public void close()
+ {
+ }
+
+ /**
+ * Clears the contents of the file
+ */
+ public void clear()
+ {
+ data = null;
+ }
+
+ /**
+ * Determines if the current position exceeds the end of the file
+ *
+ * @return TRUE if there is more data left in the array, FALSE otherwise
+ */
+ public boolean hasNext()
+ {
+ // Allow four bytes for the record code and its length
+ return filePos < data.length - 4;
+ }
+
+ /**
+ * Accessor for the compound file. The returned value will only be non-null
+ * if the property sets feature is enabled and the workbook contains
+ * additional property sets
+ *
+ * @return the compound file
+ */
+ CompoundFile getCompoundFile()
+ {
+ return compoundFile;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/FooterRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/FooterRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/FooterRecord.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,103 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.WorkbookSettings;
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+import jxl.biff.StringHelper;
+
+/**
+ * A workbook page footer record
+ */
+public class FooterRecord extends RecordData
+{
+ /**
+ * The footer
+ */
+ private String footer;
+
+ /**
+ * Dummy indicators for overloading the constructor
+ */
+ private static class Biff7 {};
+ public static Biff7 biff7 = new Biff7();
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the record data
+ * @param ws the workbook settings
+ */
+ FooterRecord(Record t, WorkbookSettings ws)
+ {
+ super(t);
+ byte[] data = getRecord().getData();
+
+ if (data.length == 0)
+ {
+ return;
+ }
+
+ int chars = IntegerHelper.getInt(data[0], data[1]);
+
+ boolean unicode = data[2] == 1;
+
+ if (unicode)
+ {
+ footer = StringHelper.getUnicodeString(data, chars, 3);
+ }
+ else
+ {
+ footer = StringHelper.getString(data, chars, 3, ws);
+ }
+ }
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the record data
+ * @param ws the workbook settings
+ * @param dummy dummy record to indicate a biff7 document
+ */
+ FooterRecord(Record t, WorkbookSettings ws, Biff7 dummy)
+ {
+ super(t);
+ byte[] data = getRecord().getData();
+
+ if (data.length == 0)
+ {
+ return;
+ }
+
+ int chars = data[0];
+ footer = StringHelper.getString(data, chars, 1, ws);
+ }
+
+ /**
+ * Gets the footer string
+ *
+ * @return the footer string
+ */
+ String getFooter()
+ {
+ return footer;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/Formula.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/Formula.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/Formula.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,37 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.Cell;
+
+/**
+ * Interface which is used for copying formulas from a read only
+ * to a writable spreadsheet
+ */
+public interface Formula extends Cell
+{
+ /**
+ * Gets the raw bytes for the formula. This will include the
+ * parsed tokens array
+ *
+ * @return the raw record data
+ */
+ public byte[] getFormulaData();
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/FormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/FormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/FormulaRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,278 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.CellType;
+import jxl.WorkbookSettings;
+import jxl.biff.DoubleHelper;
+import jxl.biff.FormattingRecords;
+import jxl.biff.IntegerHelper;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.formula.ExternalSheet;
+
+/**
+ * A formula's last calculated value
+ */
+class FormulaRecord extends CellValue
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(FormulaRecord.class);
+
+ /**
+ * The "real" formula record - will be either a string a or a number
+ */
+ private CellValue formula;
+
+ /**
+ * Flag to indicate whether this is a shared formula
+ */
+ private boolean shared;
+
+ /**
+ * Static class for a dummy override, indicating that the formula
+ * passed in is not a shared formula
+ */
+ private static class IgnoreSharedFormula {};
+ public static final IgnoreSharedFormula ignoreSharedFormula
+ = new IgnoreSharedFormula();
+
+ /**
+ * Constructs this object from the raw data. Creates either a
+ * NumberFormulaRecord or a StringFormulaRecord depending on whether
+ * this formula represents a numerical calculation or not
+ *
+ * @param t the raw data
+ * @param excelFile the excel file
+ * @param fr the formatting records
+ * @param es the workbook, which contains the external sheet references
+ * @param nt the name table
+ * @param si the sheet
+ * @param ws the workbook settings
+ */
+ public FormulaRecord(Record t,
+ File excelFile,
+ FormattingRecords fr,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ SheetImpl si,
+ WorkbookSettings ws)
+ {
+ super(t, fr, si);
+
+ byte[] data = getRecord().getData();
+
+ shared = false;
+
+ // Check to see if this forms part of a shared formula
+ int grbit = IntegerHelper.getInt(data[14], data[15]);
+ if ((grbit & 0x08) != 0)
+ {
+ shared = true;
+
+ if (data[6] == 0 && data[12] == -1 && data[13] == -1)
+ {
+ // It is a shared string formula
+ formula = new SharedStringFormulaRecord
+ (t, excelFile, fr, es, nt, si, ws);
+ }
+ else if (data[6] == 3 && data[12] == -1 && data[13] == -1)
+ {
+ // We have a string which evaluates to null
+ formula = new SharedStringFormulaRecord
+ (t, excelFile, fr, es, nt, si,
+ SharedStringFormulaRecord.EMPTY_STRING);
+ }
+ else if (data[6] == 2 &&
+ data[12] == -1 &&
+ data[13] == -1)
+ {
+ // The cell is in error
+ int errorCode = data[8];
+ formula = new SharedErrorFormulaRecord(t, excelFile, errorCode,
+ fr, es, nt, si);
+ }
+ else if (data[6] == 1 &&
+ data[12] == -1 &&
+ data[13] == -1)
+ {
+ boolean value = data[8] == 1 ? true : false;
+ formula = new SharedBooleanFormulaRecord
+ (t, excelFile, value, fr, es, nt, si);
+ }
+ else
+ {
+ // It is a numerical formula
+ double value = DoubleHelper.getIEEEDouble(data, 6);
+ SharedNumberFormulaRecord snfr = new SharedNumberFormulaRecord
+ (t, excelFile, value, fr, es, nt, si);
+ snfr.setNumberFormat(fr.getNumberFormat(getXFIndex()));
+ formula = snfr;
+ }
+
+ return;
+ }
+
+ // microsoft and their goddam magic values determine whether this
+ // is a string or a number value
+ if (data[6] == 0 && data[12] == -1 && data[13] == -1)
+ {
+ // we have a string
+ formula = new StringFormulaRecord(t, excelFile, fr, es, nt, si, ws);
+ }
+ else if (data[6] == 1 &&
+ data[12] == -1 &&
+ data[13] == -1)
+ {
+ // We have a boolean formula
+ // multiple values. Thanks to Frank for spotting this
+ formula = new BooleanFormulaRecord(t, fr, es, nt, si);
+ }
+ else if (data[6] == 2 &&
+ data[12] == -1 &&
+ data[13] == -1)
+ {
+ // The cell is in error
+ formula = new ErrorFormulaRecord(t, fr, es, nt, si);
+ }
+ else if (data[6] == 3 && data[12] == -1 && data[13] == -1)
+ {
+ // we have a string which evaluates to null
+ formula = new StringFormulaRecord(t, fr, es, nt, si);
+ }
+ else
+ {
+ // it is most assuredly a number
+ formula = new NumberFormulaRecord(t, fr, es, nt, si);
+ }
+ }
+
+ /**
+ * Constructs this object from the raw data. Creates either a
+ * NumberFormulaRecord or a StringFormulaRecord depending on whether
+ * this formula represents a numerical calculation or not
+ *
+ * @param t the raw data
+ * @param excelFile the excel file
+ * @param fr the formatting records
+ * @param es the workbook, which contains the external sheet references
+ * @param nt the name table
+ * @param i a dummy override to indicate that we don't want to do
+ * any shared formula processing
+ * @param si the sheet impl
+ * @param ws the workbook settings
+ */
+ public FormulaRecord(Record t,
+ File excelFile,
+ FormattingRecords fr,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ IgnoreSharedFormula i,
+ SheetImpl si,
+ WorkbookSettings ws)
+ {
+ super(t, fr, si);
+ byte[] data = getRecord().getData();
+
+ shared = false;
+
+ // microsoft and their magic values determine whether this
+ // is a string or a number value
+ if (data[6] == 0 && data[12] == -1 && data[13] == -1)
+ {
+ // we have a string
+ formula = new StringFormulaRecord(t, excelFile, fr, es, nt, si, ws);
+ }
+ else if (data[6] == 1 &&
+ data[12] == -1 &&
+ data[13] == -1)
+ {
+ // We have a boolean formula
+ // multiple values. Thanks to Frank for spotting this
+ formula = new BooleanFormulaRecord(t, fr, es, nt, si);
+ }
+ else if (data[6] == 2 &&
+ data[12] == -1 &&
+ data[13] == -1)
+ {
+ // The cell is in error
+ formula = new ErrorFormulaRecord(t, fr, es, nt, si);
+ }
+ else
+ {
+ // it is most assuredly a number
+ formula = new NumberFormulaRecord(t, fr, es, nt, si);
+ }
+ }
+
+ /**
+ * Returns the numerical value as a string
+ *
+ * @return The numerical value of the formula as a string
+ */
+ public String getContents()
+ {
+ Assert.verify(false);
+ return "";
+ }
+
+ /**
+ * Returns the cell type
+ *
+ * @return The cell type
+ */
+ public CellType getType()
+ {
+ Assert.verify(false);
+ return CellType.EMPTY;
+ }
+
+ /**
+ * Gets the "real" formula
+ *
+ * @return the cell value
+ */
+ final CellValue getFormula()
+ {
+ return formula;
+ }
+
+ /**
+ * Interrogates this formula to determine if it forms part of a shared
+ * formula
+ *
+ * @return TRUE if this is shared formula, FALSE otherwise
+ */
+ final boolean isShared()
+ {
+ return shared;
+ }
+
+}
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/GuttersRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/GuttersRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/GuttersRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,61 @@
+/*********************************************************************
+*
+* Copyright (C) 2007 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * The gutters record
+ */
+public class GuttersRecord extends RecordData
+{
+ private int width;
+ private int height;
+ private int rowOutlineLevel;
+ private int columnOutlineLevel;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param r the raw data
+ */
+ public GuttersRecord(Record r)
+ {
+ super(r);
+
+ byte[] data = getRecord().getData();
+ width = IntegerHelper.getInt(data[0], data[1]);
+ height = IntegerHelper.getInt(data[2], data[3]);
+ rowOutlineLevel = IntegerHelper.getInt(data[4], data[5]);
+ columnOutlineLevel = IntegerHelper.getInt(data[6], data[7]);
+ }
+
+ int getRowOutlineLevel()
+ {
+ return rowOutlineLevel;
+ }
+
+ int getColumnOutlineLevel()
+ {
+ return columnOutlineLevel;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/HeaderRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/HeaderRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/HeaderRecord.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,110 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+import jxl.biff.StringHelper;
+
+/**
+ * A workbook page header record
+ */
+public class HeaderRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(HeaderRecord.class);
+
+ /**
+ * The footer
+ */
+ private String header;
+
+ /**
+ * Dummy indicators for overloading the constructor
+ */
+ private static class Biff7 {};
+ public static Biff7 biff7 = new Biff7();
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the record data
+ * @param ws the workbook settings
+ */
+ HeaderRecord(Record t, WorkbookSettings ws)
+ {
+ super(t);
+ byte[] data = getRecord().getData();
+
+ if (data.length == 0)
+ {
+ return;
+ }
+
+ int chars = IntegerHelper.getInt(data[0], data[1]);
+
+ boolean unicode = data[2] == 1;
+
+ if (unicode)
+ {
+ header = StringHelper.getUnicodeString(data, chars, 3);
+ }
+ else
+ {
+ header = StringHelper.getString(data, chars, 3, ws);
+ }
+ }
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the record data
+ * @param ws the workbook settings
+ * @param dummy dummy record to indicate a biff7 document
+ */
+ HeaderRecord(Record t, WorkbookSettings ws, Biff7 dummy)
+ {
+ super(t);
+ byte[] data = getRecord().getData();
+
+ if (data.length == 0)
+ {
+ return;
+ }
+
+ int chars = data[0];
+ header = StringHelper.getString(data, chars, 1, ws);
+ }
+
+ /**
+ * Gets the header string
+ *
+ * @return the header string
+ */
+ String getHeader()
+ {
+ return header;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/HorizontalPageBreaksRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/HorizontalPageBreaksRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/HorizontalPageBreaksRecord.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,108 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * Contains the cell dimensions of this worksheet
+ */
+class HorizontalPageBreaksRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private final Logger logger = Logger.getLogger
+ (HorizontalPageBreaksRecord.class);
+
+ /**
+ * The row page breaks
+ */
+ private int[] rowBreaks;
+
+ /**
+ * Dummy indicators for overloading the constructor
+ */
+ private static class Biff7 {};
+ public static Biff7 biff7 = new Biff7();
+
+ /**
+ * Constructs the dimensions from the raw data
+ *
+ * @param t the raw data
+ */
+ public HorizontalPageBreaksRecord(Record t)
+ {
+ super(t);
+
+ byte[] data = t.getData();
+
+ int numbreaks = IntegerHelper.getInt(data[0], data[1]);
+ int pos = 2;
+ rowBreaks = new int[numbreaks];
+
+ for (int i = 0; i < numbreaks; i++)
+ {
+ rowBreaks[i] = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ pos += 6;
+ }
+ }
+
+ /**
+ * Constructs the dimensions from the raw data
+ *
+ * @param t the raw data
+ * @param biff7 an indicator to initialise this record for biff 7 format
+ */
+ public HorizontalPageBreaksRecord(Record t, Biff7 biff7)
+ {
+ super(t);
+
+ byte[] data = t.getData();
+ int numbreaks = IntegerHelper.getInt(data[0], data[1]);
+ int pos = 2;
+ rowBreaks = new int[numbreaks];
+ for (int i = 0; i < numbreaks; i++)
+ {
+ rowBreaks[i] = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ pos += 2;
+ }
+ }
+
+ /**
+ * Gets the row breaks
+ *
+ * @return the row breaks on the current sheet
+ */
+ public int[] getRowBreaks()
+ {
+ return rowBreaks;
+ }
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/HyperlinkRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/HyperlinkRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/HyperlinkRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,417 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import common.Logger;
+
+import jxl.CellReferenceHelper;
+import jxl.Hyperlink;
+import jxl.Range;
+import jxl.Sheet;
+import jxl.WorkbookSettings;
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+import jxl.biff.SheetRangeImpl;
+import jxl.biff.StringHelper;
+
+/**
+ * A number record. This is stored as 8 bytes, as opposed to the
+ * 4 byte RK record
+ */
+public class HyperlinkRecord extends RecordData implements Hyperlink
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(HyperlinkRecord.class);
+
+ /**
+ * The first row
+ */
+ private int firstRow;
+ /**
+ * The last row
+ */
+ private int lastRow;
+ /**
+ * The first column
+ */
+ private int firstColumn;
+ /**
+ * The last column
+ */
+ private int lastColumn;
+
+ /**
+ * The URL referred to by this hyperlink
+ */
+ private URL url;
+
+ /**
+ * The local file referred to by this hyperlink
+ */
+ private File file;
+
+ /**
+ * The location in this workbook referred to by this hyperlink
+ */
+ private String location;
+
+ /**
+ * The range of cells which activate this hyperlink
+ */
+ private SheetRangeImpl range;
+
+ /**
+ * The type of this hyperlink
+ */
+ private LinkType linkType;
+
+ /**
+ * The excel type of hyperlink
+ */
+ private static class LinkType {};
+
+ private static final LinkType urlLink = new LinkType();
+ private static final LinkType fileLink = new LinkType();
+ private static final LinkType workbookLink = new LinkType();
+ private static final LinkType unknown = new LinkType();
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param s the sheet
+ * @param ws the workbook settings
+ */
+ HyperlinkRecord(Record t, Sheet s, WorkbookSettings ws)
+ {
+ super(t);
+
+ linkType = unknown;
+
+ byte[] data = getRecord().getData();
+
+ // Build up the range of cells occupied by this hyperlink
+ firstRow = IntegerHelper.getInt(data[0], data[1]);
+ lastRow = IntegerHelper.getInt(data[2], data[3]);
+ firstColumn = IntegerHelper.getInt(data[4], data[5]);
+ lastColumn = IntegerHelper.getInt(data[6], data[7]);
+ range = new SheetRangeImpl(s,
+ firstColumn, firstRow,
+ lastColumn, lastRow);
+
+ int options = IntegerHelper.getInt(data[28], data[29], data[30], data[31]);
+
+ boolean description = (options & 0x14) != 0;
+ int startpos = 32;
+ int descbytes = 0;
+ if (description)
+ {
+ int descchars = IntegerHelper.getInt
+ (data[startpos], data[startpos + 1],
+ data[startpos + 2], data[startpos + 3]);
+ descbytes = descchars * 2 + 4;
+ }
+
+ startpos += descbytes;
+
+ boolean targetFrame = (options & 0x80) != 0;
+ int targetbytes = 0;
+ if (targetFrame)
+ {
+ int targetchars = IntegerHelper.getInt
+ (data[startpos], data[startpos + 1],
+ data[startpos + 2], data[startpos + 3]);
+ targetbytes = targetchars * 2 + 4;
+ }
+
+ startpos += targetbytes;
+
+ // Try and determine the type
+ if ((options & 0x3) == 0x03)
+ {
+ linkType = urlLink;
+
+ // check the guid monicker
+ if (data[startpos] == 0x03)
+ {
+ linkType = fileLink;
+ }
+ }
+ else if ((options & 0x01) != 0)
+ {
+ linkType = fileLink;
+ // check the guid monicker
+ if (data[startpos] == (byte) 0xe0)
+ {
+ linkType = urlLink;
+ }
+ }
+ else if ((options & 0x08) != 0)
+ {
+ linkType = workbookLink;
+ }
+
+ // Try and determine the type
+ if (linkType == urlLink)
+ {
+ String urlString = null;
+ try
+ {
+ startpos += 16;
+
+ // Get the url, ignoring the 0 char at the end
+ int bytes = IntegerHelper.getInt(data[startpos],
+ data[startpos + 1],
+ data[startpos + 2],
+ data[startpos + 3]);
+
+ urlString = StringHelper.getUnicodeString(data, bytes / 2 - 1,
+ startpos + 4);
+ url = new URL(urlString);
+ }
+ catch (MalformedURLException e)
+ {
+ logger.warn("URL " + urlString + " is malformed. Trying a file");
+ try
+ {
+ linkType = fileLink;
+ file = new File(urlString);
+ }
+ catch (Exception e3)
+ {
+ logger.warn("Cannot set to file. Setting a default URL");
+
+ // Set a default URL
+ try
+ {
+ linkType = urlLink;
+ url = new URL("http://www.andykhan.com/jexcelapi/index.html");
+ }
+ catch (MalformedURLException e2)
+ {
+ // fail silently
+ }
+ }
+ }
+ catch (Throwable e)
+ {
+ StringBuffer sb1 = new StringBuffer();
+ StringBuffer sb2 = new StringBuffer();
+ CellReferenceHelper.getCellReference(firstColumn, firstRow, sb1);
+ CellReferenceHelper.getCellReference(lastColumn, lastRow, sb2);
+ sb1.insert(0, "Exception when parsing URL ");
+ sb1.append('\"').append(sb2.toString()).append("\". Using default.");
+ logger.warn(sb1, e);
+
+ // Set a default URL
+ try
+ {
+ url = new URL("http://www.andykhan.com/jexcelapi/index.html");
+ }
+ catch (MalformedURLException e2)
+ {
+ // fail silently
+ }
+ }
+ }
+ else if (linkType == fileLink)
+ {
+ try
+ {
+ startpos += 16;
+
+ // Get the name of the local file, ignoring the zero character at the
+ // end
+ int upLevelCount = IntegerHelper.getInt(data[startpos],
+ data[startpos + 1]);
+ int chars = IntegerHelper.getInt(data[startpos + 2],
+ data[startpos + 3],
+ data[startpos + 4],
+ data[startpos + 5]);
+ String fileName = StringHelper.getString(data, chars - 1,
+ startpos + 6, ws);
+
+ StringBuffer sb = new StringBuffer();
+
+ for (int i = 0; i < upLevelCount; i++)
+ {
+ sb.append("..\\");
+ }
+
+ sb.append(fileName);
+
+ file = new File(sb.toString());
+ }
+ catch (Throwable e)
+ {
+ e.printStackTrace();
+ logger.warn("Exception when parsing file " +
+ e.getClass().getName() + ".");
+ file = new File(".");
+ }
+ }
+ else if (linkType == workbookLink)
+ {
+ int chars = IntegerHelper.getInt(data[32], data[33], data[34], data[35]);
+ location = StringHelper.getUnicodeString(data, chars - 1, 36);
+ }
+ else
+ {
+ // give up
+ logger.warn("Cannot determine link type");
+ return;
+ }
+ }
+
+ /**
+ * Determines whether this is a hyperlink to a file
+ *
+ * @return TRUE if this is a hyperlink to a file, FALSE otherwise
+ */
+ public boolean isFile()
+ {
+ return linkType == fileLink;
+ }
+
+ /**
+ * Determines whether this is a hyperlink to a web resource
+ *
+ * @return TRUE if this is a URL
+ */
+ public boolean isURL()
+ {
+ return linkType == urlLink;
+ }
+
+ /**
+ * Determines whether this is a hyperlink to a location in this workbook
+ *
+ * @return TRUE if this is a link to an internal location
+ */
+ public boolean isLocation()
+ {
+ return linkType == workbookLink;
+ }
+
+ /**
+ * Returns the row number of the top left cell
+ *
+ * @return the row number of this cell
+ */
+ public int getRow()
+ {
+ return firstRow;
+ }
+
+ /**
+ * Returns the column number of the top left cell
+ *
+ * @return the column number of this cell
+ */
+ public int getColumn()
+ {
+ return firstColumn;
+ }
+
+ /**
+ * Returns the row number of the bottom right cell
+ *
+ * @return the row number of this cell
+ */
+ public int getLastRow()
+ {
+ return lastRow;
+ }
+
+ /**
+ * Returns the column number of the bottom right cell
+ *
+ * @return the column number of this cell
+ */
+ public int getLastColumn()
+ {
+ return lastColumn;
+ }
+
+ /**
+ * Gets the URL referenced by this Hyperlink
+ *
+ * @return the URL, or NULL if this hyperlink is not a URL
+ */
+ public URL getURL()
+ {
+ return url;
+ }
+
+ /**
+ * Returns the local file eferenced by this Hyperlink
+ *
+ * @return the file, or NULL if this hyperlink is not a file
+ */
+ public File getFile()
+ {
+ return file;
+ }
+
+ /**
+ * Exposes the base class method. This is used when copying hyperlinks
+ *
+ * @return the Record data
+ */
+ public Record getRecord()
+ {
+ return super.getRecord();
+ }
+
+ /**
+ * Gets the range of cells which activate this hyperlink
+ * The get sheet index methods will all return -1, because the
+ * cells will all be present on the same sheet
+ *
+ * @return the range of cells which activate the hyperlink
+ */
+ public Range getRange()
+ {
+ return range;
+ }
+
+ /**
+ * Gets the location referenced by this hyperlink
+ *
+ * @return the location
+ */
+ public String getLocation()
+ {
+ return location;
+ }
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/LabelRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/LabelRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/LabelRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,123 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.CellType;
+import jxl.LabelCell;
+import jxl.WorkbookSettings;
+import jxl.biff.FormattingRecords;
+import jxl.biff.IntegerHelper;
+import jxl.biff.StringHelper;
+
+/**
+ * A label which is stored in the cell
+ */
+class LabelRecord extends CellValue implements LabelCell
+{
+ /**
+ * The length of the label in characters
+ */
+ private int length;
+
+ /**
+ * The label
+ */
+ private String string;
+
+ /**
+ * Dummy indicators for overloading the constructor
+ */
+ private static class Biff7 {};
+ public static Biff7 biff7 = new Biff7();
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param fr the formatting records
+ * @param si the sheet
+ * @param ws the workbook settings
+ */
+ public LabelRecord(Record t, FormattingRecords fr,
+ SheetImpl si, WorkbookSettings ws)
+ {
+ super(t, fr, si);
+ byte[] data = getRecord().getData();
+ length = IntegerHelper.getInt(data[6], data[7]);
+
+ if (data[8] == 0x0)
+ {
+ string = StringHelper.getString(data, length, 9, ws);
+ }
+ else
+ {
+ string = StringHelper.getUnicodeString(data, length, 9);
+ }
+ }
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param fr the formatting records
+ * @param si the sheet
+ * @param ws the workbook settings
+ * @param dummy dummy overload to indicate a biff 7 workbook
+ */
+ public LabelRecord(Record t, FormattingRecords fr, SheetImpl si,
+ WorkbookSettings ws, Biff7 dummy)
+ {
+ super(t, fr, si);
+ byte[] data = getRecord().getData();
+ length = IntegerHelper.getInt(data[6], data[7]);
+
+ string = StringHelper.getString(data, length, 8, ws);
+ }
+
+ /**
+ * Gets the label
+ *
+ * @return the label
+ */
+ public String getString()
+ {
+ return string;
+ }
+
+ /**
+ * Gets the cell contents as a string
+ *
+ * @return the label
+ */
+ public String getContents()
+ {
+ return string;
+ }
+
+ /**
+ * Accessor for the cell type
+ *
+ * @return the cell type
+ */
+ public CellType getType()
+ {
+ return CellType.LABEL;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/LabelSSTRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/LabelSSTRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/LabelSSTRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,88 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.CellType;
+import jxl.LabelCell;
+import jxl.biff.FormattingRecords;
+import jxl.biff.IntegerHelper;
+
+/**
+ * A label which is stored in the shared string table
+ */
+class LabelSSTRecord extends CellValue implements LabelCell
+{
+ /**
+ * The index into the shared string table
+ */
+ private int index;
+ /**
+ * The label
+ */
+ private String string;
+
+ /**
+ * Constructor. Retrieves the index from the raw data and looks it up
+ * in the shared string table
+ *
+ * @param stringTable the shared string table
+ * @param t the raw data
+ * @param fr the formatting records
+ * @param si the sheet
+ */
+ public LabelSSTRecord(Record t, SSTRecord stringTable, FormattingRecords fr,
+ SheetImpl si)
+ {
+ super(t, fr, si);
+ byte[] data = getRecord().getData();
+ index = IntegerHelper.getInt(data[6], data[7], data[8], data[9]);
+ string = stringTable.getString(index);
+ }
+
+ /**
+ * Gets the label
+ *
+ * @return the label
+ */
+ public String getString()
+ {
+ return string;
+ }
+
+ /**
+ * Gets this cell's contents as a string
+ *
+ * @return the label
+ */
+ public String getContents()
+ {
+ return string;
+ }
+
+ /**
+ * Returns the cell type
+ *
+ * @return the cell type
+ */
+ public CellType getType()
+ {
+ return CellType.LABEL;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/LeftMarginRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/LeftMarginRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/LeftMarginRecord.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,38 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.Type;
+
+/**
+ * Record for the left margin settings
+ */
+class LeftMarginRecord extends MarginRecord
+{
+ /**
+ * Constructor
+ *
+ * @param r the raw record
+ */
+ LeftMarginRecord(Record r)
+ {
+ super(Type.LEFTMARGIN, r);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/MarginRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/MarginRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/MarginRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,61 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.DoubleHelper;
+import jxl.biff.RecordData;
+import jxl.biff.Type;
+
+/**
+ * Abstract class containing the margin value for top,left,right and bottom
+ * margins
+ */
+abstract class MarginRecord extends RecordData
+{
+ /**
+ * The size of the margin
+ */
+ private double margin;
+
+ /**
+ * Constructs this record from the raw data
+ *
+ * @param t the type
+ * @param r the record
+ */
+ protected MarginRecord(Type t, Record r)
+ {
+ super(t);
+
+ byte[] data = r.getData();
+
+ margin = DoubleHelper.getIEEEDouble(data, 0);
+ }
+
+ /**
+ * Accessor for the margin
+ *
+ * @return the margin
+ */
+ double getMargin()
+ {
+ return margin;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/MergedCellsRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/MergedCellsRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/MergedCellsRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,90 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.Range;
+import jxl.Sheet;
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+import jxl.biff.SheetRangeImpl;
+
+/**
+ * A merged cells record for a given sheet
+ */
+public class MergedCellsRecord extends RecordData
+{
+ /**
+ * The ranges of the cells merged on this sheet
+ */
+ private Range[] ranges;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param s the sheet
+ */
+ MergedCellsRecord(Record t, Sheet s)
+ {
+ super(t);
+
+ byte[] data = getRecord().getData();
+
+ int numRanges = IntegerHelper.getInt(data[0], data[1]);
+
+ ranges = new Range[numRanges];
+
+ int pos = 2;
+ int firstRow = 0;
+ int lastRow = 0;
+ int firstCol = 0;
+ int lastCol = 0;
+
+ for (int i = 0; i < numRanges; i++)
+ {
+ firstRow = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ lastRow = IntegerHelper.getInt(data[pos + 2], data[pos + 3]);
+ firstCol = IntegerHelper.getInt(data[pos + 4], data[pos + 5]);
+ lastCol = IntegerHelper.getInt(data[pos + 6], data[pos + 7]);
+
+ ranges[i] = new SheetRangeImpl(s, firstCol, firstRow,
+ lastCol, lastRow);
+
+ pos += 8;
+ }
+ }
+
+ /**
+ * Gets the ranges which have been merged in this sheet
+ *
+ * @return the ranges of cells which have been merged
+ */
+ public Range[] getRanges()
+ {
+ return ranges;
+ }
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/MulBlankCell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/MulBlankCell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/MulBlankCell.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,207 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.Cell;
+import jxl.CellFeatures;
+import jxl.CellType;
+import jxl.biff.FormattingRecords;
+import jxl.format.CellFormat;
+
+/**
+ * A blank cell value, initialized indirectly from a multiple biff record
+ * rather than directly from the binary data
+ */
+class MulBlankCell implements Cell, CellFeaturesAccessor
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(MulBlankCell.class);
+
+ /**
+ * The row containing this blank
+ */
+ private int row;
+ /**
+ * The column containing this blank
+ */
+ private int column;
+ /**
+ * The raw cell format
+ */
+ private CellFormat cellFormat;
+
+ /**
+ * The index to the XF Record
+ */
+ private int xfIndex;
+
+ /**
+ * A handle to the formatting records
+ */
+ private FormattingRecords formattingRecords;
+
+ /**
+ * A flag to indicate whether this object's formatting things have
+ * been initialized
+ */
+ private boolean initialized;
+
+ /**
+ * A handle to the sheet
+ */
+ private SheetImpl sheet;
+
+ /**
+ * The cell features
+ */
+ private CellFeatures features;
+
+
+ /**
+ * Constructs this cell
+ *
+ * @param r the zero based row
+ * @param c the zero base column
+ * @param xfi the xf index
+ * @param fr the formatting records
+ * @param si the sheet
+ */
+ public MulBlankCell(int r, int c,
+ int xfi,
+ FormattingRecords fr,
+ SheetImpl si)
+ {
+ row = r;
+ column = c;
+ xfIndex = xfi;
+ formattingRecords = fr;
+ sheet = si;
+ initialized = false;
+ }
+
+ /**
+ * Accessor for the row
+ *
+ * @return the zero based row
+ */
+ public final int getRow()
+ {
+ return row;
+ }
+
+ /**
+ * Accessor for the column
+ *
+ * @return the zero based column
+ */
+ public final int getColumn()
+ {
+ return column;
+ }
+
+ /**
+ * Accessor for the contents as a string
+ *
+ * @return the value as a string
+ */
+ public String getContents()
+ {
+ return "";
+ }
+
+ /**
+ * Accessor for the cell type
+ *
+ * @return the cell type
+ */
+ public CellType getType()
+ {
+ return CellType.EMPTY;
+ }
+
+ /**
+ * Gets the cell format for this cell
+ *
+ * @return the cell format for these cells
+ */
+ public CellFormat getCellFormat()
+ {
+ if (!initialized)
+ {
+ cellFormat = formattingRecords.getXFRecord(xfIndex);
+ initialized = true;
+ }
+
+ return cellFormat;
+ }
+
+ /**
+ * Determines whether or not this cell has been hidden
+ *
+ * @return TRUE if this cell has been hidden, FALSE otherwise
+ */
+ public boolean isHidden()
+ {
+ ColumnInfoRecord cir = sheet.getColumnInfo(column);
+
+ if (cir != null && cir.getWidth() == 0)
+ {
+ return true;
+ }
+
+ RowRecord rr = sheet.getRowInfo(row);
+
+ if (rr != null && (rr.getRowHeight() == 0 || rr.isCollapsed()))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Accessor for the cell features
+ *
+ * @return the cell features or NULL if this cell doesn't have any
+ */
+ public CellFeatures getCellFeatures()
+ {
+ return features;
+ }
+
+ /**
+ * Sets the cell features during the reading process
+ *
+ * @param cf the cell features
+ */
+ public void setCellFeatures(CellFeatures cf)
+ {
+ if (features != null)
+ {
+ logger.warn("current cell features not null - overwriting");
+ }
+
+ features = cf;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/MulBlankRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/MulBlankRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/MulBlankRecord.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,135 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * Contains an array of Blank, formatted cells
+ */
+class MulBlankRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(MulBlankRecord.class);
+
+ /**
+ * The row containing these numbers
+ */
+ private int row;
+ /**
+ * The first column these rk number occur on
+ */
+ private int colFirst;
+ /**
+ * The last column these blank numbers occur on
+ */
+ private int colLast;
+ /**
+ * The number of blank numbers contained in this record
+ */
+ private int numblanks;
+ /**
+ * The array of xf indices
+ */
+ private int[] xfIndices;
+
+ /**
+ * Constructs the blank records from the raw data
+ *
+ * @param t the raw data
+ */
+ public MulBlankRecord(Record t)
+ {
+ super(t);
+ byte[] data = getRecord().getData();
+ int length = getRecord().getLength();
+ row = IntegerHelper.getInt(data[0], data[1]);
+ colFirst = IntegerHelper.getInt(data[2], data[3]);
+ colLast = IntegerHelper.getInt(data[length - 2], data[length - 1]);
+ numblanks = colLast - colFirst + 1;
+ xfIndices = new int[numblanks];
+
+ readBlanks(data);
+ }
+
+ /**
+ * Reads the blanks from the raw data
+ *
+ * @param data the raw data
+ */
+ private void readBlanks(byte[] data)
+ {
+ int pos = 4;
+ for (int i = 0; i < numblanks; i++)
+ {
+ xfIndices[i] = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ pos += 2;
+ }
+ }
+
+ /**
+ * Accessor for the row
+ *
+ * @return the row of containing these blank numbers
+ */
+ public int getRow()
+ {
+ return row;
+ }
+
+ /**
+ * The first column containing the blank numbers
+ *
+ * @return the first column
+ */
+ public int getFirstColumn()
+ {
+ return colFirst;
+ }
+
+ /**
+ * Accessor for the number of blank values
+ *
+ * @return the number of blank values
+ */
+ public int getNumberOfColumns()
+ {
+ return numblanks;
+ }
+
+ /**
+ * Return a specific formatting index
+ * @param index the cell index in the group
+ * @return the formatting index
+ */
+ public int getXFIndex(int index)
+ {
+ return xfIndices[index];
+ }
+}
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/MulRKRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/MulRKRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/MulRKRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,156 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * Contains an array of RK numbers
+ */
+class MulRKRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(MulRKRecord.class);
+
+ /**
+ * The row containing these numbers
+ */
+ private int row;
+ /**
+ * The first column these rk number occur on
+ */
+ private int colFirst;
+ /**
+ * The last column these rk numbers occur on
+ */
+ private int colLast;
+ /**
+ * The number of rk numbers contained in this record
+ */
+ private int numrks;
+ /**
+ * The array of rk numbers
+ */
+ private int[] rknumbers;
+ /**
+ * The array of xf indices
+ */
+ private int[] xfIndices;
+
+ /**
+ * Constructs the rk numbers from the raw data
+ *
+ * @param t the raw data
+ */
+ public MulRKRecord(Record t)
+ {
+ super(t);
+ byte[] data = getRecord().getData();
+ int length = getRecord().getLength();
+ row = IntegerHelper.getInt(data[0], data[1]);
+ colFirst = IntegerHelper.getInt(data[2], data[3]);
+ colLast = IntegerHelper.getInt(data[length - 2], data[length - 1]);
+ numrks = colLast - colFirst + 1;
+ rknumbers = new int[numrks];
+ xfIndices = new int[numrks];
+
+ readRks(data);
+ }
+
+ /**
+ * Reads the rks from the raw data
+ *
+ * @param data the raw data
+ */
+ private void readRks(byte[] data)
+ {
+ int pos = 4;
+ int rk;
+ for (int i = 0; i < numrks; i++)
+ {
+ xfIndices[i] = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ rk = IntegerHelper.getInt
+ (data[pos + 2], data[pos + 3], data[pos + 4], data[pos + 5]);
+ rknumbers[i] = rk;
+ pos += 6;
+ }
+ }
+
+ /**
+ * Accessor for the row
+ *
+ * @return the row of containing these rk numbers
+ */
+ public int getRow()
+ {
+ return row;
+ }
+
+ /**
+ * The first column containing the rk numbers
+ *
+ * @return the first column
+ */
+ public int getFirstColumn()
+ {
+ return colFirst;
+ }
+
+ /**
+ * Accessor for the number of rk values
+ *
+ * @return the number of rk values
+ */
+ public int getNumberOfColumns()
+ {
+ return numrks;
+ }
+
+ /**
+ * Returns a specific rk number
+ *
+ * @param index the rk number to return
+ * @return the rk number in bits
+ */
+ public int getRKNumber(int index)
+ {
+ return rknumbers[index];
+ }
+
+ /**
+ * Return a specific formatting index
+ *
+ * @param index the index of the cell in this group
+ * @return the xf index
+ */
+ public int getXFIndex(int index)
+ {
+ return xfIndices[index];
+ }
+}
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/NameRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/NameRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/NameRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,580 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.util.ArrayList;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.BuiltInName;
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+import jxl.biff.StringHelper;
+
+/**
+ * Holds an excel name record, and the details of the cells/ranges it refers
+ * to
+ */
+public class NameRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(NameRecord.class);
+
+ /**
+ * The name
+ */
+ private String name;
+
+ /**
+ * The built in name
+ */
+ private BuiltInName builtInName;
+
+ /**
+ * The 0-based index in the name table
+ */
+ private int index;
+
+ /**
+ * The 0-based index sheet reference for a record name
+ * 0 is for a global reference
+ */
+ private int sheetRef = 0;
+
+ /**
+ * Indicates whether this is a biff8 name record. Used during copying
+ */
+ private boolean isbiff8;
+
+ /**
+ * Dummy indicators for overloading the constructor
+ */
+ private static class Biff7 {};
+ public static Biff7 biff7 = new Biff7();
+
+ // Constants which refer to the name type
+ private static final int commandMacro = 0xc;
+ private static final int builtIn = 0x20;
+
+ // Constants which refer to the parse tokens after the string
+ private static final int cellReference = 0x3a;
+ private static final int areaReference = 0x3b;
+ private static final int subExpression = 0x29;
+ private static final int union = 0x10;
+
+ /**
+ * A nested class to hold range information
+ */
+ public class NameRange
+ {
+ /**
+ * The first column
+ */
+ private int columnFirst;
+
+ /**
+ * The first row
+ */
+ private int rowFirst;
+
+ /**
+ * The last column
+ */
+ private int columnLast;
+
+ /**
+ * The last row
+ */
+ private int rowLast;
+
+ /**
+ * The first sheet
+ */
+ private int externalSheet;
+
+ /**
+ * Constructor
+ *
+ * @param s1 the sheet
+ * @param c1 the first column
+ * @param r1 the first row
+ * @param c2 the last column
+ * @param r2 the last row
+ */
+ NameRange(int s1, int c1, int r1, int c2, int r2)
+ {
+ columnFirst = c1;
+ rowFirst = r1;
+ columnLast = c2;
+ rowLast = r2;
+ externalSheet = s1;
+ }
+
+ /**
+ * Accessor for the first column
+ *
+ * @return the index of the first column
+ */
+ public int getFirstColumn()
+ {
+ return columnFirst;
+ }
+
+ /**
+ * Accessor for the first row
+ *
+ * @return the index of the first row
+ */
+ public int getFirstRow()
+ {
+ return rowFirst;
+ }
+
+ /**
+ * Accessor for the last column
+ *
+ * @return the index of the last column
+ */
+ public int getLastColumn()
+ {
+ return columnLast;
+ }
+
+ /**
+ * Accessor for the last row
+ *
+ * @return the index of the last row
+ */
+ public int getLastRow()
+ {
+ return rowLast;
+ }
+
+ /**
+ * Accessor for the first sheet
+ *
+ * @return the index of the external sheet
+ */
+ public int getExternalSheet()
+ {
+ return externalSheet;
+ }
+ }
+
+ /**
+ * The ranges referenced by this name
+ */
+ private ArrayList ranges;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param ws the workbook settings
+ * @param ind the index in the name table
+ */
+ NameRecord(Record t, WorkbookSettings ws, int ind)
+ {
+ super(t);
+ index = ind;
+ isbiff8 = true;
+
+ try
+ {
+ ranges = new ArrayList();
+
+ byte[] data = getRecord().getData();
+ int option = IntegerHelper.getInt(data[0], data[1]);
+ int length = data[3];
+ sheetRef = IntegerHelper.getInt(data[8],data[9]);
+
+ if ((option & builtIn) != 0)
+ {
+ builtInName = BuiltInName.getBuiltInName(data[15]);
+ }
+ else
+ {
+ name = StringHelper.getString(data, length, 15, ws);
+ }
+
+ if ((option & commandMacro) != 0)
+ {
+ // This is a command macro, so it has no cell references
+ return;
+ }
+
+ int pos = length + 15;
+
+ if (data[pos] == cellReference)
+ {
+ int sheet = IntegerHelper.getInt(data[pos + 1], data[pos + 2]);
+ int row = IntegerHelper.getInt(data[pos + 3], data[pos + 4]);
+ int columnMask = IntegerHelper.getInt(data[pos + 5], data[pos + 6]);
+ int column = columnMask & 0xff;
+
+ // Check that we are not dealing with offsets
+ Assert.verify((columnMask & 0xc0000) == 0);
+
+ NameRange r = new NameRange(sheet, column, row, column, row);
+ ranges.add(r);
+ }
+ else if (data[pos] == areaReference)
+ {
+ int sheet1 = 0;
+ int r1 = 0;
+ int columnMask = 0;
+ int c1 = 0;
+ int r2 = 0;
+ int c2 = 0;
+ NameRange range = null;
+
+ while (pos < data.length)
+ {
+ sheet1 = IntegerHelper.getInt(data[pos + 1], data[pos + 2]);
+ r1 = IntegerHelper.getInt(data[pos + 3], data[pos + 4]);
+ r2 = IntegerHelper.getInt(data[pos + 5], data[pos + 6]);
+
+ columnMask = IntegerHelper.getInt(data[pos + 7], data[pos + 8]);
+ c1 = columnMask & 0xff;
+
+ // Check that we are not dealing with offsets
+ Assert.verify((columnMask & 0xc0000) == 0);
+
+ columnMask = IntegerHelper.getInt(data[pos + 9], data[pos + 10]);
+ c2 = columnMask & 0xff;
+
+ // Check that we are not dealing with offsets
+ Assert.verify((columnMask & 0xc0000) == 0);
+
+ range = new NameRange(sheet1, c1, r1, c2, r2);
+ ranges.add(range);
+
+ pos += 11;
+ }
+ }
+ else if (data[pos] == subExpression)
+ {
+ int sheet1 = 0;
+ int r1 = 0;
+ int columnMask = 0;
+ int c1 = 0;
+ int r2 = 0;
+ int c2 = 0;
+ NameRange range = null;
+
+ // Consume unnecessary parsed tokens
+ if (pos < data.length &&
+ data[pos] != cellReference &&
+ data[pos] != areaReference)
+ {
+ if (data[pos] == subExpression)
+ {
+ pos += 3;
+ }
+ else if (data[pos] == union)
+ {
+ pos += 1;
+ }
+ }
+
+ while (pos < data.length)
+ {
+ sheet1 = IntegerHelper.getInt(data[pos + 1], data[pos + 2]);
+ r1 = IntegerHelper.getInt(data[pos + 3], data[pos + 4]);
+ r2 = IntegerHelper.getInt(data[pos + 5], data[pos + 6]);
+
+ columnMask = IntegerHelper.getInt(data[pos + 7], data[pos + 8]);
+ c1 = columnMask & 0xff;
+
+ // Check that we are not dealing with offsets
+ Assert.verify((columnMask & 0xc0000) == 0);
+
+ columnMask = IntegerHelper.getInt(data[pos + 9], data[pos + 10]);
+ c2 = columnMask & 0xff;
+
+ // Check that we are not dealing with offsets
+ Assert.verify((columnMask & 0xc0000) == 0);
+
+ range = new NameRange(sheet1, c1, r1, c2, r2);
+ ranges.add(range);
+
+ pos += 11;
+
+ // Consume unnecessary parsed tokens
+ if (pos < data.length &&
+ data[pos] != cellReference &&
+ data[pos] != areaReference)
+ {
+ if (data[pos] == subExpression)
+ {
+ pos += 3;
+ }
+ else if (data[pos] == union)
+ {
+ pos += 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ String n = name != null ? name : builtInName.getName();
+ logger.warn("Cannot read name ranges for " + n +
+ " - setting to empty");
+ NameRange range = new NameRange(0,0,0,0,0);
+ ranges.add(range);
+ }
+ }
+ catch (Throwable t1)
+ {
+ // Generate a warning
+ // Names are really a nice to have, and we don't want to halt the
+ // reading process for functionality that probably won't be used
+ logger.warn("Cannot read name");
+ name = "ERROR";
+ }
+ }
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param ws the workbook settings
+ * @param ind the index in the name table
+ * @param dummy dummy parameter to indicate a biff7 workbook
+ */
+ NameRecord(Record t, WorkbookSettings ws, int ind, Biff7 dummy)
+ {
+ super(t);
+ index = ind;
+ isbiff8 = false;
+
+ try
+ {
+ ranges = new ArrayList();
+ byte[] data = getRecord().getData();
+ int length = data[3];
+ sheetRef = IntegerHelper.getInt(data[8], data[9]);
+ name = StringHelper.getString(data, length, 14, ws);
+
+ int pos = length + 14;
+
+ if (pos >= data.length)
+ {
+ // There appears to be nothing after the name, so return
+ return;
+ }
+
+ if (data[pos] == cellReference)
+ {
+ int sheet = IntegerHelper.getInt(data[pos + 11], data[pos + 12]);
+ int row = IntegerHelper.getInt(data[pos + 15], data[pos + 16]);
+ int column = data[pos + 17];
+
+ NameRange r = new NameRange(sheet, column, row, column, row);
+ ranges.add(r);
+ }
+ else if (data[pos] == areaReference)
+ {
+ int sheet1 = 0;
+ int r1 = 0;
+ int c1 = 0;
+ int r2 = 0;
+ int c2 = 0;
+ NameRange range = null;
+
+ while (pos < data.length)
+ {
+ sheet1 = IntegerHelper.getInt(data[pos + 11], data[pos + 12]);
+ r1 = IntegerHelper.getInt(data[pos + 15], data[pos + 16]);
+ r2 = IntegerHelper.getInt(data[pos + 17], data[pos + 18]);
+
+ c1 = data[pos + 19];
+ c2 = data[pos + 20];
+
+ range = new NameRange(sheet1, c1, r1, c2, r2);
+ ranges.add(range);
+
+ pos += 21;
+ }
+ }
+ else if (data[pos] == subExpression)
+ {
+ int sheet1 = 0;
+ int sheet2 = 0;
+ int r1 = 0;
+ int c1 = 0;
+ int r2 = 0;
+ int c2 = 0;
+ NameRange range = null;
+
+ // Consume unnecessary parsed tokens
+ if (pos < data.length &&
+ data[pos] != cellReference &&
+ data[pos] != areaReference)
+ {
+ if (data[pos] == subExpression)
+ {
+ pos += 3;
+ }
+ else if (data[pos] == union)
+ {
+ pos += 1;
+ }
+ }
+
+ while (pos < data.length)
+ {
+ sheet1 = IntegerHelper.getInt(data[pos + 11], data[pos + 12]);
+ r1 = IntegerHelper.getInt(data[pos + 15], data[pos + 16]);
+ r2 = IntegerHelper.getInt(data[pos + 17], data[pos + 18]);
+
+ c1 = data[pos + 19];
+ c2 = data[pos + 20];
+
+ range = new NameRange(sheet1, c1, r1, c2, r2);
+ ranges.add(range);
+
+ pos += 21;
+
+ // Consume unnecessary parsed tokens
+ if (pos < data.length &&
+ data[pos] != cellReference &&
+ data[pos] != areaReference)
+ {
+ if (data[pos] == subExpression)
+ {
+ pos += 3;
+ }
+ else if (data[pos] == union)
+ {
+ pos += 1;
+ }
+ }
+ }
+ }
+ }
+ catch (Throwable t1)
+ {
+ // Generate a warning
+ // Names are really a nice to have, and we don't want to halt the
+ // reading process for functionality that probably won't be used
+ logger.warn("Cannot read name.");
+ name = "ERROR";
+ }
+ }
+
+ /**
+ * Gets the name
+ *
+ * @return the strings
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Gets the built in name
+ *
+ * @return the built in name
+ */
+ public BuiltInName getBuiltInName()
+ {
+ return builtInName;
+ }
+
+ /**
+ * Gets the array of ranges for this name. This method is public as it is
+ * used from the writable side when copying ranges
+ *
+ * @return the ranges
+ */
+ public NameRange[] getRanges()
+ {
+ NameRange[] nr = new NameRange[ranges.size()];
+ return (NameRange[]) ranges.toArray(nr);
+ }
+
+ /**
+ * Accessor for the index into the name table
+ *
+ * @return the 0-based index into the name table
+ */
+ int getIndex()
+ {
+ return index;
+ }
+
+ /**
+ * The 0-based index sheet reference for a record name
+ * 0 is for a global reference
+ *
+ * @return the sheet reference for name formula
+ */
+ public int getSheetRef()
+ {
+ return sheetRef;
+ }
+
+ /**
+ * Set the index sheet reference for a record name
+ * 0 is for a global reference
+ */
+ public void setSheetRef(int i)
+ {
+ sheetRef = i;
+ }
+
+ /**
+ * Called when copying a sheet. Just returns the raw data
+ *
+ * @return the raw data
+ */
+ public byte[] getData()
+ {
+ return getRecord().getData();
+ }
+
+ /**
+ * Called when copying to determine whether this is a biff8 name
+ *
+ * @return TRUE if this is a biff8 name record, FALSE otherwise
+ */
+ public boolean isBiff8()
+ {
+ return isbiff8;
+ }
+
+ /**
+ * Queries whether this is a global name or not
+ *
+ * @return TRUE if this is a global name, FALSE otherwise
+ */
+ public boolean isGlobal()
+ {
+ return sheetRef == 0;
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/NineteenFourRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/NineteenFourRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/NineteenFourRecord.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,64 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.RecordData;
+
+/**
+ * Identifies the date system as the 1904 system or not
+ */
+class NineteenFourRecord extends RecordData
+{
+ /**
+ * The base year for dates
+ */
+ private boolean nineteenFour;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ */
+ public NineteenFourRecord(Record t)
+ {
+ super(t);
+
+ byte[] data = getRecord().getData();
+
+ nineteenFour = data[0] == 1 ? true : false;
+
+ }
+
+ /**
+ * Accessor to see whether this spreadsheets dates are based around
+ * 1904
+ *
+ * @return true if this workbooks dates are based around the 1904
+ * date system
+ */
+ public boolean is1904()
+ {
+ return nineteenFour;
+ }
+
+
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/NumberFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/NumberFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/NumberFormulaRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,196 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+import common.Logger;
+
+import jxl.CellType;
+import jxl.NumberCell;
+import jxl.NumberFormulaCell;
+import jxl.biff.DoubleHelper;
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.formula.ExternalSheet;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+
+/**
+ * A formula's last calculated value
+ */
+class NumberFormulaRecord extends CellValue
+ implements NumberCell, FormulaData, NumberFormulaCell
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(NumberFormulaRecord.class);
+
+ /**
+ * The last calculated value of the formula
+ */
+ private double value;
+
+ /**
+ * The number format
+ */
+ private NumberFormat format;
+
+ /**
+ * The string format for the double value
+ */
+ private static final DecimalFormat defaultFormat =
+ new DecimalFormat("#.###");
+
+ /**
+ * The formula as an excel string
+ */
+ private String formulaString;
+
+ /**
+ * A handle to the class needed to access external sheets
+ */
+ private ExternalSheet externalSheet;
+
+ /**
+ * A handle to the name table
+ */
+ private WorkbookMethods nameTable;
+
+ /**
+ * The raw data
+ */
+ private byte[] data;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param fr the formatting record
+ * @param es the external sheet
+ * @param nt the name table
+ * @param si the sheet
+ */
+ public NumberFormulaRecord(Record t, FormattingRecords fr,
+ ExternalSheet es, WorkbookMethods nt,
+ SheetImpl si)
+ {
+ super(t, fr, si);
+
+ externalSheet = es;
+ nameTable = nt;
+ data = getRecord().getData();
+
+ format = fr.getNumberFormat(getXFIndex());
+
+ if (format == null)
+ {
+ format = defaultFormat;
+ }
+
+ value = DoubleHelper.getIEEEDouble(data, 6);
+ }
+
+ /**
+ * Interface method which returns the value
+ *
+ * @return the last calculated value of the formula
+ */
+ public double getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the numerical value as a string
+ *
+ * @return The numerical value of the formula as a string
+ */
+ public String getContents()
+ {
+ return !Double.isNaN(value) ? format.format(value) : "";
+ }
+
+ /**
+ * Returns the cell type
+ *
+ * @return The cell type
+ */
+ public CellType getType()
+ {
+ return CellType.NUMBER_FORMULA;
+ }
+
+ /**
+ * Gets the raw bytes for the formula. This will include the
+ * parsed tokens array. Used when copying spreadsheets
+ *
+ * @return the raw record data
+ */
+ public byte[] getFormulaData() throws FormulaException
+ {
+ if (!getSheet().getWorkbookBof().isBiff8())
+ {
+ throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
+ }
+
+ // Lop off the standard information
+ byte[] d = new byte[data.length - 6];
+ System.arraycopy(data, 6, d, 0, data.length - 6);
+
+ return d;
+ }
+
+ /**
+ * Gets the formula as an excel string
+ *
+ * @return the formula as an excel string
+ * @exception FormulaException
+ */
+ public String getFormula() throws FormulaException
+ {
+ if (formulaString == null)
+ {
+ byte[] tokens = new byte[data.length - 22];
+ System.arraycopy(data, 22, tokens, 0, tokens.length);
+ FormulaParser fp = new FormulaParser
+ (tokens, this, externalSheet, nameTable,
+ getSheet().getWorkbook().getSettings());
+ fp.parse();
+ formulaString = fp.getFormula();
+ }
+
+ return formulaString;
+ }
+
+ /**
+ * Gets the NumberFormat used to format this cell. This is the java
+ * equivalent of the Excel format
+ *
+ * @return the NumberFormat used to format the cell
+ */
+ public NumberFormat getNumberFormat()
+ {
+ return format;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/NumberRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/NumberRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/NumberRecord.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,123 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+import common.Logger;
+
+import jxl.CellType;
+import jxl.NumberCell;
+import jxl.biff.DoubleHelper;
+import jxl.biff.FormattingRecords;
+
+/**
+ * A number record. This is stored as 8 bytes, as opposed to the
+ * 4 byte RK record
+ */
+class NumberRecord extends CellValue implements NumberCell
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(NumberRecord.class);
+
+ /**
+ * The value
+ */
+ private double value;
+
+ /**
+ * The java equivalent of the excel format
+ */
+ private NumberFormat format;
+
+ /**
+ * The formatter to convert the value into a string
+ */
+ private static DecimalFormat defaultFormat = new DecimalFormat("#.###");
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param fr the available formats
+ * @param si the sheet
+ */
+ public NumberRecord(Record t, FormattingRecords fr, SheetImpl si)
+ {
+ super(t, fr, si);
+ byte[] data = getRecord().getData();
+
+ value = DoubleHelper.getIEEEDouble(data, 6);
+
+ // Now get the number format
+ format = fr.getNumberFormat(getXFIndex());
+ if (format == null)
+ {
+ format = defaultFormat;
+ }
+ }
+
+ /**
+ * Accessor for the value
+ *
+ * @return the value
+ */
+ public double getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the contents of this cell as a string
+ *
+ * @return the value formatted into a string
+ */
+ public String getContents()
+ {
+ return format.format(value);
+ }
+
+ /**
+ * Accessor for the cell type
+ *
+ * @return the cell type
+ */
+ public CellType getType()
+ {
+ return CellType.NUMBER;
+ }
+
+ /**
+ * Gets the NumberFormat used to format this cell. This is the java
+ * equivalent of the Excel format
+ *
+ * @return the NumberFormat used to format the cell
+ */
+ public NumberFormat getNumberFormat()
+ {
+ return format;
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/NumberValue.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/NumberValue.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/NumberValue.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,255 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+import jxl.CellFeatures;
+import jxl.CellType;
+import jxl.NumberCell;
+import jxl.biff.FormattingRecords;
+import jxl.format.CellFormat;
+
+/**
+ * A numerical cell value, initialized indirectly from a multiple biff record
+ * rather than directly from the binary data
+ */
+class NumberValue implements NumberCell, CellFeaturesAccessor
+{
+ /**
+ * The row containing this number
+ */
+ private int row;
+ /**
+ * The column containing this number
+ */
+ private int column;
+ /**
+ * The value of this number
+ */
+ private double value;
+
+ /**
+ * The cell format
+ */
+ private NumberFormat format;
+
+ /**
+ * The raw cell format
+ */
+ private CellFormat cellFormat;
+
+ /**
+ * The cell features
+ */
+ private CellFeatures features;
+
+ /**
+ * The index to the XF Record
+ */
+ private int xfIndex;
+
+ /**
+ * A handle to the formatting records
+ */
+ private FormattingRecords formattingRecords;
+
+ /**
+ * A flag to indicate whether this object's formatting things have
+ * been initialized
+ */
+ private boolean initialized;
+
+ /**
+ * A handle to the sheet
+ */
+ private SheetImpl sheet;
+
+ /**
+ * The format in which to return this number as a string
+ */
+ private static DecimalFormat defaultFormat = new DecimalFormat("#.###");
+
+ /**
+ * Constructs this number
+ *
+ * @param r the zero based row
+ * @param c the zero base column
+ * @param val the value
+ * @param xfi the xf index
+ * @param fr the formatting records
+ * @param si the sheet
+ */
+ public NumberValue(int r, int c, double val,
+ int xfi,
+ FormattingRecords fr,
+ SheetImpl si)
+ {
+ row = r;
+ column = c;
+ value = val;
+ format = defaultFormat;
+ xfIndex = xfi;
+ formattingRecords = fr;
+ sheet = si;
+ initialized = false;
+ }
+
+ /**
+ * Sets the format for the number based on the Excel spreadsheets' format.
+ * This is called from SheetImpl when it has been definitely established
+ * that this cell is a number and not a date
+ *
+ * @param f the format
+ */
+ final void setNumberFormat(NumberFormat f)
+ {
+ if (f != null)
+ {
+ format = f;
+ }
+ }
+
+ /**
+ * Accessor for the row
+ *
+ * @return the zero based row
+ */
+ public final int getRow()
+ {
+ return row;
+ }
+
+ /**
+ * Accessor for the column
+ *
+ * @return the zero based column
+ */
+ public final int getColumn()
+ {
+ return column;
+ }
+
+ /**
+ * Accessor for the value
+ *
+ * @return the value
+ */
+ public double getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Accessor for the contents as a string
+ *
+ * @return the value as a string
+ */
+ public String getContents()
+ {
+ return format.format(value);
+ }
+
+ /**
+ * Accessor for the cell type
+ *
+ * @return the cell type
+ */
+ public CellType getType()
+ {
+ return CellType.NUMBER;
+ }
+
+ /**
+ * Gets the cell format
+ *
+ * @return the cell format
+ */
+ public CellFormat getCellFormat()
+ {
+ if (!initialized)
+ {
+ cellFormat = formattingRecords.getXFRecord(xfIndex);
+ initialized = true;
+ }
+
+ return cellFormat;
+ }
+
+ /**
+ * Determines whether or not this cell has been hidden
+ *
+ * @return TRUE if this cell has been hidden, FALSE otherwise
+ */
+ public boolean isHidden()
+ {
+ ColumnInfoRecord cir = sheet.getColumnInfo(column);
+
+ if (cir != null && cir.getWidth() == 0)
+ {
+ return true;
+ }
+
+ RowRecord rr = sheet.getRowInfo(row);
+
+ if (rr != null && (rr.getRowHeight() == 0 || rr.isCollapsed()))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Gets the NumberFormat used to format this cell. This is the java
+ * equivalent of the Excel format
+ *
+ * @return the NumberFormat used to format the cell
+ */
+ public NumberFormat getNumberFormat()
+ {
+ return format;
+ }
+
+ /**
+ * Accessor for the cell features
+ *
+ * @return the cell features or NULL if this cell doesn't have any
+ */
+ public CellFeatures getCellFeatures()
+ {
+ return features;
+ }
+
+ /**
+ * Sets the cell features
+ *
+ * @param cf the cell features
+ */
+ public void setCellFeatures(CellFeatures cf)
+ {
+ features = cf;
+ }
+
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/PLSRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/PLSRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/PLSRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,48 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.RecordData;
+
+/**
+ * The environment specific print record
+ */
+public class PLSRecord extends RecordData
+{
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param r the raw data
+ */
+ public PLSRecord(Record r)
+ {
+ super(r);
+ }
+
+ /**
+ * Gets the data
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return getRecord().getData();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/PaletteRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/PaletteRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/PaletteRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,48 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.RecordData;
+
+/**
+ * A password record
+ */
+public class PaletteRecord extends RecordData
+{
+ /**
+ * Constructor
+ *
+ * @param t the raw bytes
+ */
+ PaletteRecord(Record t)
+ {
+ super(t);
+ }
+
+ /**
+ * Accessor for the binary data - used when copying
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return getRecord().getData();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/PaneRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/PaneRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/PaneRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,86 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * Contains the cell dimensions of this worksheet
+ */
+class PaneRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(PaneRecord.class);
+
+ /**
+ * The number of rows visible in the top left pane
+ */
+ private int rowsVisible;
+ /**
+ * The number of columns visible in the top left pane
+ */
+ private int columnsVisible;
+
+ /**
+ * Constructs the dimensions from the raw data
+ *
+ * @param t the raw data
+ */
+ public PaneRecord(Record t)
+ {
+ super(t);
+ byte[] data = t.getData();
+
+ columnsVisible = IntegerHelper.getInt(data[0], data[1]);
+ rowsVisible = IntegerHelper.getInt(data[2], data[3]);
+ }
+
+ /**
+ * Accessor for the number of rows in the top left pane
+ *
+ * @return the number of rows visible in the top left pane
+ */
+ public final int getRowsVisible()
+ {
+ return rowsVisible;
+ }
+
+ /**
+ * Accessor for the numbe rof columns visible in the top left pane
+ *
+ * @return the number of columns visible in the top left pane
+ */
+ public final int getColumnsVisible()
+ {
+ return columnsVisible;
+ }
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/PasswordException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/PasswordException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/PasswordException.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,35 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+/**
+ * A properly typed exception in case consumers of the API specifically
+ * wish to handle the case when the workbook is password protected
+ */
+public class PasswordException extends BiffException
+{
+ /**
+ * Constructor
+ */
+ public PasswordException()
+ {
+ super(passwordProtected);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/PasswordRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/PasswordRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/PasswordRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,62 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+import jxl.biff.Type;
+
+/**
+ * A password record
+ */
+class PasswordRecord extends RecordData
+{
+ /**
+ * The password
+ */
+ private String password;
+ /**
+ * The binary data
+ */
+ private int passwordHash;
+
+ /**
+ * Constructor
+ *
+ * @param t the raw bytes
+ */
+ public PasswordRecord(Record t)
+ {
+ super(Type.PASSWORD);
+
+ byte[] data = t.getData();
+ passwordHash = IntegerHelper.getInt(data[0], data[1]);
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the password hash
+ */
+ public int getPasswordHash()
+ {
+ return passwordHash;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/PrintGridLinesRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/PrintGridLinesRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/PrintGridLinesRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,57 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.RecordData;
+
+/**
+ * Contains the print grid lines option of this worksheet
+ */
+class PrintGridLinesRecord extends RecordData
+{
+ /**
+ * print grid lines flag
+ */
+ private boolean printGridLines;
+
+ /**
+ * Constructs the value from the raw data
+ *
+ * @param pgl the raw data
+ */
+ public PrintGridLinesRecord(Record pgl)
+ {
+ super(pgl);
+ byte[] data = pgl.getData();
+
+ printGridLines = (data[0] == 1 ? true : false);
+ }
+
+ /**
+ * Accessor for the print grid lines flag
+ *
+ * @return TRUE to print grid lines, FALSE otherwise
+ */
+ public boolean getPrintGridLines()
+ {
+ return printGridLines;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/PrintHeadersRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/PrintHeadersRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/PrintHeadersRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,57 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.RecordData;
+
+/**
+ * Contains the print grid lines option of this worksheet
+ */
+class PrintHeadersRecord extends RecordData
+{
+ /**
+ * print grid lines flag
+ */
+ private boolean printHeaders;
+
+ /**
+ * Constructs the value from the raw data
+ *
+ * @param ph the raw data
+ */
+ public PrintHeadersRecord(Record ph)
+ {
+ super(ph);
+ byte[] data = ph.getData();
+
+ printHeaders = (data[0] == 1 ? true : false);
+ }
+
+ /**
+ * Accessor for the print headers flag
+ *
+ * @return TRUE to print headers, FALSE otherwise
+ */
+ public boolean getPrintHeaders()
+ {
+ return printHeaders;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/ProtectRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/ProtectRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/ProtectRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,70 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * A record detailing whether the sheet is protected
+ */
+class ProtectRecord extends RecordData
+{
+ /**
+ * Protected flag
+ */
+ private boolean prot;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ */
+ ProtectRecord(Record t)
+ {
+ super(t);
+ byte[] data = getRecord().getData();
+
+ int protflag = IntegerHelper.getInt(data[0], data[1]);
+
+ prot = (protflag == 1);
+ }
+
+ /**
+ * Returns the protected flag
+ *
+ * @return TRUE if this is protected, FALSE otherwise
+ */
+ boolean isProtected()
+ {
+ return prot;
+ }
+
+
+}
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/RKHelper.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/RKHelper.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/RKHelper.java 17 Aug 2012 14:50:58 -0000 1.1
@@ -0,0 +1,70 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+/**
+ * Helper to convert an RK number into a double or an integer
+ */
+final class RKHelper
+{
+ /**
+ * Private constructor to prevent instantiation
+ */
+ private RKHelper()
+ {
+ }
+
+ /**
+ * Converts excel's internal RK format into a double value
+ *
+ * @param rk the rk number in bits
+ * @return the double representation
+ */
+ public static double getDouble(int rk)
+ {
+ if ((rk & 0x02) != 0)
+ {
+ int intval = rk >> 2;
+
+ double value = intval;
+ if ((rk & 0x01) != 0)
+ {
+ value /= 100;
+ }
+
+ return value;
+ }
+ else
+ {
+ long valbits = (rk & 0xfffffffc);
+ valbits <<= 32;
+ double value = Double.longBitsToDouble(valbits);
+
+ if ((rk & 0x01) != 0)
+ {
+ value /= 100;
+ }
+
+ return value;
+ }
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/RKRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/RKRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/RKRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,122 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+import common.Logger;
+
+import jxl.CellType;
+import jxl.NumberCell;
+import jxl.biff.FormattingRecords;
+import jxl.biff.IntegerHelper;
+
+/**
+ * An individual RK record
+ */
+class RKRecord extends CellValue implements NumberCell
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(RKRecord.class);
+
+ /**
+ * The value
+ */
+ private double value;
+
+ /**
+ * The java equivalent of the excel format
+ */
+ private NumberFormat format;
+
+ /**
+ * The formatter to convert the value into a string
+ */
+ private static DecimalFormat defaultFormat = new DecimalFormat("#.###");
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param fr the available cell formats
+ * @param si the sheet
+ */
+ public RKRecord(Record t, FormattingRecords fr, SheetImpl si)
+ {
+ super(t, fr, si);
+ byte[] data = getRecord().getData();
+ int rknum = IntegerHelper.getInt(data[6], data[7], data[8], data[9]);
+ value = RKHelper.getDouble(rknum);
+
+ // Now get the number format
+ format = fr.getNumberFormat(getXFIndex());
+ if (format == null)
+ {
+ format = defaultFormat;
+ }
+ }
+
+ /**
+ * Accessor for the value
+ *
+ * @return the value
+ */
+ public double getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the contents of this cell as a string
+ *
+ * @return the value formatted into a string
+ */
+ public String getContents()
+ {
+ return format.format(value);
+ }
+
+ /**
+ * Accessor for the cell type
+ *
+ * @return the cell type
+ */
+ public CellType getType()
+ {
+ return CellType.NUMBER;
+ }
+
+ /**
+ * Gets the NumberFormat used to format this cell. This is the java
+ * equivalent of the Excel format
+ *
+ * @return the NumberFormat used to format the cell
+ */
+ public NumberFormat getNumberFormat()
+ {
+ return format;
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/RStringRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/RStringRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/RStringRecord.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,97 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.CellType;
+import jxl.LabelCell;
+import jxl.WorkbookSettings;
+import jxl.biff.FormattingRecords;
+import jxl.biff.IntegerHelper;
+import jxl.biff.StringHelper;
+
+/**
+ * A label which is stored in the cell
+ */
+class RStringRecord extends CellValue implements LabelCell
+{
+ /**
+ * The length of the label in characters
+ */
+ private int length;
+ /**
+ * The label
+ */
+ private String string;
+
+ /**
+ * Dummy indicators for overloading the constructor
+ */
+ private static class Biff7 {};
+ public static Biff7 biff7 = new Biff7();
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param fr the formatting records
+ * @param si the sheet
+ * @param ws the workbook settings
+ * @param dummy dummy overload to indicate a biff 7 workbook
+ */
+ public RStringRecord(Record t, FormattingRecords fr,
+ SheetImpl si, WorkbookSettings ws, Biff7 dummy)
+ {
+ super(t, fr, si);
+ byte[] data = getRecord().getData();
+ length = IntegerHelper.getInt(data[6], data[7]);
+
+ string = StringHelper.getString(data, length, 8, ws);
+ }
+
+ /**
+ * Gets the label
+ *
+ * @return the label
+ */
+ public String getString()
+ {
+ return string;
+ }
+
+ /**
+ * Gets the cell contents as a string
+ *
+ * @return the label
+ */
+ public String getContents()
+ {
+ return string;
+ }
+
+ /**
+ * Accessor for the cell type
+ *
+ * @return the cell type
+ */
+ public CellType getType()
+ {
+ return CellType.LABEL;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/Record.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/Record.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/Record.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,184 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.util.ArrayList;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+
+
+/**
+ * A container for the raw record data within a biff file
+ */
+public final class Record
+{
+ /**
+ * The logger
+ */
+ private static final Logger logger = Logger.getLogger(Record.class);
+
+ /**
+ * The excel biff code
+ */
+ private int code;
+ /**
+ * The data type
+ */
+ private Type type;
+ /**
+ * The length of this record
+ */
+ private int length;
+ /**
+ * A pointer to the beginning of the actual data
+ */
+ private int dataPos;
+ /**
+ * A handle to the excel 97 file
+ */
+ private File file;
+ /**
+ * The raw data within this record
+ */
+ private byte[] data;
+
+ /**
+ * Any continue records
+ */
+ private ArrayList continueRecords;
+
+ /**
+ * Constructor
+ *
+ * @param offset the offset in the raw file
+ * @param f the excel 97 biff file
+ * @param d the data record
+ */
+ Record(byte[] d, int offset, File f)
+ {
+ code = IntegerHelper.getInt(d[offset], d[offset + 1]);
+ length = IntegerHelper.getInt(d[offset + 2], d[offset + 3]);
+ file = f;
+ file.skip(4);
+ dataPos = f.getPos();
+ file.skip(length);
+ type = Type.getType(code);
+ }
+
+ /**
+ * Gets the biff type
+ *
+ * @return the biff type
+ */
+ public Type getType()
+ {
+ return type;
+ }
+
+ /**
+ * Gets the length of the record
+ *
+ * @return the length of the record
+ */
+ public int getLength()
+ {
+ return length;
+ }
+
+ /**
+ * Gets the data portion of the record
+ *
+ * @return the data portion of the record
+ */
+ public byte[] getData()
+ {
+ if (data == null)
+ {
+ data = file.read(dataPos, length);
+ }
+
+ // copy in any data from the continue records
+ if (continueRecords != null)
+ {
+ int size = 0;
+ byte[][] contData = new byte[continueRecords.size()][];
+ for (int i = 0; i < continueRecords.size(); i++)
+ {
+ Record r = (Record) continueRecords.get(i);
+ contData[i] = r.getData();
+ byte[] d2 = contData[i];
+ size += d2.length;
+ }
+
+ byte[] d3 = new byte[data.length + size];
+ System.arraycopy(data, 0, d3, 0, data.length);
+ int pos = data.length;
+ for (int i = 0; i < contData.length; i++)
+ {
+ byte[] d2 = contData[i];
+ System.arraycopy(d2, 0, d3, pos, d2.length);
+ pos += d2.length;
+ }
+
+ data = d3;
+ }
+
+ return data;
+ }
+
+ /**
+ * The excel 97 code
+ *
+ * @return the excel code
+ */
+ public int getCode()
+ {
+ return code;
+ }
+
+ /**
+ * In the case of dodgy records, this method may be called to forcibly
+ * set the type in order to continue processing
+ *
+ * @param t the forcibly overridden type
+ */
+ void setType(Type t)
+ {
+ type = t;
+ }
+
+ /**
+ * Adds a continue record to this data
+ *
+ * @param d the continue record
+ */
+ public void addContinueRecord(Record d)
+ {
+ if (continueRecords == null)
+ {
+ continueRecords = new ArrayList();
+ }
+
+ continueRecords.add(d);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/RightMarginRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/RightMarginRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/RightMarginRecord.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,37 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.Type;
+
+/**
+ * Record for the left margin settings
+ */
+class RightMarginRecord extends MarginRecord
+{
+ /**
+ * Constructor
+ * @param r the record
+ */
+ RightMarginRecord(Record r)
+ {
+ super(Type.RIGHTMARGIN, r);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/RowRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/RowRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/RowRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,191 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * A row record
+ */
+public class RowRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(RowRecord.class);
+
+ /**
+ * The number of this row
+ */
+ private int rowNumber;
+ /**
+ * The height of this row
+ */
+ private int rowHeight;
+ /**
+ * Flag to indicate whether this row is collapsed or not
+ */
+ private boolean collapsed;
+ /**
+ * Indicates whether this row has an explicit default format
+ */
+ private boolean defaultFormat;
+ /**
+ * Indicates whether the row record height matches the default font height
+ */
+ private boolean matchesDefFontHeight;
+ /**
+ * The (default) xf index for cells on this row
+ */
+ private int xfIndex;
+
+ /**
+ * The outline level of the row
+ */
+ private int outlineLevel;
+
+ /**
+ * Is this the icon indicator row of a group?
+ */
+ private boolean groupStart;
+
+ /**
+ * Indicates that the row is default height
+ */
+ private static final int defaultHeightIndicator = 0xff;
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ */
+ RowRecord(Record t)
+ {
+ super(t);
+
+ byte[] data = getRecord().getData();
+ rowNumber = IntegerHelper.getInt(data[0], data[1]);
+ rowHeight = IntegerHelper.getInt(data[6], data[7]);
+
+ int options = IntegerHelper.getInt(data[12], data[13],
+ data[14], data[15]);
+ outlineLevel = (options & 0x7);
+ groupStart = (options & 0x10) != 0;
+ collapsed = (options & 0x20) != 0;
+ matchesDefFontHeight = (options & 0x40) == 0;
+ defaultFormat = (options & 0x80) != 0;
+ xfIndex = (options & 0x0fff0000) >> 16;
+ }
+
+ /**
+ * Interrogates whether this row is of default height
+ *
+ * @return TRUE if this is set to the default height, FALSE otherwise
+ */
+ boolean isDefaultHeight()
+ {
+ return rowHeight == defaultHeightIndicator;
+ }
+
+ /**
+ * Interrogates this row to see whether it matches the default font height
+ *
+ * @return TRUE if this matches the default font height, FALSE otherwise
+ */
+ public boolean matchesDefaultFontHeight()
+ {
+ return matchesDefFontHeight;
+ }
+
+ /**
+ * Gets the row number
+ *
+ * @return the number of this row
+ */
+ public int getRowNumber()
+ {
+ return rowNumber;
+ }
+
+ /**
+ * Accessor for the row's outline level
+ *
+ * @return the row's outline level
+ */
+ public int getOutlineLevel()
+ {
+ return outlineLevel;
+ }
+
+ /**
+ * Accessor for row's groupStart value
+ *
+ * @return the row's groupStart value
+ */
+ public boolean getGroupStart()
+ {
+ return groupStart;
+ }
+
+ /**
+ * Gets the height of the row
+ *
+ * @return the row height
+ */
+ public int getRowHeight()
+ {
+ return rowHeight;
+ }
+
+ /**
+ * Queries whether the row is collapsed
+ *
+ * @return the collapsed indicator
+ */
+ public boolean isCollapsed()
+ {
+ return collapsed;
+ }
+
+ /**
+ * Gets the default xf index for this row
+ *
+ * @return the xf index
+ */
+ public int getXFIndex()
+ {
+ return xfIndex;
+ }
+
+ /**
+ * Queries whether the row has a specific default cell format applied
+ *
+ * @return the default cell format
+ */
+ public boolean hasDefaultFormat()
+ {
+ return defaultFormat;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/SCLRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/SCLRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/SCLRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,64 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan, Adam Caldwell
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+import jxl.biff.Type;
+
+/**
+ * Class containing the zoom factor for display
+ */
+class SCLRecord extends RecordData
+{
+ /**
+ * The numerator of the zoom
+ */
+ private int numerator;
+
+ /**
+ * The denominator of the zoom
+ */
+ private int denominator;
+
+ /**
+ * Constructs this record from the raw data
+ * @param r the record
+ */
+ protected SCLRecord(Record r)
+ {
+ super(Type.SCL);
+
+ byte[] data = r.getData();
+
+ numerator = IntegerHelper.getInt(data[0], data[1]);
+ denominator = IntegerHelper.getInt(data[2], data[3]);
+ }
+
+ /**
+ * Accessor for the zoom factor
+ *
+ * @return the zoom factor as the nearest integer percentage
+ */
+ public int getZoomFactor()
+ {
+ return numerator * 100 / denominator;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/SSTRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/SSTRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/SSTRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,431 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Assert;
+
+import jxl.WorkbookSettings;
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+import jxl.biff.StringHelper;
+
+/**
+ * Holds all the strings in the shared string table
+ */
+class SSTRecord extends RecordData
+{
+ /**
+ * The total number of strings in this table
+ */
+ private int totalStrings;
+ /**
+ * The number of unique strings
+ */
+ private int uniqueStrings;
+ /**
+ * The shared strings
+ */
+ private String[] strings;
+ /**
+ * The array of continuation breaks
+ */
+ private int[] continuationBreaks;
+
+ /**
+ * A holder for a byte array
+ */
+ private static class ByteArrayHolder
+ {
+ /**
+ * the byte holder
+ */
+ public byte[] bytes;
+ }
+
+ /**
+ * A holder for a boolean
+ */
+ private static class BooleanHolder
+ {
+ /**
+ * the holder holder
+ */
+ public boolean value;
+ }
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param continuations the continuations
+ * @param ws the workbook settings
+ */
+ public SSTRecord(Record t, Record[] continuations, WorkbookSettings ws)
+ {
+ super(t);
+
+ // If a continue record appears in the middle of
+ // a string, then the encoding character is repeated
+
+ // Concatenate everything into one big bugger of a byte array
+ int totalRecordLength = 0;
+
+ for (int i = 0; i < continuations.length; i++)
+ {
+ totalRecordLength += continuations[i].getLength();
+ }
+ totalRecordLength += getRecord().getLength();
+
+ byte[] data = new byte[totalRecordLength];
+
+ // First the original data gets put in
+ int pos = 0;
+ System.arraycopy(getRecord().getData(), 0,
+ data, 0, getRecord().getLength());
+ pos += getRecord().getLength();
+
+ // Now copy in everything else.
+ continuationBreaks = new int[continuations.length];
+ Record r = null;
+ for (int i = 0; i < continuations.length; i++)
+ {
+ r = continuations[i];
+ System.arraycopy(r.getData(), 0,
+ data, pos,
+ r.getLength());
+ continuationBreaks[i] = pos;
+ pos += r.getLength();
+ }
+
+ totalStrings = IntegerHelper.getInt(data[0], data[1],
+ data[2], data[3]);
+ uniqueStrings = IntegerHelper.getInt(data[4], data[5],
+ data[6], data[7]);
+
+ strings = new String[uniqueStrings];
+ readStrings(data, 8, ws);
+ }
+
+ /**
+ * Reads in all the strings from the raw data
+ *
+ * @param data the raw data
+ * @param offset the offset
+ * @param ws the workbook settings
+ */
+ private void readStrings(byte[] data, int offset, WorkbookSettings ws)
+ {
+ int pos = offset;
+ int numChars;
+ byte optionFlags;
+ String s = null;
+ boolean asciiEncoding = false;
+ boolean richString = false;
+ boolean extendedString = false;
+ int formattingRuns = 0;
+ int extendedRunLength = 0;
+
+ for (int i = 0; i < uniqueStrings; i++)
+ {
+ // Read in the number of characters
+ numChars = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ pos += 2;
+ optionFlags = data[pos];
+ pos++;
+
+ // See if it is an extended string
+ extendedString = ((optionFlags & 0x04) != 0);
+
+ // See if string contains formatting information
+ richString = ((optionFlags & 0x08) != 0);
+
+ if (richString)
+ {
+ // Read in the crun
+ formattingRuns = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ pos += 2;
+ }
+
+ if (extendedString)
+ {
+ // Read in cchExtRst
+ extendedRunLength = IntegerHelper.getInt
+ (data[pos], data[pos + 1], data[pos + 2], data[pos + 3]);
+ pos += 4;
+ }
+
+ // See if string is ASCII (compressed) or unicode
+ asciiEncoding = ((optionFlags & 0x01) == 0);
+
+ ByteArrayHolder bah = new ByteArrayHolder();
+ BooleanHolder bh = new BooleanHolder();
+ bh.value = asciiEncoding;
+ pos += getChars(data, bah, pos, bh, numChars);
+ asciiEncoding = bh.value;
+
+ if (asciiEncoding)
+ {
+ s = StringHelper.getString(bah.bytes, numChars, 0, ws);
+ }
+ else
+ {
+ s = StringHelper.getUnicodeString(bah.bytes, numChars, 0);
+ }
+
+ strings[i] = s;
+
+ // For rich strings, skip over the formatting runs
+ if (richString)
+ {
+ pos += 4 * formattingRuns;
+ }
+
+ // For extended strings, skip over the extended string data
+ if (extendedString)
+ {
+ pos += extendedRunLength;
+ }
+
+ if (pos > data.length)
+ {
+ Assert.verify(false, "pos exceeds record length");
+ }
+ }
+ }
+
+ /**
+ * Gets the chars in the ascii array, taking into account continuation
+ * breaks
+ *
+ * @param source the original source
+ * @param bah holder for the new byte array
+ * @param pos the current position in the source
+ * @param ascii holder for a return ascii flag
+ * @param numChars the number of chars in the string
+ * @return the number of bytes read from the source
+ */
+ private int getChars(byte[] source,
+ ByteArrayHolder bah,
+ int pos,
+ BooleanHolder ascii,
+ int numChars)
+ {
+ int i = 0;
+ boolean spansBreak = false;
+
+ if (ascii.value)
+ {
+ bah.bytes = new byte[numChars];
+ }
+ else
+ {
+ bah.bytes = new byte[numChars * 2];
+ }
+
+ while (i < continuationBreaks.length && !spansBreak)
+ {
+ spansBreak = pos <= continuationBreaks[i] &&
+ (pos + bah.bytes.length > continuationBreaks[i]);
+
+ if (!spansBreak)
+ {
+ i++;
+ }
+ }
+
+ // If it doesn't span a break simply do an array copy into the
+ // destination array and finish
+ if (!spansBreak)
+ {
+ System.arraycopy(source, pos, bah.bytes, 0, bah.bytes.length);
+ return bah.bytes.length;
+ }
+
+ // Copy the portion before the break pos into the array
+ int breakpos = continuationBreaks[i];
+ System.arraycopy(source, pos, bah.bytes, 0, breakpos - pos);
+
+ int bytesRead = breakpos - pos;
+ int charsRead;
+ if (ascii.value)
+ {
+ charsRead = bytesRead;
+ }
+ else
+ {
+ charsRead = bytesRead / 2;
+ }
+
+ bytesRead += getContinuedString(source,
+ bah,
+ bytesRead,
+ i,
+ ascii,
+ numChars - charsRead);
+ return bytesRead;
+ }
+
+ /**
+ * Gets the rest of the string after a continuation break
+ *
+ * @param source the original bytes
+ * @param bah the holder for the new bytes
+ * @param destPos the des pos
+ * @param contBreakIndex the index of the continuation break
+ * @param ascii the ascii flag holder
+ * @param charsLeft the number of chars left in the array
+ * @return the number of bytes read in the continued string
+ */
+ private int getContinuedString(byte[] source,
+ ByteArrayHolder bah,
+ int destPos,
+ int contBreakIndex,
+ BooleanHolder ascii,
+ int charsLeft)
+ {
+ int breakpos = continuationBreaks[contBreakIndex];
+ int bytesRead = 0;
+
+ while (charsLeft > 0)
+ {
+ Assert.verify(contBreakIndex < continuationBreaks.length,
+ "continuation break index");
+
+ if (ascii.value && source[breakpos] == 0)
+ {
+ // The string is consistently ascii throughout
+
+ int length = contBreakIndex == continuationBreaks.length - 1 ?
+ charsLeft :
+ Math.min
+ (charsLeft,
+ continuationBreaks[contBreakIndex + 1] - breakpos - 1);
+
+ System.arraycopy(source,
+ breakpos + 1,
+ bah.bytes,
+ destPos,
+ length);
+ destPos += length;
+ bytesRead += length + 1;
+ charsLeft -= length;
+ ascii.value = true;
+ }
+ else if (!ascii.value && source[breakpos] != 0)
+ {
+ // The string is Unicode throughout
+
+ int length = contBreakIndex == continuationBreaks.length - 1 ?
+ charsLeft * 2 :
+ Math.min
+ (charsLeft * 2,
+ continuationBreaks[contBreakIndex + 1] - breakpos - 1);
+
+ // It looks like the string continues as Unicode too. That's handy
+ System.arraycopy(source,
+ breakpos + 1,
+ bah.bytes,
+ destPos,
+ length);
+
+ destPos += length;
+ bytesRead += length + 1;
+ charsLeft -= length / 2;
+ ascii.value = false;
+ }
+ else if (!ascii.value && source[breakpos] == 0)
+ {
+ // Bummer - the string starts off as Unicode, but after the
+ // continuation it is in straightforward ASCII encoding
+ int chars = contBreakIndex == continuationBreaks.length - 1 ?
+ charsLeft:
+ Math.min
+ (charsLeft,
+ continuationBreaks[contBreakIndex + 1] - breakpos - 1);
+
+ for (int j = 0; j < chars; j++)
+ {
+ bah.bytes[destPos] = source[breakpos + j + 1];
+ destPos += 2;
+ }
+
+ bytesRead += chars + 1;
+ charsLeft -= chars;
+ ascii.value = false;
+ }
+ else
+ {
+ // Double Bummer - the string starts off as ASCII, but after the
+ // continuation it is in Unicode. This impacts the allocated array
+
+ // Reallocate what we have of the byte array so that it is all
+ // Unicode
+ byte[] oldBytes = bah.bytes;
+ bah.bytes = new byte[destPos * 2 + charsLeft * 2];
+ for (int j = 0; j < destPos; j++)
+ {
+ bah.bytes[j * 2] = oldBytes[j];
+ }
+
+ destPos = destPos * 2;
+
+ int length = contBreakIndex == continuationBreaks.length - 1 ?
+ charsLeft * 2 :
+ Math.min
+ (charsLeft * 2,
+ continuationBreaks[contBreakIndex + 1] - breakpos - 1);
+
+ System.arraycopy(source,
+ breakpos + 1,
+ bah.bytes,
+ destPos,
+ length);
+
+ destPos += length;
+ bytesRead += length + 1;
+ charsLeft -= length / 2;
+ ascii.value = false;
+ }
+
+ contBreakIndex++;
+
+ if (contBreakIndex < continuationBreaks.length)
+ {
+ breakpos = continuationBreaks[contBreakIndex];
+ }
+ }
+
+ return bytesRead;
+ }
+
+ /**
+ * Gets the string at the specified position
+ *
+ * @param index the index of the string to return
+ * @return the strings
+ */
+ public String getString(int index)
+ {
+ Assert.verify(index < uniqueStrings);
+ return strings[index];
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/SaveRecalcRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/SaveRecalcRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/SaveRecalcRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,64 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * A calculation mode record
+ */
+class SaveRecalcRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(SaveRecalcRecord.class);
+
+ /**
+ * The calculation mode
+ */
+ private boolean recalculateOnSave;
+
+ /**
+ * Constructor
+ *
+ * @param t the record
+ */
+ public SaveRecalcRecord(Record t)
+ {
+ super(t);
+ byte[] data = t.getData();
+ int mode = IntegerHelper.getInt(data[0], data[1]);
+ recalculateOnSave = (mode == 1);
+ }
+
+ /**
+ * Accessor for the recalculate on save mode
+ *
+ * @return the recalculate on save mode
+ */
+ public boolean getRecalculateOnSave()
+ {
+ return recalculateOnSave;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/SetupRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/SetupRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/SetupRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,272 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.biff.DoubleHelper;
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+import jxl.biff.Type;
+
+/**
+ * Contains the page set up for a sheet
+ */
+public class SetupRecord extends RecordData
+{
+ // The logger
+ private static Logger logger = Logger.getLogger(SetupRecord.class);
+
+ /**
+ * The raw data
+ */
+ private byte[] data;
+
+ /**
+ * The orientation flag
+ */
+ private boolean portraitOrientation;
+
+ /**
+ * The Page Order flag
+ */
+ private boolean pageOrder;
+
+ /**
+ * The header margin
+ */
+ private double headerMargin;
+
+ /**
+ * The footer margin
+ */
+ private double footerMargin;
+
+ /**
+ * The paper size
+ */
+ private int paperSize;
+
+ /**
+ * The scale factor
+ */
+ private int scaleFactor;
+
+ /**
+ * The page start
+ */
+ private int pageStart;
+
+ /**
+ * The fit width
+ */
+ private int fitWidth;
+
+ /**
+ * The fit height
+ */
+ private int fitHeight;
+
+ /**
+ * The horizontal print resolution
+ */
+ private int horizontalPrintResolution;
+
+ /**
+ * The vertical print resolution
+ */
+ private int verticalPrintResolution;
+
+ /**
+ * The number of copies
+ */
+ private int copies;
+
+ /**
+ * Indicates whether the setup data should be initiliazed in the setup
+ * box
+ */
+ private boolean initialized;
+
+ /**
+ * Constructor which creates this object from the binary data
+ *
+ * @param t the record
+ */
+ SetupRecord(Record t)
+ {
+ super(Type.SETUP);
+
+ data = t.getData();
+
+ paperSize = IntegerHelper.getInt(data[0], data[1]);
+ scaleFactor = IntegerHelper.getInt(data[2], data[3]);
+ pageStart = IntegerHelper.getInt(data[4], data[5]);
+ fitWidth = IntegerHelper.getInt(data[6], data[7]);
+ fitHeight = IntegerHelper.getInt(data[8], data[9]);
+ horizontalPrintResolution = IntegerHelper.getInt(data[12], data[13]);
+ verticalPrintResolution = IntegerHelper.getInt(data[14], data[15]);
+ copies = IntegerHelper.getInt(data[32], data[33]);
+
+ headerMargin = DoubleHelper.getIEEEDouble(data, 16);
+ footerMargin = DoubleHelper.getIEEEDouble(data, 24);
+
+
+
+ int grbit = IntegerHelper.getInt(data[10], data[11]);
+ pageOrder = ((grbit & 0x01) != 0);
+ portraitOrientation = ((grbit & 0x02) != 0);
+ initialized = ( (grbit & 0x04) == 0);
+ }
+
+ /**
+ * Accessor for the orientation. Called when copying sheets
+ *
+ * @return TRUE if the orientation is portrait, FALSE if it is landscape
+ */
+ public boolean isPortrait()
+ {
+ return portraitOrientation;
+ }
+
+
+ /**
+ * Accessor for the page order. Called when copying sheets
+ *
+ * @return TRUE if the page order is Left to Right, then Down, otherwise
+ * FALSE
+ */
+ public boolean isRightDown()
+ {
+ return pageOrder;
+ }
+
+ /**
+ * Accessor for the header. Called when copying sheets
+ *
+ * @return the header margin
+ */
+ public double getHeaderMargin()
+ {
+ return headerMargin;
+ }
+
+ /**
+ * Accessor for the footer. Called when copying sheets
+ *
+ * @return the footer margin
+ */
+ public double getFooterMargin()
+ {
+ return footerMargin;
+ }
+
+ /**
+ * Accessor for the paper size. Called when copying sheets
+ *
+ * @return the footer margin
+ */
+ public int getPaperSize()
+ {
+ return paperSize;
+ }
+
+ /**
+ * Accessor for the scale factor. Called when copying sheets
+ *
+ * @return the scale factor
+ */
+ public int getScaleFactor()
+ {
+ return scaleFactor;
+ }
+
+ /**
+ * Accessor for the page height. called when copying sheets
+ *
+ * @return the page to start printing at
+ */
+ public int getPageStart()
+ {
+ return pageStart;
+ }
+
+ /**
+ * Accessor for the fit width. Called when copying sheets
+ *
+ * @return the fit width
+ */
+ public int getFitWidth()
+ {
+ return fitWidth;
+ }
+
+ /**
+ * Accessor for the fit height. Called when copying sheets
+ *
+ * @return the fit height
+ */
+ public int getFitHeight()
+ {
+ return fitHeight;
+ }
+
+ /**
+ * The horizontal print resolution. Called when copying sheets
+ *
+ * @return the horizontal print resolution
+ */
+ public int getHorizontalPrintResolution()
+ {
+ return horizontalPrintResolution;
+ }
+
+ /**
+ * Accessor for the vertical print resolution. Called when copying sheets
+ *
+ * @return an vertical print resolution
+ */
+ public int getVerticalPrintResolution()
+ {
+ return verticalPrintResolution;
+ }
+
+ /**
+ * Accessor for the number of copies
+ *
+ * @return the number of copies
+ */
+ public int getCopies()
+ {
+ return copies;
+ }
+
+ /**
+ * Accessor for the initialized flag
+ *
+ * @return whether the print page setup should be initialized in the dialog
+ * box
+ */
+ public boolean getInitialized()
+ {
+ return initialized;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/SharedBooleanFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/SharedBooleanFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/SharedBooleanFormulaRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,156 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.BooleanCell;
+import jxl.BooleanFormulaCell;
+import jxl.CellType;
+import jxl.biff.DoubleHelper;
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.IntegerHelper;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.formula.ExternalSheet;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+
+/**
+ * A shared boolean formula record
+ */
+public class SharedBooleanFormulaRecord extends BaseSharedFormulaRecord
+ implements BooleanCell, FormulaData, BooleanFormulaCell
+{
+ /**
+ * The logger
+ */
+ private static Logger logger =
+ Logger.getLogger(SharedBooleanFormulaRecord.class);
+
+ /**
+ * The boolean value of this cell. If this cell represents an error,
+ * this will be false
+ */
+ private boolean value;
+
+ /**
+ * Constructs this number
+ *
+ * @param t the data
+ * @param excelFile the excel biff data
+ * @param v the value
+ * @param fr the formatting records
+ * @param es the external sheet
+ * @param nt the name table
+ * @param si the sheet
+ */
+ public SharedBooleanFormulaRecord(Record t,
+ File excelFile,
+ boolean v,
+ FormattingRecords fr,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ SheetImpl si)
+ {
+ super(t, fr, es, nt, si, excelFile.getPos());
+ value = v;
+ }
+
+ /**
+ * Interface method which Gets the boolean value stored in this cell. If
+ * this cell contains an error, then returns FALSE. Always query this cell
+ * type using the accessor method isError() prior to calling this method
+ *
+ * @return TRUE if this cell contains TRUE, FALSE if it contains FALSE or
+ * an error code
+ */
+ public boolean getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the numerical value as a string
+ *
+ * @return The numerical value of the formula as a string
+ */
+ public String getContents()
+ {
+ // return Boolean.toString(value) - only available in 1.4 or later
+ return (new Boolean(value)).toString();
+ }
+
+ /**
+ * Returns the cell type
+ *
+ * @return The cell type
+ */
+ public CellType getType()
+ {
+ return CellType.BOOLEAN_FORMULA;
+ }
+
+ /**
+ * Gets the raw bytes for the formula. This will include the
+ * parsed tokens array. Used when copying spreadsheets
+ *
+ * @return the raw record data
+ * @exception FormulaException
+ */
+ public byte[] getFormulaData() throws FormulaException
+ {
+ if (!getSheet().getWorkbookBof().isBiff8())
+ {
+ throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
+ }
+
+ // Get the tokens, taking into account the mapping from shared
+ // formula specific values into normal values
+ FormulaParser fp = new FormulaParser
+ (getTokens(), this,
+ getExternalSheet(), getNameTable(),
+ getSheet().getWorkbook().getSettings());
+ fp.parse();
+ byte[] rpnTokens = fp.getBytes();
+
+ byte[] data = new byte[rpnTokens.length + 22];
+
+ // Set the standard info for this cell
+ IntegerHelper.getTwoBytes(getRow(), data, 0);
+ IntegerHelper.getTwoBytes(getColumn(), data, 2);
+ IntegerHelper.getTwoBytes(getXFIndex(), data, 4);
+ data[6] = (byte) 1;
+ data[8] = (byte) (value == true ? 1 : 0);
+ data[12] = (byte) 0xff;
+ data[13] = (byte) 0xff;
+
+ // Now copy in the parsed tokens
+ System.arraycopy(rpnTokens, 0, data, 22, rpnTokens.length);
+ IntegerHelper.getTwoBytes(rpnTokens.length, data, 20);
+
+ // Lop off the standard information
+ byte[] d = new byte[data.length - 6];
+ System.arraycopy(data, 6, d, 0, data.length - 6);
+
+ return d;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/SharedDateFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/SharedDateFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/SharedDateFormulaRecord.java 17 Aug 2012 14:50:55 -0000 1.1
@@ -0,0 +1,194 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.text.DateFormat;
+import java.util.Date;
+
+
+import jxl.CellType;
+import jxl.DateCell;
+import jxl.DateFormulaCell;
+import jxl.biff.DoubleHelper;
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.IntegerHelper;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+
+/**
+ * A number formula record, manufactured out of the Shared Formula
+ * "optimization"
+ */
+public class SharedDateFormulaRecord extends BaseSharedFormulaRecord
+ implements DateCell, FormulaData, DateFormulaCell
+{
+ /**
+ * Re-use the date record to handle all the formatting information and
+ * date calculations
+ */
+ private DateRecord dateRecord;
+
+ /**
+ * The double value
+ */
+ private double value;
+
+ /**
+ * Constructs this number formula
+ *
+ * @param nfr the number formula records
+ * @param fr the formatting records
+ * @param nf flag indicating whether this uses the 1904 date system
+ * @param si the sheet
+ * @param pos the position
+ */
+ public SharedDateFormulaRecord(SharedNumberFormulaRecord nfr,
+ FormattingRecords fr,
+ boolean nf,
+ SheetImpl si,
+ int pos)
+ {
+ super(nfr.getRecord(),
+ fr,
+ nfr.getExternalSheet(),
+ nfr.getNameTable(),
+ si,
+ pos);
+ dateRecord = new DateRecord(nfr, nfr.getXFIndex(), fr, nf, si);
+ value = nfr.getValue();
+ }
+
+ /**
+ * Accessor for the value
+ *
+ * @return the value
+ */
+ public double getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Accessor for the contents as a string
+ *
+ * @return the value as a string
+ */
+ public String getContents()
+ {
+ return dateRecord.getContents();
+ }
+
+ /**
+ * Accessor for the cell type
+ *
+ * @return the cell type
+ */
+ public CellType getType()
+ {
+ return CellType.DATE_FORMULA;
+ }
+
+ /**
+ * Gets the raw bytes for the formula. This will include the
+ * parsed tokens array. Used when copying spreadsheets
+ *
+ * @return the raw record data
+ * @exception FormulaException
+ */
+ public byte[] getFormulaData() throws FormulaException
+ {
+ if (!getSheet().getWorkbookBof().isBiff8())
+ {
+ throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
+ }
+
+ // Get the tokens, taking into account the mapping from shared
+ // formula specific values into normal values
+ FormulaParser fp = new FormulaParser
+ (getTokens(), this,
+ getExternalSheet(), getNameTable(),
+ getSheet().getWorkbook().getSettings());
+ fp.parse();
+ byte[] rpnTokens = fp.getBytes();
+
+ byte[] data = new byte[rpnTokens.length + 22];
+
+ // Set the standard info for this cell
+ IntegerHelper.getTwoBytes(getRow(), data, 0);
+ IntegerHelper.getTwoBytes(getColumn(), data, 2);
+ IntegerHelper.getTwoBytes(getXFIndex(), data, 4);
+ DoubleHelper.getIEEEBytes(value, data, 6);
+
+ // Now copy in the parsed tokens
+ System.arraycopy(rpnTokens, 0, data, 22, rpnTokens.length);
+ IntegerHelper.getTwoBytes(rpnTokens.length, data, 20);
+
+ // Lop off the standard information
+ byte[] d = new byte[data.length - 6];
+ System.arraycopy(data, 6, d, 0, data.length - 6);
+
+ return d;
+ }
+
+ /**
+ * Gets the date
+ *
+ * @return the date
+ */
+ public Date getDate()
+ {
+ return dateRecord.getDate();
+ }
+
+ /**
+ * Indicates whether the date value contained in this cell refers to a date,
+ * or merely a time
+ *
+ * @return TRUE if the value refers to a time
+ */
+ public boolean isTime()
+ {
+ return dateRecord.isTime();
+ }
+
+ /**
+ * Gets the DateFormat used to format the cell. This will normally be
+ * the format specified in the excel spreadsheet, but in the event of any
+ * difficulty parsing this, it will revert to the default date/time format.
+ *
+ * @return the DateFormat object used to format the date in the original
+ * excel cell
+ */
+ public DateFormat getDateFormat()
+ {
+ return dateRecord.getDateFormat();
+ }
+
+}
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/SharedErrorFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/SharedErrorFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/SharedErrorFormulaRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,177 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.CellType;
+import jxl.ErrorCell;
+import jxl.ErrorFormulaCell;
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.IntegerHelper;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.formula.ExternalSheet;
+import jxl.biff.formula.FormulaErrorCode;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+
+/**
+ * A number formula record, manufactured out of the Shared Formula
+ * "optimization"
+ */
+public class SharedErrorFormulaRecord extends BaseSharedFormulaRecord
+ implements ErrorCell, FormulaData, ErrorFormulaCell
+{
+ /**
+ * The logger
+ */
+ private static Logger logger =
+ Logger.getLogger(SharedErrorFormulaRecord.class);
+
+ /**
+ * The error code of this cell
+ */
+ private int errorCode;
+
+ /**
+ * The raw data
+ */
+ private byte[] data;
+
+ /**
+ * The error code
+ */
+ private FormulaErrorCode error;
+
+ /**
+ * Constructs this number
+ *
+ * @param t the data
+ * @param excelFile the excel biff data
+ * @param v the errorCode
+ * @param fr the formatting records
+ * @param es the external sheet
+ * @param nt the name table
+ * @param si the sheet
+ */
+ public SharedErrorFormulaRecord(Record t,
+ File excelFile,
+ int ec,
+ FormattingRecords fr,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ SheetImpl si)
+ {
+ super(t, fr, es, nt, si, excelFile.getPos());
+ errorCode = ec;
+ }
+
+ /**
+ * Interface method which gets the error code for this cell. If this cell
+ * does not represent an error, then it returns 0. Always use the
+ * method isError() to determine this prior to calling this method
+ *
+ * @return the error code if this cell contains an error, 0 otherwise
+ */
+ public int getErrorCode()
+ {
+ return errorCode;
+ }
+
+ /**
+ * Returns the numerical value as a string
+ *
+ * @return The numerical value of the formula as a string
+ */
+ public String getContents()
+ {
+ if (error == null)
+ {
+ error = FormulaErrorCode.getErrorCode(errorCode);
+ }
+
+ return error != FormulaErrorCode.UNKNOWN ?
+ error.getDescription() : "ERROR " + errorCode;
+ }
+
+ /**
+ * Accessor for the cell type
+ *
+ * @return the cell type
+ */
+ public CellType getType()
+ {
+ return CellType.FORMULA_ERROR;
+ }
+
+ /**
+ * Gets the raw bytes for the formula. This will include the
+ * parsed tokens array. Used when copying spreadsheets
+ *
+ * @return the raw record data
+ * @exception FormulaException
+ */
+ public byte[] getFormulaData() throws FormulaException
+ {
+ if (!getSheet().getWorkbookBof().isBiff8())
+ {
+ throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
+ }
+
+ // Get the tokens, taking into account the mapping from shared
+ // formula specific values into normal values
+ FormulaParser fp = new FormulaParser
+ (getTokens(), this,
+ getExternalSheet(), getNameTable(),
+ getSheet().getWorkbook().getSettings());
+ fp.parse();
+ byte[] rpnTokens = fp.getBytes();
+
+ byte[] data = new byte[rpnTokens.length + 22];
+
+ // Set the standard info for this cell
+ IntegerHelper.getTwoBytes(getRow(), data, 0);
+ IntegerHelper.getTwoBytes(getColumn(), data, 2);
+ IntegerHelper.getTwoBytes(getXFIndex(), data, 4);
+
+ data[6] = (byte) 0x02; // indicates this cell is an error value
+ data[8] = (byte) errorCode;
+ data[12] = (byte) 0xff;
+ data[13] = (byte) 0xff;
+
+ // Now copy in the parsed tokens
+ System.arraycopy(rpnTokens, 0, data, 22, rpnTokens.length);
+ IntegerHelper.getTwoBytes(rpnTokens.length, data, 20);
+
+ // Lop off the standard information
+ byte[] d = new byte[data.length - 6];
+ System.arraycopy(data, 6, d, 0, data.length - 6);
+
+ return d;
+ }
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/SharedFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/SharedFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/SharedFormulaRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,231 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.text.NumberFormat;
+import java.util.ArrayList;
+
+import common.Logger;
+
+import jxl.Cell;
+import jxl.CellType;
+import jxl.biff.FormattingRecords;
+import jxl.biff.IntegerHelper;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.formula.ExternalSheet;
+
+/**
+ * A shared formula
+ */
+class SharedFormulaRecord
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(SharedFormulaRecord.class);
+
+ /**
+ * The first row to which this shared formula applies
+ */
+ private int firstRow;
+
+ /**
+ * The last row to which this shared formula applies
+ */
+ private int lastRow;
+
+ /**
+ * The first column to which this shared formula applies
+ */
+ private int firstCol;
+
+ /**
+ * The last column to which this shared formula applies
+ */
+ private int lastCol;
+
+ /**
+ * The first (template) formula comprising this group
+ */
+ private BaseSharedFormulaRecord templateFormula;
+
+ /**
+ * The rest of the cells comprising this shared formula
+ */
+ private ArrayList formulas;
+
+ /**
+ * The token data
+ */
+ private byte[] tokens;
+
+ /**
+ * A handle to the external sheet
+ */
+ private ExternalSheet externalSheet;
+
+ /**
+ * A handle to the sheet
+ */
+ private SheetImpl sheet;
+
+
+ /**
+ * Constructs this object from the raw data. Creates either a
+ * NumberFormulaRecord or a StringFormulaRecord depending on whether
+ * this formula represents a numerical calculation or not
+ *
+ * @param t the raw data
+ * @param fr the base shared formula
+ * @param es the workbook, which contains the external sheet references
+ * @param nt the workbook
+ * @param si the sheet
+ */
+ public SharedFormulaRecord(Record t, BaseSharedFormulaRecord fr,
+ ExternalSheet es, WorkbookMethods nt,
+ SheetImpl si)
+ {
+ sheet = si;
+ byte[] data = t.getData();
+
+ firstRow = IntegerHelper.getInt(data[0], data[1]);
+ lastRow = IntegerHelper.getInt(data[2], data[3]);
+ firstCol = data[4] & 0xff;
+ lastCol = data[5] & 0xff;
+
+ formulas = new ArrayList();
+
+ templateFormula = fr;
+
+ tokens = new byte[data.length - 10];
+ System.arraycopy(data, 10, tokens, 0, tokens.length);
+ }
+
+ /**
+ * Adds this formula to the list of formulas, if it falls within
+ * the bounds
+ *
+ * @param fr the formula record to test for membership of this group
+ * @return TRUE if the formulas was added, FALSE otherwise
+ */
+ public boolean add(BaseSharedFormulaRecord fr)
+ {
+ boolean added = false;
+ int r = fr.getRow();
+ if (r >= firstRow && r <= lastRow)
+ {
+ int c = fr.getColumn();
+ if (c >= firstCol && c <= lastCol)
+ {
+ formulas.add(fr);
+ added = true;
+ }
+ }
+
+
+ return added;
+ }
+
+ /**
+ * Manufactures individual cell formulas out the whole shared formula
+ * debacle
+ *
+ * @param fr the formatting records
+ * @param nf flag indicating whether this uses the 1904 date system
+ * @return an array of formulas to be added to the sheet
+ */
+ Cell[] getFormulas(FormattingRecords fr, boolean nf)
+ {
+ Cell[] sfs = new Cell[formulas.size() + 1];
+
+ // This can happen if there are many identical formulas in the
+ // sheet and excel has not sliced and diced them exclusively
+ if (templateFormula == null)
+ {
+ logger.warn("Shared formula template formula is null");
+ return new Cell[0];
+ }
+
+ templateFormula.setTokens(tokens);
+ NumberFormat templateNumberFormat = null;
+
+ // See if the template formula evaluates to date
+ if (templateFormula.getType() == CellType.NUMBER_FORMULA)
+ {
+ SharedNumberFormulaRecord snfr = (SharedNumberFormulaRecord)
+ templateFormula;
+ templateNumberFormat = snfr.getNumberFormat();
+
+ if (fr.isDate(templateFormula.getXFIndex()))
+ {
+ templateFormula = new SharedDateFormulaRecord(snfr, fr, nf, sheet,
+ snfr.getFilePos());
+ templateFormula.setTokens(snfr.getTokens());
+ }
+ }
+
+ sfs[0] = templateFormula;
+
+ BaseSharedFormulaRecord f = null;
+
+ for (int i = 0; i < formulas.size(); i++)
+ {
+ f = (BaseSharedFormulaRecord) formulas.get(i);
+
+ // See if the formula evaluates to date
+ if (f.getType() == CellType.NUMBER_FORMULA)
+ {
+ SharedNumberFormulaRecord snfr = (SharedNumberFormulaRecord) f;
+
+ if (fr.isDate(f.getXFIndex()))
+ {
+ f = new SharedDateFormulaRecord(snfr, fr, nf, sheet,
+ snfr.getFilePos());
+ }
+ else
+ {
+ ;// snfr.setNumberFormat(templateNumberFormat);
+ }
+ }
+
+ f.setTokens(tokens);
+ sfs[i + 1] = f;
+ }
+
+ return sfs;
+ }
+
+ /**
+ * Accessor for the template formula. Called when a shared formula has,
+ * for some reason, specified an inappropriate range and it is necessary
+ * to retrieve the template from a previously available shared formula
+ */
+ BaseSharedFormulaRecord getTemplateFormula()
+ {
+ return templateFormula;
+ }
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/SharedNumberFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/SharedNumberFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/SharedNumberFormulaRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,201 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+import common.Logger;
+
+import jxl.CellType;
+import jxl.NumberCell;
+import jxl.NumberFormulaCell;
+
+import jxl.biff.DoubleHelper;
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.IntegerHelper;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.formula.ExternalSheet;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+
+/**
+ * A number formula record, manufactured out of the Shared Formula
+ * "optimization"
+ */
+public class SharedNumberFormulaRecord extends BaseSharedFormulaRecord
+ implements NumberCell, FormulaData, NumberFormulaCell
+{
+ /**
+ * The logger
+ */
+ private static Logger logger =
+ Logger.getLogger(SharedNumberFormulaRecord.class);
+ /**
+ * The value of this number
+ */
+ private double value;
+ /**
+ * The cell format
+ */
+ private NumberFormat format;
+ /**
+ * A handle to the formatting records
+ */
+ private FormattingRecords formattingRecords;
+
+ /**
+ * The string format for the double value
+ */
+ private static DecimalFormat defaultFormat = new DecimalFormat("#.###");
+
+ /**
+ * Constructs this number
+ *
+ * @param t the data
+ * @param excelFile the excel biff data
+ * @param v the value
+ * @param fr the formatting records
+ * @param es the external sheet
+ * @param nt the name table
+ * @param si the sheet
+ */
+ public SharedNumberFormulaRecord(Record t,
+ File excelFile,
+ double v,
+ FormattingRecords fr,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ SheetImpl si)
+ {
+ super(t, fr, es, nt, si, excelFile.getPos());
+ value = v;
+ format = defaultFormat; // format is set up later from the
+ // SharedFormulaRecord
+ }
+
+ /**
+ * Sets the format for the number based on the Excel spreadsheets' format.
+ * This is called from SheetImpl when it has been definitely established
+ * that this cell is a number and not a date
+ *
+ * @param f the format
+ */
+ final void setNumberFormat(NumberFormat f)
+ {
+ if (f != null)
+ {
+ format = f;
+ }
+ }
+
+ /**
+ * Accessor for the value
+ *
+ * @return the value
+ */
+ public double getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Accessor for the contents as a string
+ *
+ * @return the value as a string
+ */
+ public String getContents()
+ {
+ return !Double.isNaN(value) ? format.format(value) : "";
+ }
+
+ /**
+ * Accessor for the cell type
+ *
+ * @return the cell type
+ */
+ public CellType getType()
+ {
+ return CellType.NUMBER_FORMULA;
+ }
+
+ /**
+ * Gets the raw bytes for the formula. This will include the
+ * parsed tokens array. Used when copying spreadsheets
+ *
+ * @return the raw record data
+ * @exception FormulaException
+ */
+ public byte[] getFormulaData() throws FormulaException
+ {
+ if (!getSheet().getWorkbookBof().isBiff8())
+ {
+ throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
+ }
+
+ // Get the tokens, taking into account the mapping from shared
+ // formula specific values into normal values
+ FormulaParser fp = new FormulaParser
+ (getTokens(), this,
+ getExternalSheet(), getNameTable(),
+ getSheet().getWorkbook().getSettings());
+ fp.parse();
+ byte[] rpnTokens = fp.getBytes();
+
+ byte[] data = new byte[rpnTokens.length + 22];
+
+ // Set the standard info for this cell
+ IntegerHelper.getTwoBytes(getRow(), data, 0);
+ IntegerHelper.getTwoBytes(getColumn(), data, 2);
+ IntegerHelper.getTwoBytes(getXFIndex(), data, 4);
+ DoubleHelper.getIEEEBytes(value, data, 6);
+
+ // Now copy in the parsed tokens
+ System.arraycopy(rpnTokens, 0, data, 22, rpnTokens.length);
+ IntegerHelper.getTwoBytes(rpnTokens.length, data, 20);
+
+ // Lop off the standard information
+ byte[] d = new byte[data.length - 6];
+ System.arraycopy(data, 6, d, 0, data.length - 6);
+
+ return d;
+ }
+
+ /**
+ * Gets the NumberFormat used to format this cell. This is the java
+ * equivalent of the Excel format
+ *
+ * @return the NumberFormat used to format the cell
+ */
+ public NumberFormat getNumberFormat()
+ {
+ return format;
+ }
+}
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/SharedStringFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/SharedStringFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/SharedStringFormulaRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,260 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.CellType;
+import jxl.LabelCell;
+import jxl.StringFormulaCell;
+import jxl.WorkbookSettings;
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.IntegerHelper;
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.formula.ExternalSheet;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+
+/**
+ * A string formula record, manufactured out of the Shared Formula
+ * "optimization"
+ */
+public class SharedStringFormulaRecord extends BaseSharedFormulaRecord
+ implements LabelCell, FormulaData, StringFormulaCell
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger
+ (SharedStringFormulaRecord.class);
+
+ /**
+ * The value of this string formula
+ */
+ private String value;
+
+ // Dummy value for overloading the constructor when the string evaluates
+ // to null
+ private static final class EmptyString {};
+ protected static final EmptyString EMPTY_STRING = new EmptyString();
+
+ /**
+ * Constructs this string formula
+ *
+ * @param t the record
+ * @param excelFile the excel file
+ * @param fr the formatting record
+ * @param es the external sheet
+ * @param nt the workbook
+ * @param si the sheet
+ * @param ws the workbook settings
+ */
+ public SharedStringFormulaRecord(Record t,
+ File excelFile,
+ FormattingRecords fr,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ SheetImpl si,
+ WorkbookSettings ws)
+ {
+ super(t, fr, es, nt, si, excelFile.getPos());
+ int pos = excelFile.getPos();
+
+ // Save the position in the excel file
+ int filepos = excelFile.getPos();
+
+ // Look for the string record in one of the records after the
+ // formula. Put a cap on it to prevent ednas
+ Record nextRecord = excelFile.next();
+ int count = 0;
+ while (nextRecord.getType() != Type.STRING && count < 4)
+ {
+ nextRecord = excelFile.next();
+ count++;
+ }
+ Assert.verify(count < 4, " @ " + pos);
+
+ byte[] stringData = nextRecord.getData();
+
+ // Read in any continuation records
+ nextRecord = excelFile.peek();
+ while (nextRecord.getType() == Type.CONTINUE)
+ {
+ nextRecord = excelFile.next(); // move the pointer within the data
+ byte[] d = new byte[stringData.length + nextRecord.getLength() - 1];
+ System.arraycopy(stringData, 0, d, 0, stringData.length);
+ System.arraycopy(nextRecord.getData(), 1, d,
+ stringData.length, nextRecord.getLength() - 1);
+ stringData = d;
+ nextRecord = excelFile.peek();
+ }
+
+ int chars = IntegerHelper.getInt(stringData[0], stringData[1]);
+
+ boolean unicode = false;
+ int startpos = 3;
+ if (stringData.length == chars + 2)
+ {
+ // String might only consist of a one byte length indicator, instead
+ // of the more normal 2
+ startpos = 2;
+ unicode = false;
+ }
+ else if (stringData[2] == 0x1)
+ {
+ // unicode string, two byte length indicator
+ startpos = 3;
+ unicode = true;
+ }
+ else
+ {
+ // ascii string, two byte length indicator
+ startpos = 3;
+ unicode = false;
+ }
+
+ if (!unicode)
+ {
+ value = StringHelper.getString(stringData, chars, startpos, ws);
+ }
+ else
+ {
+ value = StringHelper.getUnicodeString(stringData, chars, startpos);
+ }
+
+ // Restore the position in the excel file, to enable the SHRFMLA
+ // record to be picked up
+ excelFile.setPos(filepos);
+ }
+
+ /**
+ * Constructs this string formula
+ *
+ * @param t the record
+ * @param excelFile the excel file
+ * @param fr the formatting record
+ * @param es the external sheet
+ * @param nt the workbook
+ * @param si the sheet
+ * @param dummy the overload indicator
+ */
+ public SharedStringFormulaRecord(Record t,
+ File excelFile,
+ FormattingRecords fr,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ SheetImpl si,
+ EmptyString dummy)
+ {
+ super(t, fr, es, nt, si, excelFile.getPos());
+
+ value = "";
+ }
+
+ /**
+ * Accessor for the value
+ *
+ * @return the value
+ */
+ public String getString()
+ {
+ return value;
+ }
+
+ /**
+ * Accessor for the contents as a string
+ *
+ * @return the value as a string
+ */
+ public String getContents()
+ {
+ return value;
+ }
+
+ /**
+ * Accessor for the cell type
+ *
+ * @return the cell type
+ */
+ public CellType getType()
+ {
+ return CellType.STRING_FORMULA;
+ }
+
+ /**
+ * Gets the raw bytes for the formula. This will include the
+ * parsed tokens array. Used when copying spreadsheets
+ *
+ * @return the raw record data
+ * @exception FormulaException
+ */
+ public byte[] getFormulaData() throws FormulaException
+ {
+ if (!getSheet().getWorkbookBof().isBiff8())
+ {
+ throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
+ }
+
+ // Get the tokens, taking into account the mapping from shared
+ // formula specific values into normal values
+ FormulaParser fp = new FormulaParser
+ (getTokens(), this,
+ getExternalSheet(), getNameTable(),
+ getSheet().getWorkbook().getSettings());
+ fp.parse();
+ byte[] rpnTokens = fp.getBytes();
+
+ byte[] data = new byte[rpnTokens.length + 22];
+
+ // Set the standard info for this cell
+ IntegerHelper.getTwoBytes(getRow(), data, 0);
+ IntegerHelper.getTwoBytes(getColumn(), data, 2);
+ IntegerHelper.getTwoBytes(getXFIndex(), data, 4);
+
+ // Set the two most significant bytes of the value to be 0xff in
+ // order to identify this as a string
+ data[6] = 0;
+ data[12] = -1;
+ data[13] = -1;
+
+ // Now copy in the parsed tokens
+ System.arraycopy(rpnTokens, 0, data, 22, rpnTokens.length);
+ IntegerHelper.getTwoBytes(rpnTokens.length, data, 20);
+
+ // Lop off the standard information
+ byte[] d = new byte[data.length - 6];
+ System.arraycopy(data, 6, d, 0, data.length - 6);
+
+ return d;
+ }
+}
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/SheetImpl.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/SheetImpl.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/SheetImpl.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,1253 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.regex.Pattern;
+
+import common.Logger;
+import common.Assert;
+
+import jxl.Cell;
+import jxl.CellType;
+import jxl.CellView;
+import jxl.Hyperlink;
+import jxl.Image;
+import jxl.LabelCell;
+import jxl.Range;
+import jxl.Sheet;
+import jxl.SheetSettings;
+import jxl.WorkbookSettings;
+import jxl.biff.BuiltInName;
+import jxl.biff.AutoFilter;
+import jxl.biff.CellFinder;
+import jxl.biff.CellReferenceHelper;
+import jxl.biff.ConditionalFormat;
+import jxl.biff.DataValidation;
+import jxl.biff.EmptyCell;
+import jxl.biff.FormattingRecords;
+import jxl.biff.Type;
+import jxl.biff.WorkspaceInformationRecord;
+import jxl.biff.drawing.Chart;
+import jxl.biff.drawing.Drawing;
+import jxl.biff.drawing.DrawingData;
+import jxl.biff.drawing.DrawingGroupObject;
+import jxl.format.CellFormat;
+
+/**
+ * Represents a sheet within a workbook. Provides a handle to the individual
+ * cells, or lines of cells (grouped by Row or Column)
+ * In order to simplify this class due to code bloat, the actual reading
+ * logic has been delegated to the SheetReaderClass. This class' main
+ * responsibility is now to implement the API methods declared in the
+ * Sheet interface
+ */
+public class SheetImpl implements Sheet
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(SheetImpl.class);
+
+ /**
+ * The excel file
+ */
+ private File excelFile;
+ /**
+ * A handle to the shared string table
+ */
+ private SSTRecord sharedStrings;
+
+ /**
+ * A handle to the sheet BOF record, which indicates the stream type
+ */
+ private BOFRecord sheetBof;
+
+ /**
+ * A handle to the workbook BOF record, which indicates the stream type
+ */
+ private BOFRecord workbookBof;
+
+ /**
+ * A handle to the formatting records
+ */
+ private FormattingRecords formattingRecords;
+
+ /**
+ * The name of this sheet
+ */
+ private String name;
+
+ /**
+ * The number of rows
+ */
+ private int numRows;
+
+ /**
+ * The number of columns
+ */
+ private int numCols;
+
+ /**
+ * The cells
+ */
+ private Cell[][] cells;
+
+ /**
+ * The start position in the stream of this sheet
+ */
+ private int startPosition;
+
+ /**
+ * The list of specified (ie. non default) column widths
+ */
+ private ColumnInfoRecord[] columnInfos;
+
+ /**
+ * The array of row records
+ */
+ private RowRecord[] rowRecords;
+
+ /**
+ * The list of non-default row properties
+ */
+ private ArrayList rowProperties;
+
+ /**
+ * An array of column info records. They are held this way before
+ * they are transferred to the more convenient array
+ */
+ private ArrayList columnInfosArray;
+
+ /**
+ * A list of shared formula groups
+ */
+ private ArrayList sharedFormulas;
+
+ /**
+ * A list of hyperlinks on this page
+ */
+ private ArrayList hyperlinks;
+
+ /**
+ * A list of charts on this page
+ */
+ private ArrayList charts;
+
+ /**
+ * A list of drawings on this page
+ */
+ private ArrayList drawings;
+
+ /**
+ * A list of drawings (as opposed to comments/validation/charts) on this
+ * page
+ */
+ private ArrayList images;
+
+ /**
+ * A list of data validations on this page
+ */
+ private DataValidation dataValidation;
+
+ /**
+ * A list of merged cells on this page
+ */
+ private Range[] mergedCells;
+
+ /**
+ * Indicates whether the columnInfos array has been initialized
+ */
+ private boolean columnInfosInitialized;
+
+ /**
+ * Indicates whether the rowRecords array has been initialized
+ */
+ private boolean rowRecordsInitialized;
+
+ /**
+ * Indicates whether or not the dates are based around the 1904 date system
+ */
+ private boolean nineteenFour;
+
+ /**
+ * The workspace options
+ */
+ private WorkspaceInformationRecord workspaceOptions;
+
+ /**
+ * The hidden flag
+ */
+ private boolean hidden;
+
+ /**
+ * The environment specific print record
+ */
+ private PLSRecord plsRecord;
+
+ /**
+ * The property set record associated with this workbook
+ */
+ private ButtonPropertySetRecord buttonPropertySet;
+
+ /**
+ * The sheet settings
+ */
+ private SheetSettings settings;
+
+ /**
+ * The horizontal page breaks contained on this sheet
+ */
+ private int[] rowBreaks;
+
+ /**
+ * The vertical page breaks contained on this sheet
+ */
+ private int[] columnBreaks;
+
+ /**
+ * The maximum row outline level
+ */
+ private int maxRowOutlineLevel;
+
+ /**
+ * The maximum column outline level
+ */
+ private int maxColumnOutlineLevel;
+
+ /**
+ * The list of local names for this sheet
+ */
+ private ArrayList localNames;
+
+ /**
+ * The list of conditional formats for this sheet
+ */
+ private ArrayList conditionalFormats;
+
+ /**
+ * The autofilter information
+ */
+ private AutoFilter autoFilter;
+
+ /**
+ * A handle to the workbook which contains this sheet. Some of the records
+ * need this in order to reference external sheets
+ */
+ private WorkbookParser workbook;
+
+ /**
+ * A handle to the workbook settings
+ */
+ private WorkbookSettings workbookSettings;
+
+ /**
+ * Constructor
+ *
+ * @param f the excel file
+ * @param sst the shared string table
+ * @param fr formatting records
+ * @param sb the bof record which indicates the start of the sheet
+ * @param wb the bof record which indicates the start of the sheet
+ * @param nf the 1904 flag
+ * @param wp the workbook which this sheet belongs to
+ * @exception BiffException
+ */
+ SheetImpl(File f,
+ SSTRecord sst,
+ FormattingRecords fr,
+ BOFRecord sb,
+ BOFRecord wb,
+ boolean nf,
+ WorkbookParser wp)
+ throws BiffException
+ {
+ excelFile = f;
+ sharedStrings = sst;
+ formattingRecords = fr;
+ sheetBof = sb;
+ workbookBof = wb;
+ columnInfosArray = new ArrayList();
+ sharedFormulas = new ArrayList();
+ hyperlinks = new ArrayList();
+ rowProperties = new ArrayList(10);
+ columnInfosInitialized = false;
+ rowRecordsInitialized = false;
+ nineteenFour = nf;
+ workbook = wp;
+ workbookSettings = workbook.getSettings();
+
+ // Mark the position in the stream, and then skip on until the end
+ startPosition = f.getPos();
+
+ if (sheetBof.isChart())
+ {
+ // Set the start pos to include the bof so the sheet reader can handle it
+ startPosition -= (sheetBof.getLength() + 4);
+ }
+
+ Record r = null;
+ int bofs = 1;
+
+ while (bofs >= 1)
+ {
+ r = f.next();
+
+ // use this form for quick performance
+ if (r.getCode() == Type.EOF.value)
+ {
+ bofs--;
+ }
+
+ if (r.getCode() == Type.BOF.value)
+ {
+ bofs++;
+ }
+ }
+ }
+
+ /**
+ * Returns the cell for the specified location eg. "A4", using the
+ * CellReferenceHelper
+ *
+ * @param loc the cell reference
+ * @return the cell at the specified co-ordinates
+ */
+ public Cell getCell(String loc)
+ {
+ return getCell(CellReferenceHelper.getColumn(loc),
+ CellReferenceHelper.getRow(loc));
+ }
+
+ /**
+ * Returns the cell specified at this row and at this column
+ *
+ * @param row the row number
+ * @param column the column number
+ * @return the cell at the specified co-ordinates
+ */
+ public Cell getCell(int column, int row)
+ {
+ // just in case this has been cleared, but something else holds
+ // a reference to it
+ if (cells == null)
+ {
+ readSheet();
+ }
+
+ Cell c = cells[row][column];
+
+ if (c == null)
+ {
+ c = new EmptyCell(column, row);
+ cells[row][column] = c;
+ }
+
+ return c;
+ }
+
+ /**
+ * Gets the cell whose contents match the string passed in.
+ * If no match is found, then null is returned. The search is performed
+ * on a row by row basis, so the lower the row number, the more
+ * efficiently the algorithm will perform
+ *
+ * @param contents the string to match
+ * @return the Cell whose contents match the paramter, null if not found
+ */
+ public Cell findCell(String contents)
+ {
+ CellFinder cellFinder = new CellFinder(this);
+ return cellFinder.findCell(contents);
+ }
+
+ /**
+ * Gets the cell whose contents match the string passed in.
+ * If no match is found, then null is returned. The search is performed
+ * on a row by row basis, so the lower the row number, the more
+ * efficiently the algorithm will perform
+ *
+ * @param contents the string to match
+ * @param firstCol the first column within the range
+ * @param firstRow the first row of the range
+ * @param lastCol the last column within the range
+ * @param lastRow the last row within the range
+ * @param reverse indicates whether to perform a reverse search or not
+ * @return the Cell whose contents match the parameter, null if not found
+ */
+ public Cell findCell(String contents,
+ int firstCol,
+ int firstRow,
+ int lastCol,
+ int lastRow,
+ boolean reverse)
+ {
+ CellFinder cellFinder = new CellFinder(this);
+ return cellFinder.findCell(contents,
+ firstCol,
+ firstRow,
+ lastCol,
+ lastRow,
+ reverse);
+ }
+
+ /**
+ * Gets the cell whose contents match the regular expressionstring passed in.
+ * If no match is found, then null is returned. The search is performed
+ * on a row by row basis, so the lower the row number, the more
+ * efficiently the algorithm will perform
+ *
+ * @param pattern the regular expression string to match
+ * @param firstCol the first column within the range
+ * @param firstRow the first row of the range
+ * @param lastRow the last row within the range
+ * @param lastCol the last column within the ranage
+ * @param reverse indicates whether to perform a reverse search or not
+ * @return the Cell whose contents match the parameter, null if not found
+ */
+ public Cell findCell(Pattern pattern,
+ int firstCol,
+ int firstRow,
+ int lastCol,
+ int lastRow,
+ boolean reverse)
+ {
+ CellFinder cellFinder = new CellFinder(this);
+ return cellFinder.findCell(pattern,
+ firstCol,
+ firstRow,
+ lastCol,
+ lastRow,
+ reverse);
+ }
+
+ /**
+ * Gets the cell whose contents match the string passed in.
+ * If no match is found, then null is returned. The search is performed
+ * on a row by row basis, so the lower the row number, the more
+ * efficiently the algorithm will perform. This method differs
+ * from the findCell methods in that only cells with labels are
+ * queried - all numerical cells are ignored. This should therefore
+ * improve performance.
+ *
+ * @param contents the string to match
+ * @return the Cell whose contents match the paramter, null if not found
+ */
+ public LabelCell findLabelCell(String contents)
+ {
+ CellFinder cellFinder = new CellFinder(this);
+ return cellFinder.findLabelCell(contents);
+ }
+
+ /**
+ * Returns the number of rows in this sheet
+ *
+ * @return the number of rows in this sheet
+ */
+ public int getRows()
+ {
+ // just in case this has been cleared, but something else holds
+ // a reference to it
+ if (cells == null)
+ {
+ readSheet();
+ }
+
+ return numRows;
+ }
+
+ /**
+ * Returns the number of columns in this sheet
+ *
+ * @return the number of columns in this sheet
+ */
+ public int getColumns()
+ {
+ // just in case this has been cleared, but something else holds
+ // a reference to it
+ if (cells == null)
+ {
+ readSheet();
+ }
+
+ return numCols;
+ }
+
+ /**
+ * Gets all the cells on the specified row. The returned array will
+ * be stripped of all trailing empty cells
+ *
+ * @param row the rows whose cells are to be returned
+ * @return the cells on the given row
+ */
+ public Cell[] getRow(int row)
+ {
+ // just in case this has been cleared, but something else holds
+ // a reference to it
+ if (cells == null)
+ {
+ readSheet();
+ }
+
+ // Find the last non-null cell
+ boolean found = false;
+ int col = numCols - 1;
+ while (col >= 0 && !found)
+ {
+ if (cells[row][col] != null)
+ {
+ found = true;
+ }
+ else
+ {
+ col--;
+ }
+ }
+
+ // Only create entries for non-null cells
+ Cell[] c = new Cell[col + 1];
+
+ for (int i = 0; i <= col; i++)
+ {
+ c[i] = getCell(i, row);
+ }
+ return c;
+ }
+
+ /**
+ * Gets all the cells on the specified column. The returned array
+ * will be stripped of all trailing empty cells
+ *
+ * @param col the column whose cells are to be returned
+ * @return the cells on the specified column
+ */
+ public Cell[] getColumn(int col)
+ {
+ // just in case this has been cleared, but something else holds
+ // a reference to it
+ if (cells == null)
+ {
+ readSheet();
+ }
+
+ // Find the last non-null cell
+ boolean found = false;
+ int row = numRows - 1;
+ while (row >= 0 && !found)
+ {
+ if (cells[row][col] != null)
+ {
+ found = true;
+ }
+ else
+ {
+ row--;
+ }
+ }
+
+ // Only create entries for non-null cells
+ Cell[] c = new Cell[row + 1];
+
+ for (int i = 0; i <= row; i++)
+ {
+ c[i] = getCell(col, i);
+ }
+ return c;
+ }
+
+ /**
+ * Gets the name of this sheet
+ *
+ * @return the name of the sheet
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Sets the name of this sheet
+ *
+ * @param s the sheet name
+ */
+ final void setName(String s)
+ {
+ name = s;
+ }
+
+ /**
+ * Determines whether the sheet is hidden
+ *
+ * @return whether or not the sheet is hidden
+ * @deprecated in favour of the getSettings function
+ */
+ public boolean isHidden()
+ {
+ return hidden;
+ }
+
+ /**
+ * Gets the column info record for the specified column. If no
+ * column is specified, null is returned
+ *
+ * @param col the column
+ * @return the ColumnInfoRecord if specified, NULL otherwise
+ */
+ public ColumnInfoRecord getColumnInfo(int col)
+ {
+ if (!columnInfosInitialized)
+ {
+ // Initialize the array
+ Iterator i = columnInfosArray.iterator();
+ ColumnInfoRecord cir = null;
+ while (i.hasNext())
+ {
+ cir = (ColumnInfoRecord) i.next();
+
+ int startcol = Math.max(0, cir.getStartColumn());
+ int endcol = Math.min(columnInfos.length - 1, cir.getEndColumn());
+
+ for (int c = startcol; c <= endcol; c++)
+ {
+ columnInfos[c] = cir;
+ }
+
+ if (endcol < startcol)
+ {
+ columnInfos[startcol] = cir;
+ }
+ }
+
+ columnInfosInitialized = true;
+ }
+
+ return col < columnInfos.length ? columnInfos[col] : null;
+ }
+
+ /**
+ * Gets all the column info records
+ *
+ * @return the ColumnInfoRecordArray
+ */
+ public ColumnInfoRecord[] getColumnInfos()
+ {
+ // Just chuck all the column infos we have into an array
+ ColumnInfoRecord[] infos = new ColumnInfoRecord[columnInfosArray.size()];
+ for (int i = 0; i < columnInfosArray.size(); i++)
+ {
+ infos[i] = (ColumnInfoRecord) columnInfosArray.get(i);
+ }
+
+ return infos;
+ }
+
+ /**
+ * Sets the visibility of this sheet
+ *
+ * @param h hidden flag
+ */
+ final void setHidden(boolean h)
+ {
+ hidden = h;
+ }
+
+ /**
+ * Clears out the array of cells. This is done for memory allocation
+ * reasons when reading very large sheets
+ */
+ final void clear()
+ {
+ cells = null;
+ mergedCells = null;
+ columnInfosArray.clear();
+ sharedFormulas.clear();
+ hyperlinks.clear();
+ columnInfosInitialized = false;
+
+ if (!workbookSettings.getGCDisabled())
+ {
+ System.gc();
+ }
+ }
+
+ /**
+ * Reads in the contents of this sheet
+ */
+ final void readSheet()
+ {
+ // If this sheet contains only a chart, then set everything to
+ // empty and do not bother parsing the sheet
+ // Thanks to steve.brophy for spotting this
+ if (!sheetBof.isWorksheet())
+ {
+ numRows = 0;
+ numCols = 0;
+ cells = new Cell[0][0];
+ // return;
+ }
+
+ SheetReader reader = new SheetReader(excelFile,
+ sharedStrings,
+ formattingRecords,
+ sheetBof,
+ workbookBof,
+ nineteenFour,
+ workbook,
+ startPosition,
+ this);
+ reader.read();
+
+ // Take stuff that was read in
+ numRows = reader.getNumRows();
+ numCols = reader.getNumCols();
+ cells = reader.getCells();
+ rowProperties = reader.getRowProperties();
+ columnInfosArray = reader.getColumnInfosArray();
+ hyperlinks = reader.getHyperlinks();
+ conditionalFormats = reader.getConditionalFormats();
+ autoFilter = reader.getAutoFilter();
+ charts = reader.getCharts();
+ drawings = reader.getDrawings();
+ dataValidation = reader.getDataValidation();
+ mergedCells = reader.getMergedCells();
+ settings = reader.getSettings();
+ settings.setHidden(hidden);
+ rowBreaks = reader.getRowBreaks();
+ columnBreaks = reader.getColumnBreaks();
+ workspaceOptions = reader.getWorkspaceOptions();
+ plsRecord = reader.getPLS();
+ buttonPropertySet = reader.getButtonPropertySet();
+ maxRowOutlineLevel = reader.getMaxRowOutlineLevel();
+ maxColumnOutlineLevel = reader.getMaxColumnOutlineLevel();
+
+ reader = null;
+
+ if (!workbookSettings.getGCDisabled())
+ {
+ System.gc();
+ }
+
+ if (columnInfosArray.size() > 0)
+ {
+ ColumnInfoRecord cir = (ColumnInfoRecord)
+ columnInfosArray.get(columnInfosArray.size() - 1);
+ columnInfos = new ColumnInfoRecord[cir.getEndColumn() + 1];
+ }
+ else
+ {
+ columnInfos = new ColumnInfoRecord[0];
+ }
+
+ // Add any local names
+ if (localNames != null)
+ {
+ for (Iterator it = localNames.iterator(); it.hasNext() ;)
+ {
+ NameRecord nr = (NameRecord) it.next();
+ if (nr.getBuiltInName() == BuiltInName.PRINT_AREA)
+ {
+ if(nr.getRanges().length > 0)
+ {
+ NameRecord.NameRange rng = nr.getRanges()[0];
+ settings.setPrintArea(rng.getFirstColumn(),
+ rng.getFirstRow(),
+ rng.getLastColumn(),
+ rng.getLastRow());
+ }
+ }
+ else if (nr.getBuiltInName() == BuiltInName.PRINT_TITLES)
+ {
+ // There can be 1 or 2 entries.
+ // Row entries have hardwired column entries (first and last
+ // possible column)
+ // Column entries have hardwired row entries (first and last
+ // possible row)
+ for (int i = 0 ; i < nr.getRanges().length ; i++)
+ {
+ NameRecord.NameRange rng = nr.getRanges()[i];
+ if (rng.getFirstColumn() == 0 && rng.getLastColumn() == 255)
+ {
+ settings.setPrintTitlesRow(rng.getFirstRow(),
+ rng.getLastRow());
+ }
+ else
+ {
+ settings.setPrintTitlesCol(rng.getFirstColumn(),
+ rng.getLastColumn());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the hyperlinks on this sheet
+ *
+ * @return an array of hyperlinks
+ */
+ public Hyperlink[] getHyperlinks()
+ {
+ Hyperlink[] hl = new Hyperlink[hyperlinks.size()];
+
+ for (int i = 0; i < hyperlinks.size(); i++)
+ {
+ hl[i] = (Hyperlink) hyperlinks.get(i);
+ }
+
+ return hl;
+ }
+
+ /**
+ * Gets the cells which have been merged on this sheet
+ *
+ * @return an array of range objects
+ */
+ public Range[] getMergedCells()
+ {
+ if (mergedCells == null)
+ {
+ return new Range[0];
+ }
+
+ return mergedCells;
+ }
+
+ /**
+ * Gets the non-default rows. Used when copying spreadsheets
+ *
+ * @return an array of row properties
+ */
+ public RowRecord[] getRowProperties()
+ {
+ RowRecord[] rp = new RowRecord[rowProperties.size()];
+ for (int i = 0; i < rp.length; i++)
+ {
+ rp[i] = (RowRecord) rowProperties.get(i);
+ }
+
+ return rp;
+ }
+
+ /**
+ * Gets the data validations. Used when copying sheets
+ *
+ * @return the data validations
+ */
+ public DataValidation getDataValidation()
+ {
+ return dataValidation;
+ }
+
+ /**
+ * Gets the row record. Usually called by the cell in the specified
+ * row in order to determine its size
+ *
+ * @param r the row
+ * @return the RowRecord for the specified row
+ */
+ RowRecord getRowInfo(int r)
+ {
+ if (!rowRecordsInitialized)
+ {
+ rowRecords = new RowRecord[getRows()];
+ Iterator i = rowProperties.iterator();
+
+ int rownum = 0;
+ RowRecord rr = null;
+ while (i.hasNext())
+ {
+ rr = (RowRecord) i.next();
+ rownum = rr.getRowNumber();
+ if (rownum < rowRecords.length)
+ {
+ rowRecords[rownum] = rr;
+ }
+ }
+
+ rowRecordsInitialized = true;
+ }
+
+ return r < rowRecords.length ? rowRecords[r] : null;
+ }
+
+ /**
+ * Gets the row breaks. Called when copying sheets
+ *
+ * @return the explicit row breaks
+ */
+ public final int[] getRowPageBreaks()
+ {
+ return rowBreaks;
+ }
+
+ /**
+ * Gets the row breaks. Called when copying sheets
+ *
+ * @return the explicit row breaks
+ */
+ public final int[] getColumnPageBreaks()
+ {
+ return columnBreaks;
+ }
+
+ /**
+ * Gets the charts. Called when copying sheets
+ *
+ * @return the charts on this page
+ */
+ public final Chart[] getCharts()
+ {
+ Chart[] ch = new Chart[charts.size()];
+
+ for (int i = 0; i < ch.length; i++)
+ {
+ ch[i] = (Chart) charts.get(i);
+ }
+ return ch;
+ }
+
+ /**
+ * Gets the drawings. Called when copying sheets
+ *
+ * @return the drawings on this page
+ */
+ public final DrawingGroupObject[] getDrawings()
+ {
+ DrawingGroupObject[] dr = new DrawingGroupObject[drawings.size()];
+ dr = (DrawingGroupObject[]) drawings.toArray(dr);
+ return dr;
+ }
+
+ /**
+ * Determines whether the sheet is protected
+ *
+ * @return whether or not the sheet is protected
+ * @deprecated in favour of the getSettings() api
+ */
+ public boolean isProtected()
+ {
+ return settings.isProtected();
+ }
+
+ /**
+ * Gets the workspace options for this sheet. Called during the copy
+ * process
+ *
+ * @return the workspace options
+ */
+ public WorkspaceInformationRecord getWorkspaceOptions()
+ {
+ return workspaceOptions;
+ }
+
+ /**
+ * Accessor for the sheet settings
+ *
+ * @return the settings for this sheet
+ */
+ public SheetSettings getSettings()
+ {
+ return settings;
+ }
+
+ /**
+ * Accessor for the workbook. In addition to be being used by this package,
+ * it is also used during the importSheet process
+ *
+ * @return the workbook
+ */
+ public WorkbookParser getWorkbook()
+ {
+ return workbook;
+ }
+
+ /**
+ * Gets the column format for the specified column
+ *
+ * @param col the column number
+ * @return the column format, or NULL if the column has no specific format
+ * @deprecated use getColumnView instead
+ */
+ public CellFormat getColumnFormat(int col)
+ {
+ CellView cv = getColumnView(col);
+ return cv.getFormat();
+ }
+
+ /**
+ * Gets the column width for the specified column
+ *
+ * @param col the column number
+ * @return the column width, or the default width if the column has no
+ * specified format
+ */
+ public int getColumnWidth(int col)
+ {
+ return getColumnView(col).getSize() / 256;
+ }
+
+ /**
+ * Gets the column width for the specified column
+ *
+ * @param col the column number
+ * @return the column format, or the default format if no override is
+ specified
+ */
+ public CellView getColumnView(int col)
+ {
+ ColumnInfoRecord cir = getColumnInfo(col);
+ CellView cv = new CellView();
+
+ if (cir != null)
+ {
+ cv.setDimension(cir.getWidth() / 256); //deprecated
+ cv.setSize(cir.getWidth());
+ cv.setHidden(cir.getHidden());
+ cv.setFormat(formattingRecords.getXFRecord(cir.getXFIndex()));
+ }
+ else
+ {
+ cv.setDimension(settings.getDefaultColumnWidth()); //deprecated
+ cv.setSize(settings.getDefaultColumnWidth() * 256);
+ }
+
+ return cv;
+ }
+
+ /**
+ * Gets the row height for the specified column
+ *
+ * @param row the row number
+ * @return the row height, or the default height if the row has no
+ * specified format
+ * @deprecated use getRowView instead
+ */
+ public int getRowHeight(int row)
+ {
+ return getRowView(row).getDimension();
+ }
+
+ /**
+ * Gets the row view for the specified row
+ *
+ * @param row the row number
+ * @return the row format, or the default format if no override is
+ specified
+ */
+ public CellView getRowView(int row)
+ {
+ RowRecord rr = getRowInfo(row);
+
+ CellView cv = new CellView();
+
+ if (rr != null)
+ {
+ cv.setDimension(rr.getRowHeight()); //deprecated
+ cv.setSize(rr.getRowHeight());
+ cv.setHidden(rr.isCollapsed());
+ if (rr.hasDefaultFormat())
+ {
+ cv.setFormat(formattingRecords.getXFRecord(rr.getXFIndex()));
+ }
+ }
+ else
+ {
+ cv.setDimension(settings.getDefaultRowHeight());
+ cv.setSize(settings.getDefaultRowHeight()); //deprecated
+ }
+
+ return cv;
+ }
+
+
+ /**
+ * Used when copying sheets in order to determine the type of this sheet
+ *
+ * @return the BOF Record
+ */
+ public BOFRecord getSheetBof()
+ {
+ return sheetBof;
+ }
+
+ /**
+ * Used when copying sheets in order to determine the type of the containing
+ * workboook
+ *
+ * @return the workbook BOF Record
+ */
+ public BOFRecord getWorkbookBof()
+ {
+ return workbookBof;
+ }
+
+ /**
+ * Accessor for the environment specific print record, invoked when
+ * copying sheets
+ *
+ * @return the environment specific print record
+ */
+ public PLSRecord getPLS()
+ {
+ return plsRecord;
+ }
+
+ /**
+ * Accessor for the button property set, used during copying
+ *
+ * @return the button property set
+ */
+ public ButtonPropertySetRecord getButtonPropertySet()
+ {
+ return buttonPropertySet;
+ }
+
+ /**
+ * Accessor for the number of images on the sheet
+ *
+ * @return the number of images on this sheet
+ */
+ public int getNumberOfImages()
+ {
+ if (images == null)
+ {
+ initializeImages();
+ }
+
+ return images.size();
+ }
+
+ /**
+ * Accessor for the image
+ *
+ * @param i the 0 based image number
+ * @return the image at the specified position
+ */
+ public Image getDrawing(int i)
+ {
+ if (images == null)
+ {
+ initializeImages();
+ }
+
+ return (Image) images.get(i);
+ }
+
+ /**
+ * Initializes the images
+ */
+ private void initializeImages()
+ {
+ if (images != null)
+ {
+ return;
+ }
+
+ images = new ArrayList();
+ DrawingGroupObject[] dgos = getDrawings();
+
+ for (int i = 0; i < dgos.length; i++)
+ {
+ if (dgos[i] instanceof Drawing)
+ {
+ images.add(dgos[i]);
+ }
+ }
+ }
+
+ /**
+ * Used by one of the demo programs for debugging purposes only
+ */
+ public DrawingData getDrawingData()
+ {
+ SheetReader reader = new SheetReader(excelFile,
+ sharedStrings,
+ formattingRecords,
+ sheetBof,
+ workbookBof,
+ nineteenFour,
+ workbook,
+ startPosition,
+ this);
+ reader.read();
+ return reader.getDrawingData();
+ }
+
+ /**
+ * Adds a local name to this shate
+ *
+ * @param nr the local name to add
+ */
+ void addLocalName(NameRecord nr)
+ {
+ if (localNames == null)
+ {
+ localNames = new ArrayList();
+ }
+
+ localNames.add(nr);
+ }
+
+ /**
+ * Gets the conditional formats
+ *
+ * @return the conditional formats
+ */
+ public ConditionalFormat[] getConditionalFormats()
+ {
+ ConditionalFormat[] formats =
+ new ConditionalFormat[conditionalFormats.size()];
+ formats = (ConditionalFormat[]) conditionalFormats.toArray(formats);
+ return formats;
+ }
+
+ /**
+ * Returns the autofilter
+ *
+ * @return the autofilter
+ */
+ public AutoFilter getAutoFilter()
+ {
+ return autoFilter;
+ }
+
+ /**
+ * Accessor for the maximum column outline level. Used during a copy
+ *
+ * @return the maximum column outline level, or 0 if no outlines/groups
+ */
+ public int getMaxColumnOutlineLevel()
+ {
+ return maxColumnOutlineLevel;
+ }
+
+ /**
+ * Accessor for the maximum row outline level. Used during a copy
+ *
+ * @return the maximum row outline level, or 0 if no outlines/groups
+ */
+ public int getMaxRowOutlineLevel()
+ {
+ return maxRowOutlineLevel;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/SheetReader.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/SheetReader.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/SheetReader.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,1849 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.Cell;
+import jxl.CellFeatures;
+import jxl.CellReferenceHelper;
+import jxl.CellType;
+import jxl.DateCell;
+import jxl.HeaderFooter;
+import jxl.Range;
+import jxl.SheetSettings;
+import jxl.WorkbookSettings;
+import jxl.biff.AutoFilter;
+import jxl.biff.AutoFilterInfoRecord;
+import jxl.biff.AutoFilterRecord;
+import jxl.biff.ConditionalFormat;
+import jxl.biff.ConditionalFormatRangeRecord;
+import jxl.biff.ConditionalFormatRecord;
+import jxl.biff.ContinueRecord;
+import jxl.biff.DataValidation;
+import jxl.biff.DataValidityListRecord;
+import jxl.biff.DataValiditySettingsRecord;
+import jxl.biff.FilterModeRecord;
+import jxl.biff.FormattingRecords;
+import jxl.biff.Type;
+import jxl.biff.WorkspaceInformationRecord;
+import jxl.biff.drawing.Button;
+import jxl.biff.drawing.Chart;
+import jxl.biff.drawing.ComboBox;
+import jxl.biff.drawing.Comment;
+import jxl.biff.drawing.Drawing;
+import jxl.biff.drawing.Drawing2;
+import jxl.biff.drawing.DrawingData;
+import jxl.biff.drawing.DrawingDataException;
+import jxl.biff.drawing.MsoDrawingRecord;
+import jxl.biff.drawing.NoteRecord;
+import jxl.biff.drawing.ObjRecord;
+import jxl.biff.drawing.TextObjectRecord;
+import jxl.biff.formula.FormulaException;
+import jxl.format.PageOrder;
+import jxl.format.PageOrientation;
+import jxl.format.PaperSize;
+
+/**
+ * Reads the sheet. This functionality was originally part of the
+ * SheetImpl class, but was separated out in order to simplify the former
+ * class
+ */
+final class SheetReader
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(SheetReader.class);
+
+ /**
+ * The excel file
+ */
+ private File excelFile;
+
+ /**
+ * A handle to the shared string table
+ */
+ private SSTRecord sharedStrings;
+
+ /**
+ * A handle to the sheet BOF record, which indicates the stream type
+ */
+ private BOFRecord sheetBof;
+
+ /**
+ * A handle to the workbook BOF record, which indicates the stream type
+ */
+ private BOFRecord workbookBof;
+
+ /**
+ * A handle to the formatting records
+ */
+ private FormattingRecords formattingRecords;
+
+ /**
+ * The number of rows
+ */
+ private int numRows;
+
+ /**
+ * The number of columns
+ */
+ private int numCols;
+
+ /**
+ * The cells
+ */
+ private Cell[][] cells;
+
+ /**
+ * Any cells which are out of the defined bounds
+ */
+ private ArrayList outOfBoundsCells;
+
+ /**
+ * The start position in the stream of this sheet
+ */
+ private int startPosition;
+
+ /**
+ * The list of non-default row properties
+ */
+ private ArrayList rowProperties;
+
+ /**
+ * An array of column info records. They are held this way before
+ * they are transferred to the more convenient array
+ */
+ private ArrayList columnInfosArray;
+
+ /**
+ * A list of shared formula groups
+ */
+ private ArrayList sharedFormulas;
+
+ /**
+ * A list of hyperlinks on this page
+ */
+ private ArrayList hyperlinks;
+
+ /**
+ * The list of conditional formats on this page
+ */
+ private ArrayList conditionalFormats;
+
+ /**
+ * The autofilter information
+ */
+ private AutoFilter autoFilter;
+
+ /**
+ * A list of merged cells on this page
+ */
+ private Range[] mergedCells;
+
+ /**
+ * The list of data validations on this page
+ */
+ private DataValidation dataValidation;
+
+ /**
+ * The list of charts on this page
+ */
+ private ArrayList charts;
+
+ /**
+ * The list of drawings on this page
+ */
+ private ArrayList drawings;
+
+ /**
+ * The drawing data for the drawings
+ */
+ private DrawingData drawingData;
+
+ /**
+ * Indicates whether or not the dates are based around the 1904 date system
+ */
+ private boolean nineteenFour;
+
+ /**
+ * The PLS print record
+ */
+ private PLSRecord plsRecord;
+
+ /**
+ * The property set record associated with this workbook
+ */
+ private ButtonPropertySetRecord buttonPropertySet;
+
+ /**
+ * The workspace options
+ */
+ private WorkspaceInformationRecord workspaceOptions;
+
+ /**
+ * The horizontal page breaks contained on this sheet
+ */
+ private int[] rowBreaks;
+
+ /**
+ * The vertical page breaks contained on this sheet
+ */
+ private int[] columnBreaks;
+
+ /**
+ * The maximum row outline level
+ */
+ private int maxRowOutlineLevel;
+
+ /**
+ * The maximum column outline level
+ */
+ private int maxColumnOutlineLevel;
+
+ /**
+ * The sheet settings
+ */
+ private SheetSettings settings;
+
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings workbookSettings;
+
+ /**
+ * A handle to the workbook which contains this sheet. Some of the records
+ * need this in order to reference external sheets
+ */
+ private WorkbookParser workbook;
+
+ /**
+ * A handle to the sheet
+ */
+ private SheetImpl sheet;
+
+ /**
+ * Constructor
+ *
+ * @param fr the formatting records
+ * @param sst the shared string table
+ * @param f the excel file
+ * @param sb the bof record which indicates the start of the sheet
+ * @param wb the bof record which indicates the start of the sheet
+ * @param wp the workbook which this sheet belongs to
+ * @param sp the start position of the sheet bof in the excel file
+ * @param sh the sheet
+ * @param nf 1904 date record flag
+ * @exception BiffException
+ */
+ SheetReader(File f,
+ SSTRecord sst,
+ FormattingRecords fr,
+ BOFRecord sb,
+ BOFRecord wb,
+ boolean nf,
+ WorkbookParser wp,
+ int sp,
+ SheetImpl sh)
+ {
+ excelFile = f;
+ sharedStrings = sst;
+ formattingRecords = fr;
+ sheetBof = sb;
+ workbookBof = wb;
+ columnInfosArray = new ArrayList();
+ sharedFormulas = new ArrayList();
+ hyperlinks = new ArrayList();
+ conditionalFormats = new ArrayList();
+ rowProperties = new ArrayList(10);
+ charts = new ArrayList();
+ drawings = new ArrayList();
+ outOfBoundsCells = new ArrayList();
+ nineteenFour = nf;
+ workbook = wp;
+ startPosition = sp;
+ sheet = sh;
+ settings = new SheetSettings(sh);
+ workbookSettings = workbook.getSettings();
+ }
+
+ /**
+ * Adds the cell to the array
+ *
+ * @param cell the cell to add
+ */
+ private void addCell(Cell cell)
+ {
+ // Sometimes multiple cells (eg. MULBLANK) can exceed the
+ // column/row boundaries. Ignore these
+ if (cell.getRow() < numRows && cell.getColumn() < numCols)
+ {
+ if (cells[cell.getRow()][cell.getColumn()] != null)
+ {
+ StringBuffer sb = new StringBuffer();
+ CellReferenceHelper.getCellReference
+ (cell.getColumn(), cell.getRow(), sb);
+ logger.warn("Cell " + sb.toString() +
+ " already contains data");
+ }
+ cells[cell.getRow()][cell.getColumn()] = cell;
+ }
+ else
+ {
+ outOfBoundsCells.add(cell);
+ /*
+ logger.warn("Cell " +
+ CellReferenceHelper.getCellReference
+ (cell.getColumn(), cell.getRow()) +
+ " exceeds defined cell boundaries in Dimension record " +
+ "(" + numCols + "x" + numRows + ")");
+ */
+ }
+ }
+
+ /**
+ * Reads in the contents of this sheet
+ */
+ final void read()
+ {
+ Record r = null;
+ BaseSharedFormulaRecord sharedFormula = null;
+ boolean sharedFormulaAdded = false;
+
+ boolean cont = true;
+
+ // Set the position within the file
+ excelFile.setPos(startPosition);
+
+ // Handles to the last drawing and obj records
+ MsoDrawingRecord msoRecord = null;
+ ObjRecord objRecord = null;
+ boolean firstMsoRecord = true;
+
+ // Handle to the last conditional format record
+ ConditionalFormat condFormat = null;
+
+ // Handle to the autofilter records
+ FilterModeRecord filterMode = null;
+ AutoFilterInfoRecord autoFilterInfo = null;
+
+ // A handle to window2 record
+ Window2Record window2Record = null;
+
+ // A handle to printgridlines record
+ PrintGridLinesRecord printGridLinesRecord = null;
+
+ // A handle to printheaders record
+ PrintHeadersRecord printHeadersRecord = null;
+
+ // Hash map of comments, indexed on objectId. As each corresponding
+ // note record is encountered, these are removed from the array
+ HashMap comments = new HashMap();
+
+ // A list of object ids - used for cross referencing
+ ArrayList objectIds = new ArrayList();
+
+ // A handle to a continue record read in
+ ContinueRecord continueRecord = null;
+
+ while (cont)
+ {
+ r = excelFile.next();
+ Type type = r.getType();
+
+ if (type == Type.UNKNOWN && r.getCode() == 0)
+ {
+ logger.warn("Biff code zero found");
+
+ // Try a dimension record
+ if (r.getLength() == 0xa)
+ {
+ logger.warn("Biff code zero found - trying a dimension record.");
+ r.setType(Type.DIMENSION);
+ }
+ else
+ {
+ logger.warn("Biff code zero found - Ignoring.");
+ }
+ }
+
+ if (type == Type.DIMENSION)
+ {
+ DimensionRecord dr = null;
+
+ if (workbookBof.isBiff8())
+ {
+ dr = new DimensionRecord(r);
+ }
+ else
+ {
+ dr = new DimensionRecord(r, DimensionRecord.biff7);
+ }
+ numRows = dr.getNumberOfRows();
+ numCols = dr.getNumberOfColumns();
+ cells = new Cell[numRows][numCols];
+ }
+ else if (type == Type.LABELSST)
+ {
+ LabelSSTRecord label = new LabelSSTRecord(r,
+ sharedStrings,
+ formattingRecords,
+ sheet);
+ addCell(label);
+ }
+ else if (type == Type.RK || type == Type.RK2)
+ {
+ RKRecord rkr = new RKRecord(r, formattingRecords, sheet);
+
+ if (formattingRecords.isDate(rkr.getXFIndex()))
+ {
+ DateCell dc = new DateRecord
+ (rkr, rkr.getXFIndex(), formattingRecords, nineteenFour, sheet);
+ addCell(dc);
+ }
+ else
+ {
+ addCell(rkr);
+ }
+ }
+ else if (type == Type.HLINK)
+ {
+ HyperlinkRecord hr = new HyperlinkRecord(r, sheet, workbookSettings);
+ hyperlinks.add(hr);
+ }
+ else if (type == Type.MERGEDCELLS)
+ {
+ MergedCellsRecord mc = new MergedCellsRecord(r, sheet);
+ if (mergedCells == null)
+ {
+ mergedCells = mc.getRanges();
+ }
+ else
+ {
+ Range[] newMergedCells =
+ new Range[mergedCells.length + mc.getRanges().length];
+ System.arraycopy(mergedCells, 0, newMergedCells, 0,
+ mergedCells.length);
+ System.arraycopy(mc.getRanges(),
+ 0,
+ newMergedCells, mergedCells.length,
+ mc.getRanges().length);
+ mergedCells = newMergedCells;
+ }
+ }
+ else if (type == Type.MULRK)
+ {
+ MulRKRecord mulrk = new MulRKRecord(r);
+
+ // Get the individual cell records from the multiple record
+ int num = mulrk.getNumberOfColumns();
+ int ixf = 0;
+ for (int i = 0; i < num; i++)
+ {
+ ixf = mulrk.getXFIndex(i);
+
+ NumberValue nv = new NumberValue
+ (mulrk.getRow(),
+ mulrk.getFirstColumn() + i,
+ RKHelper.getDouble(mulrk.getRKNumber(i)),
+ ixf,
+ formattingRecords,
+ sheet);
+
+
+ if (formattingRecords.isDate(ixf))
+ {
+ DateCell dc = new DateRecord(nv,
+ ixf,
+ formattingRecords,
+ nineteenFour,
+ sheet);
+ addCell(dc);
+ }
+ else
+ {
+ nv.setNumberFormat(formattingRecords.getNumberFormat(ixf));
+ addCell(nv);
+ }
+ }
+ }
+ else if (type == Type.NUMBER)
+ {
+ NumberRecord nr = new NumberRecord(r, formattingRecords, sheet);
+
+ if (formattingRecords.isDate(nr.getXFIndex()))
+ {
+ DateCell dc = new DateRecord(nr,
+ nr.getXFIndex(),
+ formattingRecords,
+ nineteenFour, sheet);
+ addCell(dc);
+ }
+ else
+ {
+ addCell(nr);
+ }
+ }
+ else if (type == Type.BOOLERR)
+ {
+ BooleanRecord br = new BooleanRecord(r, formattingRecords, sheet);
+
+ if (br.isError())
+ {
+ ErrorRecord er = new ErrorRecord(br.getRecord(), formattingRecords,
+ sheet);
+ addCell(er);
+ }
+ else
+ {
+ addCell(br);
+ }
+ }
+ else if (type == Type.PRINTGRIDLINES)
+ {
+ printGridLinesRecord = new PrintGridLinesRecord(r);
+ settings.setPrintGridLines(printGridLinesRecord.getPrintGridLines());
+ }
+ else if (type == Type.PRINTHEADERS)
+ {
+ printHeadersRecord = new PrintHeadersRecord(r);
+ settings.setPrintHeaders(printHeadersRecord.getPrintHeaders());
+ }
+ else if (type == Type.WINDOW2)
+ {
+ window2Record = null;
+
+ if (workbookBof.isBiff8())
+ {
+ window2Record = new Window2Record(r);
+ }
+ else
+ {
+ window2Record = new Window2Record(r, Window2Record.biff7);
+ }
+
+ settings.setShowGridLines(window2Record.getShowGridLines());
+ settings.setDisplayZeroValues(window2Record.getDisplayZeroValues());
+ settings.setSelected(true);
+ settings.setPageBreakPreviewMode(window2Record.isPageBreakPreview());
+ }
+ else if (type == Type.PANE)
+ {
+ PaneRecord pr = new PaneRecord(r);
+
+ if (window2Record != null &&
+ window2Record.getFrozen())
+ {
+ settings.setVerticalFreeze(pr.getRowsVisible());
+ settings.setHorizontalFreeze(pr.getColumnsVisible());
+ }
+ }
+ else if (type == Type.CONTINUE)
+ {
+ // don't know what this is for, but keep hold of it anyway
+ continueRecord = new ContinueRecord(r);
+ }
+ else if (type == Type.NOTE)
+ {
+ if (!workbookSettings.getDrawingsDisabled())
+ {
+ NoteRecord nr = new NoteRecord(r);
+
+ // Get the comment for the object id
+ Comment comment = (Comment) comments.remove
+ (new Integer(nr.getObjectId()));
+
+ if (comment == null)
+ {
+ logger.warn(" cannot find comment for note id " +
+ nr.getObjectId() + "...ignoring");
+ }
+ else
+ {
+ comment.setNote(nr);
+
+ drawings.add(comment);
+
+ addCellComment(comment.getColumn(),
+ comment.getRow(),
+ comment.getText(),
+ comment.getWidth(),
+ comment.getHeight());
+ }
+ }
+ }
+ else if (type == Type.ARRAY)
+ {
+ ;
+ }
+ else if (type == Type.PROTECT)
+ {
+ ProtectRecord pr = new ProtectRecord(r);
+ settings.setProtected(pr.isProtected());
+ }
+ else if (type == Type.SHAREDFORMULA)
+ {
+ if (sharedFormula == null)
+ {
+ logger.warn("Shared template formula is null - " +
+ "trying most recent formula template");
+ SharedFormulaRecord lastSharedFormula =
+ (SharedFormulaRecord) sharedFormulas.get(sharedFormulas.size() - 1);
+
+ if (lastSharedFormula != null)
+ {
+ sharedFormula = lastSharedFormula.getTemplateFormula();
+ }
+ }
+
+ SharedFormulaRecord sfr = new SharedFormulaRecord
+ (r, sharedFormula, workbook, workbook, sheet);
+ sharedFormulas.add(sfr);
+ sharedFormula = null;
+ }
+ else if (type == Type.FORMULA || type == Type.FORMULA2)
+ {
+ FormulaRecord fr = new FormulaRecord(r,
+ excelFile,
+ formattingRecords,
+ workbook,
+ workbook,
+ sheet,
+ workbookSettings);
+
+ if (fr.isShared())
+ {
+ BaseSharedFormulaRecord prevSharedFormula = sharedFormula;
+ sharedFormula = (BaseSharedFormulaRecord) fr.getFormula();
+
+ // See if it fits in any of the shared formulas
+ sharedFormulaAdded = addToSharedFormulas(sharedFormula);
+
+ if (sharedFormulaAdded)
+ {
+ sharedFormula = prevSharedFormula;
+ }
+
+ // If we still haven't added the previous base shared formula,
+ // revert it to an ordinary formula and add it to the cell
+ if (!sharedFormulaAdded && prevSharedFormula != null)
+ {
+ // Do nothing. It's possible for the biff file to contain the
+ // record sequence
+ // FORMULA-SHRFMLA-FORMULA-SHRFMLA-FORMULA-FORMULA-FORMULA
+ // ie. it first lists all the formula templates, then it
+ // lists all the individual formulas
+ addCell(revertSharedFormula(prevSharedFormula));
+ }
+ }
+ else
+ {
+ Cell cell = fr.getFormula();
+ try
+ {
+ // See if the formula evaluates to date
+ if (fr.getFormula().getType() == CellType.NUMBER_FORMULA)
+ {
+ NumberFormulaRecord nfr = (NumberFormulaRecord) fr.getFormula();
+ if (formattingRecords.isDate(nfr.getXFIndex()))
+ {
+ cell = new DateFormulaRecord(nfr,
+ formattingRecords,
+ workbook,
+ workbook,
+ nineteenFour,
+ sheet);
+ }
+ }
+
+ addCell(cell);
+ }
+ catch (FormulaException e)
+ {
+ // Something has gone wrong trying to read the formula data eg. it
+ // might be unsupported biff7 data
+ logger.warn
+ (CellReferenceHelper.getCellReference
+ (cell.getColumn(), cell.getRow()) + " " + e.getMessage());
+ }
+ }
+ }
+ else if (type == Type.LABEL)
+ {
+ LabelRecord lr = null;
+
+ if (workbookBof.isBiff8())
+ {
+ lr = new LabelRecord(r, formattingRecords, sheet, workbookSettings);
+ }
+ else
+ {
+ lr = new LabelRecord(r, formattingRecords, sheet, workbookSettings,
+ LabelRecord.biff7);
+ }
+ addCell(lr);
+ }
+ else if (type == Type.RSTRING)
+ {
+ RStringRecord lr = null;
+
+ // RString records are obsolete in biff 8
+ Assert.verify(!workbookBof.isBiff8());
+ lr = new RStringRecord(r, formattingRecords,
+ sheet, workbookSettings,
+ RStringRecord.biff7);
+ addCell(lr);
+ }
+ else if (type == Type.NAME)
+ {
+ ;
+ }
+ else if (type == Type.PASSWORD)
+ {
+ PasswordRecord pr = new PasswordRecord(r);
+ settings.setPasswordHash(pr.getPasswordHash());
+ }
+ else if (type == Type.ROW)
+ {
+ RowRecord rr = new RowRecord(r);
+
+ // See if the row has anything funny about it
+ if (!rr.isDefaultHeight() ||
+ !rr.matchesDefaultFontHeight() ||
+ rr.isCollapsed() ||
+ rr.hasDefaultFormat() ||
+ rr.getOutlineLevel() != 0)
+ {
+ rowProperties.add(rr);
+ }
+ }
+ else if (type == Type.BLANK)
+ {
+ if (!workbookSettings.getIgnoreBlanks())
+ {
+ BlankCell bc = new BlankCell(r, formattingRecords, sheet);
+ addCell(bc);
+ }
+ }
+ else if (type == Type.MULBLANK)
+ {
+ if (!workbookSettings.getIgnoreBlanks())
+ {
+ MulBlankRecord mulblank = new MulBlankRecord(r);
+
+ // Get the individual cell records from the multiple record
+ int num = mulblank.getNumberOfColumns();
+
+ for (int i = 0; i < num; i++)
+ {
+ int ixf = mulblank.getXFIndex(i);
+
+ MulBlankCell mbc = new MulBlankCell
+ (mulblank.getRow(),
+ mulblank.getFirstColumn() + i,
+ ixf,
+ formattingRecords,
+ sheet);
+
+ addCell(mbc);
+ }
+ }
+ }
+ else if (type == Type.SCL)
+ {
+ SCLRecord scl = new SCLRecord(r);
+ settings.setZoomFactor(scl.getZoomFactor());
+ }
+ else if (type == Type.COLINFO)
+ {
+ ColumnInfoRecord cir = new ColumnInfoRecord(r);
+ columnInfosArray.add(cir);
+ }
+ else if (type == Type.HEADER)
+ {
+ HeaderRecord hr = null;
+ if (workbookBof.isBiff8())
+ {
+ hr = new HeaderRecord(r, workbookSettings);
+ }
+ else
+ {
+ hr = new HeaderRecord(r, workbookSettings, HeaderRecord.biff7);
+ }
+
+ HeaderFooter header = new HeaderFooter(hr.getHeader());
+ settings.setHeader(header);
+ }
+ else if (type == Type.FOOTER)
+ {
+ FooterRecord fr = null;
+ if (workbookBof.isBiff8())
+ {
+ fr = new FooterRecord(r, workbookSettings);
+ }
+ else
+ {
+ fr = new FooterRecord(r, workbookSettings, FooterRecord.biff7);
+ }
+
+ HeaderFooter footer = new HeaderFooter(fr.getFooter());
+ settings.setFooter(footer);
+ }
+ else if (type == Type.SETUP)
+ {
+ SetupRecord sr = new SetupRecord(r);
+
+ // If the setup record has its not initialized bit set, then
+ // use the sheet settings default values
+ if (sr.getInitialized())
+ {
+ if (sr.isPortrait())
+ {
+ settings.setOrientation(PageOrientation.PORTRAIT);
+ }
+ else
+ {
+ settings.setOrientation(PageOrientation.LANDSCAPE);
+ }
+ if (sr.isRightDown())
+ {
+ settings.setPageOrder(PageOrder.RIGHT_THEN_DOWN);
+ }
+ else
+ {
+ settings.setPageOrder(PageOrder.DOWN_THEN_RIGHT);
+ }
+ settings.setPaperSize(PaperSize.getPaperSize(sr.getPaperSize()));
+ settings.setHeaderMargin(sr.getHeaderMargin());
+ settings.setFooterMargin(sr.getFooterMargin());
+ settings.setScaleFactor(sr.getScaleFactor());
+ settings.setPageStart(sr.getPageStart());
+ settings.setFitWidth(sr.getFitWidth());
+ settings.setFitHeight(sr.getFitHeight());
+ settings.setHorizontalPrintResolution
+ (sr.getHorizontalPrintResolution());
+ settings.setVerticalPrintResolution(sr.getVerticalPrintResolution());
+ settings.setCopies(sr.getCopies());
+
+ if (workspaceOptions != null)
+ {
+ settings.setFitToPages(workspaceOptions.getFitToPages());
+ }
+ }
+ }
+ else if (type == Type.WSBOOL)
+ {
+ workspaceOptions = new WorkspaceInformationRecord(r);
+ }
+ else if (type == Type.DEFCOLWIDTH)
+ {
+ DefaultColumnWidthRecord dcwr = new DefaultColumnWidthRecord(r);
+ settings.setDefaultColumnWidth(dcwr.getWidth());
+ }
+ else if (type == Type.DEFAULTROWHEIGHT)
+ {
+ DefaultRowHeightRecord drhr = new DefaultRowHeightRecord(r);
+ if (drhr.getHeight() != 0)
+ {
+ settings.setDefaultRowHeight(drhr.getHeight());
+ }
+ }
+ else if (type == Type.CONDFMT)
+ {
+ ConditionalFormatRangeRecord cfrr =
+ new ConditionalFormatRangeRecord(r);
+ condFormat = new ConditionalFormat(cfrr);
+ conditionalFormats.add(condFormat);
+ }
+ else if (type == Type.CF)
+ {
+ ConditionalFormatRecord cfr = new ConditionalFormatRecord(r);
+ condFormat.addCondition(cfr);
+ }
+ else if (type == Type.FILTERMODE)
+ {
+ filterMode = new FilterModeRecord(r);
+ }
+ else if (type == Type.AUTOFILTERINFO)
+ {
+ autoFilterInfo = new AutoFilterInfoRecord(r);
+ }
+ else if (type == Type.AUTOFILTER)
+ {
+ if (!workbookSettings.getAutoFilterDisabled())
+ {
+ AutoFilterRecord af = new AutoFilterRecord(r);
+
+ if (autoFilter == null)
+ {
+ autoFilter = new AutoFilter(filterMode, autoFilterInfo);
+ filterMode = null;
+ autoFilterInfo = null;
+ }
+
+ autoFilter.add(af);
+ }
+ }
+ else if (type == Type.LEFTMARGIN)
+ {
+ MarginRecord m = new LeftMarginRecord(r);
+ settings.setLeftMargin(m.getMargin());
+ }
+ else if (type == Type.RIGHTMARGIN)
+ {
+ MarginRecord m = new RightMarginRecord(r);
+ settings.setRightMargin(m.getMargin());
+ }
+ else if (type == Type.TOPMARGIN)
+ {
+ MarginRecord m = new TopMarginRecord(r);
+ settings.setTopMargin(m.getMargin());
+ }
+ else if (type == Type.BOTTOMMARGIN)
+ {
+ MarginRecord m = new BottomMarginRecord(r);
+ settings.setBottomMargin(m.getMargin());
+ }
+ else if (type == Type.HORIZONTALPAGEBREAKS)
+ {
+ HorizontalPageBreaksRecord dr = null;
+
+ if (workbookBof.isBiff8())
+ {
+ dr = new HorizontalPageBreaksRecord(r);
+ }
+ else
+ {
+ dr = new HorizontalPageBreaksRecord
+ (r, HorizontalPageBreaksRecord.biff7);
+ }
+ rowBreaks = dr.getRowBreaks();
+ }
+ else if (type == Type.VERTICALPAGEBREAKS)
+ {
+ VerticalPageBreaksRecord dr = null;
+
+ if (workbookBof.isBiff8())
+ {
+ dr = new VerticalPageBreaksRecord(r);
+ }
+ else
+ {
+ dr = new VerticalPageBreaksRecord
+ (r, VerticalPageBreaksRecord.biff7);
+ }
+ columnBreaks = dr.getColumnBreaks();
+ }
+ else if (type == Type.PLS)
+ {
+ plsRecord = new PLSRecord(r);
+ }
+ else if (type == Type.DVAL)
+ {
+ if (!workbookSettings.getCellValidationDisabled())
+ {
+ DataValidityListRecord dvlr = new DataValidityListRecord(r);
+ if (dvlr.getObjectId() == -1)
+ {
+ if (msoRecord != null && objRecord == null)
+ {
+ // there is a drop down associated with this data validation
+ if (drawingData == null)
+ {
+ drawingData = new DrawingData();
+ }
+
+ Drawing2 d2 = new Drawing2(msoRecord, drawingData,
+ workbook.getDrawingGroup());
+ drawings.add(d2);
+ msoRecord = null;
+
+ dataValidation = new DataValidation(dvlr);
+ }
+ else
+ {
+ // no drop down
+ dataValidation = new DataValidation(dvlr);
+ }
+ }
+ else if (objectIds.contains(new Integer(dvlr.getObjectId())))
+ {
+ dataValidation = new DataValidation(dvlr);
+ }
+ else
+ {
+ logger.warn("object id " + dvlr.getObjectId() + " referenced " +
+ " by data validity list record not found - ignoring");
+ }
+ }
+ }
+ else if (type == Type.HCENTER)
+ {
+ CentreRecord hr = new CentreRecord(r);
+ settings.setHorizontalCentre(hr.isCentre());
+ }
+ else if (type == Type.VCENTER)
+ {
+ CentreRecord vc = new CentreRecord(r);
+ settings.setVerticalCentre(vc.isCentre());
+ }
+ else if (type == Type.DV)
+ {
+ if (!workbookSettings.getCellValidationDisabled())
+ {
+ DataValiditySettingsRecord dvsr =
+ new DataValiditySettingsRecord(r,
+ workbook,
+ workbook,
+ workbook.getSettings());
+ if (dataValidation != null)
+ {
+ dataValidation.add(dvsr);
+ addCellValidation(dvsr.getFirstColumn(),
+ dvsr.getFirstRow(),
+ dvsr.getLastColumn(),
+ dvsr.getLastRow(),
+ dvsr);
+ }
+ else
+ {
+ logger.warn("cannot add data validity settings");
+ }
+ }
+ }
+ else if (type == Type.OBJ)
+ {
+ objRecord = new ObjRecord(r);
+
+ if (!workbookSettings.getDrawingsDisabled())
+ {
+ // sometimes excel writes out continue records instead of drawing
+ // records, so forcibly hack the stashed continue record into
+ // a drawing record
+ if (msoRecord == null && continueRecord != null)
+ {
+ logger.warn("Cannot find drawing record - using continue record");
+ msoRecord = new MsoDrawingRecord(continueRecord.getRecord());
+ continueRecord = null;
+ }
+ handleObjectRecord(objRecord, msoRecord, comments);
+ objectIds.add(new Integer(objRecord.getObjectId()));
+ }
+
+ // Save chart handling until the chart BOF record appears
+ if (objRecord.getType() != ObjRecord.CHART)
+ {
+ objRecord = null;
+ msoRecord = null;
+ }
+ }
+ else if (type == Type.MSODRAWING)
+ {
+ if (!workbookSettings.getDrawingsDisabled())
+ {
+ if (msoRecord != null)
+ {
+ // For form controls, a rogue MSODRAWING record can crop up
+ // after the main one. Add these into the drawing data
+ drawingData.addRawData(msoRecord.getData());
+ }
+ msoRecord = new MsoDrawingRecord(r);
+
+ if (firstMsoRecord)
+ {
+ msoRecord.setFirst();
+ firstMsoRecord = false;
+ }
+ }
+ }
+ else if (type == Type.BUTTONPROPERTYSET)
+ {
+ buttonPropertySet = new ButtonPropertySetRecord(r);
+ }
+ else if (type == Type.CALCMODE)
+ {
+ CalcModeRecord cmr = new CalcModeRecord(r);
+ settings.setAutomaticFormulaCalculation(cmr.isAutomatic());
+ }
+ else if (type == Type.SAVERECALC)
+ {
+ SaveRecalcRecord cmr = new SaveRecalcRecord(r);
+ settings.setRecalculateFormulasBeforeSave(cmr.getRecalculateOnSave());
+ }
+ else if (type == Type.GUTS)
+ {
+ GuttersRecord gr = new GuttersRecord(r);
+ maxRowOutlineLevel =
+ gr.getRowOutlineLevel() > 0 ? gr.getRowOutlineLevel() - 1 : 0;
+ maxColumnOutlineLevel =
+ gr.getColumnOutlineLevel() > 0 ? gr.getRowOutlineLevel() - 1 : 0;
+ }
+ else if (type == Type.BOF)
+ {
+ BOFRecord br = new BOFRecord(r);
+ Assert.verify(!br.isWorksheet());
+
+ int startpos = excelFile.getPos() - r.getLength() - 4;
+
+ // Skip to the end of the nested bof
+ // Thanks to Rohit for spotting this
+ Record r2 = excelFile.next();
+ while (r2.getCode() != Type.EOF.value)
+ {
+ r2 = excelFile.next();
+ }
+
+ if (br.isChart())
+ {
+ if (!workbook.getWorkbookBof().isBiff8())
+ {
+ logger.warn("only biff8 charts are supported");
+ }
+ else
+ {
+ if (drawingData == null)
+ {
+ drawingData = new DrawingData();
+ }
+
+ if (!workbookSettings.getDrawingsDisabled())
+ {
+ Chart chart = new Chart(msoRecord, objRecord, drawingData,
+ startpos, excelFile.getPos(),
+ excelFile, workbookSettings);
+ charts.add(chart);
+
+ if (workbook.getDrawingGroup() != null)
+ {
+ workbook.getDrawingGroup().add(chart);
+ }
+ }
+ }
+
+ // Reset the drawing records
+ msoRecord = null;
+ objRecord = null;
+ }
+
+ // If this worksheet is just a chart, then the EOF reached
+ // represents the end of the sheet as well as the end of the chart
+ if (sheetBof.isChart())
+ {
+ cont = false;
+ }
+ }
+ else if (type == Type.EOF)
+ {
+ cont = false;
+ }
+ }
+
+ // Restore the file to its accurate position
+ excelFile.restorePos();
+
+ // Add any out of bounds cells
+ if (outOfBoundsCells.size() > 0)
+ {
+ handleOutOfBoundsCells();
+ }
+
+ // Add all the shared formulas to the sheet as individual formulas
+ Iterator i = sharedFormulas.iterator();
+
+ while (i.hasNext())
+ {
+ SharedFormulaRecord sfr = (SharedFormulaRecord) i.next();
+
+ Cell[] sfnr = sfr.getFormulas(formattingRecords, nineteenFour);
+
+ for (int sf = 0; sf < sfnr.length; sf++)
+ {
+ addCell(sfnr[sf]);
+ }
+ }
+
+ // If the last base shared formula wasn't added to the sheet, then
+ // revert it to an ordinary formula and add it
+ if (!sharedFormulaAdded && sharedFormula != null)
+ {
+ addCell(revertSharedFormula(sharedFormula));
+ }
+
+ // If there is a stray msoDrawing record, then flag to the drawing group
+ // that one has been omitted
+ if (msoRecord != null && workbook.getDrawingGroup() != null)
+ {
+ workbook.getDrawingGroup().setDrawingsOmitted(msoRecord, objRecord);
+ }
+
+ // Check that the comments hash is empty
+ if (!comments.isEmpty())
+ {
+ logger.warn("Not all comments have a corresponding Note record");
+ }
+ }
+
+ /**
+ * Sees if the shared formula belongs to any of the shared formula
+ * groups
+ *
+ * @param fr the candidate shared formula
+ * @return TRUE if the formula was added, FALSE otherwise
+ */
+ private boolean addToSharedFormulas(BaseSharedFormulaRecord fr)
+ {
+ boolean added = false;
+ SharedFormulaRecord sfr = null;
+
+ for (int i=0, size=sharedFormulas.size(); i row && cells[row].length > col)
+ {
+ c = cells[row][col];
+ }
+
+ if (c == null)
+ {
+ logger.warn("Cell at " +
+ CellReferenceHelper.getCellReference(col, row) +
+ " not present - adding a blank");
+ MulBlankCell mbc = new MulBlankCell(row,
+ col,
+ 0,
+ formattingRecords,
+ sheet);
+ CellFeatures cf = new CellFeatures();
+ cf.setValidationSettings(dvsr);
+ mbc.setCellFeatures(cf);
+ addCell(mbc);
+
+ return;
+ }
+
+ if (c instanceof CellFeaturesAccessor)
+ {
+ CellFeaturesAccessor cv = (CellFeaturesAccessor) c;
+ CellFeatures cf = cv.getCellFeatures();
+
+ if (cf == null)
+ {
+ cf = new CellFeatures();
+ cv.setCellFeatures(cf);
+ }
+
+ cf.setValidationSettings(dvsr);
+ }
+ else
+ {
+ logger.warn("Not able to add comment to cell type " +
+ c.getClass().getName() +
+ " at " + CellReferenceHelper.getCellReference(col, row));
+ }
+ }
+ }
+ }
+
+ /**
+ * Reads in the object record
+ *
+ * @param objRecord the obj record
+ * @param msoRecord the mso drawing record read in earlier
+ * @param comments the hash map of comments
+ */
+ private void handleObjectRecord(ObjRecord objRecord,
+ MsoDrawingRecord msoRecord,
+ HashMap comments)
+ {
+ if (msoRecord == null)
+ {
+ logger.warn("Object record is not associated with a drawing " +
+ " record - ignoring");
+ return;
+ }
+
+ try
+ {
+ // Handle images
+ if (objRecord.getType() == ObjRecord.PICTURE)
+ {
+ if (drawingData == null)
+ {
+ drawingData = new DrawingData();
+ }
+
+ Drawing drawing = new Drawing(msoRecord,
+ objRecord,
+ drawingData,
+ workbook.getDrawingGroup(),
+ sheet);
+ drawings.add(drawing);
+ return;
+ }
+
+ // Handle comments
+ if (objRecord.getType() == ObjRecord.EXCELNOTE)
+ {
+ if (drawingData == null)
+ {
+ drawingData = new DrawingData();
+ }
+
+ Comment comment = new Comment(msoRecord,
+ objRecord,
+ drawingData,
+ workbook.getDrawingGroup(),
+ workbookSettings);
+
+ // Sometimes Excel writes out Continue records instead of drawing
+ // records, so forcibly hack all of these into a drawing record
+ Record r2 = excelFile.next();
+ if (r2.getType() == Type.MSODRAWING || r2.getType() == Type.CONTINUE)
+ {
+ MsoDrawingRecord mso = new MsoDrawingRecord(r2);
+ comment.addMso(mso);
+ r2 = excelFile.next();
+ }
+ Assert.verify(r2.getType() == Type.TXO);
+ TextObjectRecord txo = new TextObjectRecord(r2);
+ comment.setTextObject(txo);
+
+ r2 = excelFile.next();
+ Assert.verify(r2.getType() == Type.CONTINUE);
+ ContinueRecord text = new ContinueRecord(r2);
+ comment.setText(text);
+
+ r2 = excelFile.next();
+ if (r2.getType() == Type.CONTINUE)
+ {
+ ContinueRecord formatting = new ContinueRecord(r2);
+ comment.setFormatting(formatting);
+ }
+
+ comments.put(new Integer(comment.getObjectId()), comment);
+ return;
+ }
+
+ // Handle combo boxes
+ if (objRecord.getType() == ObjRecord.COMBOBOX)
+ {
+ if (drawingData == null)
+ {
+ drawingData = new DrawingData();
+ }
+
+ ComboBox comboBox = new ComboBox(msoRecord,
+ objRecord,
+ drawingData,
+ workbook.getDrawingGroup(),
+ workbookSettings);
+ drawings.add(comboBox);
+ return;
+ }
+
+ // Handle form buttons
+ if (objRecord.getType() == ObjRecord.BUTTON)
+ {
+ if (drawingData == null)
+ {
+ drawingData = new DrawingData();
+ }
+
+ Button button = new Button(msoRecord,
+ objRecord,
+ drawingData,
+ workbook.getDrawingGroup(),
+ workbookSettings);
+
+ Record r2 = excelFile.next();
+ if (r2.getType() == Type.MSODRAWING)
+ {
+ MsoDrawingRecord mso = new MsoDrawingRecord(r2);
+ button.addMso(mso);
+ r2 = excelFile.next();
+ }
+ Assert.verify(r2.getType() == Type.TXO);
+ TextObjectRecord txo = new TextObjectRecord(r2);
+ button.setTextObject(txo);
+
+ r2 = excelFile.next();
+ Assert.verify(r2.getType() == Type.CONTINUE);
+ ContinueRecord text = new ContinueRecord(r2);
+ button.setText(text);
+
+ r2 = excelFile.next();
+ if (r2.getType() == Type.CONTINUE)
+ {
+ ContinueRecord formatting = new ContinueRecord(r2);
+ button.setFormatting(formatting);
+ }
+
+ drawings.add(button);
+
+ return;
+ }
+
+ // Handle other types
+ if (objRecord.getType() != ObjRecord.CHART)
+ {
+ logger.warn(objRecord.getType() + " on sheet \"" +
+ sheet.getName() +
+ "\" not supported - omitting");
+
+ if (drawingData == null)
+ {
+ drawingData = new DrawingData();
+ }
+
+ drawingData.addData(msoRecord.getData());
+
+ if (workbook.getDrawingGroup() != null) // can be null for Excel 95
+ {
+ workbook.getDrawingGroup().setDrawingsOmitted(msoRecord,
+ objRecord);
+ }
+
+ return;
+ }
+ }
+ catch (DrawingDataException e)
+ {
+ logger.warn(e.getMessage() +
+ "...disabling drawings for the remainder of the workbook");
+ workbookSettings.setDrawingsDisabled(true);
+ }
+ }
+
+ /**
+ * Gets the drawing data - for use as part of the Escher debugging tool
+ */
+ DrawingData getDrawingData()
+ {
+ return drawingData;
+ }
+
+ /**
+ * Handle any cells which fall outside of the bounds specified within
+ * the dimension record
+ */
+ private void handleOutOfBoundsCells()
+ {
+ int resizedRows = numRows;
+ int resizedCols = numCols;
+
+ // First, determine the new bounds
+ for (Iterator i = outOfBoundsCells.iterator() ; i.hasNext() ;)
+ {
+ Cell cell = (Cell) i.next();
+ resizedRows = Math.max(resizedRows, cell.getRow() + 1);
+ resizedCols = Math.max(resizedCols, cell.getColumn() + 1);
+ }
+
+ logger.warn("Some cells exceeded the specified bounds. Resizing " +
+ "sheet dimensions from " +
+ numCols + "x"+numRows + " to " +
+ resizedCols + "x" + resizedRows);
+
+ // Resize the columns, if necessary
+ if (resizedCols > numCols)
+ {
+ for (int r = 0 ; r < numRows ; r++)
+ {
+ Cell[] newRow = new Cell[resizedCols];
+ Cell[] oldRow = cells[r];
+ System.arraycopy(oldRow, 0, newRow, 0, oldRow.length);
+ cells[r] = newRow;
+ }
+ }
+
+ // Resize the rows, if necessary
+ if (resizedRows > numRows)
+ {
+ Cell[][] newCells = new Cell[resizedRows][];
+ System.arraycopy(cells, 0, newCells, 0, cells.length);
+ cells = newCells;
+
+ // Create the new rows
+ for (int i = numRows; i < resizedRows; i++)
+ {
+ newCells[i] = new Cell[resizedCols];
+ }
+ }
+
+ numRows = resizedRows;
+ numCols = resizedCols;
+
+ // Now add all the out of bounds cells into the new cells
+ for (Iterator i = outOfBoundsCells.iterator(); i.hasNext(); )
+ {
+ Cell cell = (Cell) i.next();
+ addCell(cell);
+ }
+
+ outOfBoundsCells.clear();
+ }
+
+ /**
+ * Accessor for the maximum column outline level
+ *
+ * @return the maximum column outline level, or 0 if no outlines/groups
+ */
+ public int getMaxColumnOutlineLevel()
+ {
+ return maxColumnOutlineLevel;
+ }
+
+ /**
+ * Accessor for the maximum row outline level
+ *
+ * @return the maximum row outline level, or 0 if no outlines/groups
+ */
+ public int getMaxRowOutlineLevel()
+ {
+ return maxRowOutlineLevel;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/SortRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/SortRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/SortRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,179 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan, Al Mantei
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.RecordData;
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+
+/**
+ * A storage area for the last Sort dialog box area
+ */
+public class SortRecord extends RecordData
+{
+ private int col1Size;
+ private int col2Size;
+ private int col3Size;
+ private String col1Name;
+ private String col2Name;
+ private String col3Name;
+ private byte optionFlags;
+ private boolean sortColumns = false;
+ private boolean sortKey1Desc = false;
+ private boolean sortKey2Desc = false;
+ private boolean sortKey3Desc = false;
+ private boolean sortCaseSensitive = false;
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param r the raw data
+ */
+ public SortRecord(Record r)
+ {
+ super(Type.SORT);
+
+ byte[] data = r.getData();
+
+ optionFlags = data[0];
+
+ sortColumns = ((optionFlags & 0x01) != 0);
+ sortKey1Desc = ((optionFlags & 0x02) != 0);
+ sortKey2Desc = ((optionFlags & 0x04) != 0);
+ sortKey3Desc = ((optionFlags & 0x08) != 0);
+ sortCaseSensitive = ((optionFlags & 0x10) != 0);
+
+ // data[1] contains sort list index - not implemented...
+
+ col1Size = data[2];
+ col2Size = data[3];
+ col3Size = data[4];
+ int curPos = 5;
+ if (data[curPos++] == 0x00)
+ {
+ col1Name = new String(data, curPos, col1Size);
+ curPos += col1Size;
+ }
+ else
+ {
+ col1Name = StringHelper.getUnicodeString(data, col1Size, curPos);
+ curPos += col1Size * 2;
+ }
+
+ if (col2Size > 0)
+ {
+ if (data[curPos++] == 0x00)
+ {
+ col2Name = new String(data, curPos, col2Size);
+ curPos += col2Size;
+ }
+ else
+ {
+ col2Name = StringHelper.getUnicodeString(data, col2Size, curPos);
+ curPos += col2Size * 2;
+ }
+ }
+ else
+ {
+ col2Name = "";
+ }
+ if (col3Size > 0)
+ {
+ if (data[curPos++] == 0x00)
+ {
+ col3Name = new String(data, curPos, col3Size);
+ curPos += col3Size;
+ }
+ else
+ {
+ col3Name = StringHelper.getUnicodeString(data, col3Size, curPos);
+ curPos += col3Size * 2;
+ }
+ }
+ else
+ {
+ col3Name = "";
+ }
+ }
+
+ /**
+ * Accessor for the 1st Sort Column Name
+ *
+ * @return the 1st Sort Column Name
+ */
+ public String getSortCol1Name() {
+ return col1Name;
+ }
+ /**
+ * Accessor for the 2nd Sort Column Name
+ *
+ * @return the 2nd Sort Column Name
+ */
+ public String getSortCol2Name() {
+ return col2Name;
+ }
+ /**
+ * Accessor for the 3rd Sort Column Name
+ *
+ * @return the 3rd Sort Column Name
+ */
+ public String getSortCol3Name() {
+ return col3Name;
+ }
+ /**
+ * Accessor for the Sort by Columns flag
+ *
+ * @return the Sort by Columns flag
+ */
+ public boolean getSortColumns() {
+ return sortColumns;
+ }
+ /**
+ * Accessor for the Sort Column 1 Descending flag
+ *
+ * @return the Sort Column 1 Descending flag
+ */
+ public boolean getSortKey1Desc() {
+ return sortKey1Desc;
+ }
+ /**
+ * Accessor for the Sort Column 2 Descending flag
+ *
+ * @return the Sort Column 2 Descending flag
+ */
+ public boolean getSortKey2Desc() {
+ return sortKey2Desc;
+ }
+ /**
+ * Accessor for the Sort Column 3 Descending flag
+ *
+ * @return the Sort Column 3 Descending flag
+ */
+ public boolean getSortKey3Desc() {
+ return sortKey3Desc;
+ }
+ /**
+ * Accessor for the Sort Case Sensitivity flag
+ *
+ * @return the Sort Case Secsitivity flag
+ */
+ public boolean getSortCaseSensitive() {
+ return sortCaseSensitive;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/StringFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/StringFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/StringFormulaRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,290 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Assert;
+import common.Logger;
+
+
+import jxl.CellType;
+import jxl.LabelCell;
+import jxl.StringFormulaCell;
+import jxl.WorkbookSettings;
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.IntegerHelper;
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.formula.ExternalSheet;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+
+/**
+ * A string formula's last calculated value
+ */
+class StringFormulaRecord extends CellValue
+ implements LabelCell, FormulaData, StringFormulaCell
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(StringFormulaRecord.class);
+
+ /**
+ * The last calculated value of the formula
+ */
+ private String value;
+
+ /**
+ * A handle to the class needed to access external sheets
+ */
+ private ExternalSheet externalSheet;
+
+ /**
+ * A handle to the name table
+ */
+ private WorkbookMethods nameTable;
+
+ /**
+ * The formula as an excel string
+ */
+ private String formulaString;
+
+ /**
+ * The raw data
+ */
+ private byte[] data;
+
+ /**
+ * Constructs this object from the raw data. We need to use the excelFile
+ * to retrieve the String record which follows this formula record
+ *
+ * @param t the raw data
+ * @param excelFile the excel file
+ * @param fr the formatting records
+ * @param es the external sheet records
+ * @param nt the workbook
+ * @param si the sheet impl
+ * @param ws the workbook settings
+ */
+ public StringFormulaRecord(Record t, File excelFile,
+ FormattingRecords fr,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ SheetImpl si,
+ WorkbookSettings ws)
+ {
+ super(t, fr, si);
+
+ externalSheet = es;
+ nameTable = nt;
+
+ data = getRecord().getData();
+
+ int pos = excelFile.getPos();
+
+ // Look for the string record in one of the records after the
+ // formula. Put a cap on it to prevent looping
+
+ Record nextRecord = excelFile.next();
+ int count = 0;
+ while (nextRecord.getType() != Type.STRING && count < 4)
+ {
+ nextRecord = excelFile.next();
+ count++;
+ }
+ Assert.verify(count < 4, " @ " + pos);
+ byte[] stringData = nextRecord.getData();
+
+ // Read in any continuation records
+ nextRecord = excelFile.peek();
+ while (nextRecord.getType() == Type.CONTINUE)
+ {
+ nextRecord = excelFile.next(); // move the pointer within the data
+ byte[] d = new byte[stringData.length + nextRecord.getLength() - 1];
+ System.arraycopy(stringData, 0, d, 0, stringData.length);
+ System.arraycopy(nextRecord.getData(), 1, d,
+ stringData.length, nextRecord.getLength() - 1);
+ stringData = d;
+ nextRecord = excelFile.peek();
+ }
+ readString(stringData, ws);
+ }
+
+ /**
+ * Constructs this object from the raw data. Used when reading in formula
+ * strings which evaluate to null (in the case of some IF statements)
+ *
+ * @param t the raw data
+ * @param fr the formatting records
+ * @param es the external sheet records
+ * @param nt the workbook
+ * @param si the sheet impl
+ * @param ws the workbook settings
+ */
+ public StringFormulaRecord(Record t,
+ FormattingRecords fr,
+ ExternalSheet es,
+ WorkbookMethods nt,
+ SheetImpl si)
+ {
+ super(t, fr, si);
+
+ externalSheet = es;
+ nameTable = nt;
+
+ data = getRecord().getData();
+ value = "";
+ }
+
+
+ /**
+ * Reads in the string
+ *
+ * @param d the data
+ * @param ws the workbook settings
+ */
+ private void readString(byte[] d, WorkbookSettings ws)
+ {
+ int pos = 0;
+ int chars = IntegerHelper.getInt(d[0], d[1]);
+
+ if (chars == 0)
+ {
+ value="";
+ return;
+ }
+ pos += 2;
+ int optionFlags = d[pos];
+ pos++;
+
+ if ((optionFlags & 0xf) != optionFlags)
+ {
+ // Uh oh - looks like a plain old string, not unicode
+ // Recalculate all the positions
+ pos = 0;
+ chars = IntegerHelper.getInt(d[0], (byte) 0);
+ optionFlags = d[1];
+ pos = 2;
+ }
+
+ // See if it is an extended string
+ boolean extendedString = ((optionFlags & 0x04) != 0);
+
+ // See if string contains formatting information
+ boolean richString = ((optionFlags & 0x08) != 0);
+
+ if (richString)
+ {
+ pos += 2;
+ }
+
+ if (extendedString)
+ {
+ pos += 4;
+ }
+
+ // See if string is ASCII (compressed) or unicode
+ boolean asciiEncoding = ((optionFlags & 0x01) == 0);
+
+ if (asciiEncoding)
+ {
+ value = StringHelper.getString(d, chars, pos, ws);
+ }
+ else
+ {
+ value = StringHelper.getUnicodeString(d, chars, pos);
+ }
+ }
+
+ /**
+ * Interface method which returns the value
+ *
+ * @return the last calculated value of the formula
+ */
+ public String getContents()
+ {
+ return value;
+ }
+
+ /**
+ * Interface method which returns the value
+ *
+ * @return the last calculated value of the formula
+ */
+ public String getString()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the cell type
+ *
+ * @return The cell type
+ */
+ public CellType getType()
+ {
+ return CellType.STRING_FORMULA;
+ }
+
+ /**
+ * Gets the raw bytes for the formula. This will include the
+ * parsed tokens array
+ *
+ * @return the raw record data
+ */
+ public byte[] getFormulaData() throws FormulaException
+ {
+ if (!getSheet().getWorkbook().getWorkbookBof().isBiff8())
+ {
+ throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
+ }
+
+ // Lop off the standard information
+ byte[] d = new byte[data.length - 6];
+ System.arraycopy(data, 6, d, 0, data.length - 6);
+
+ return d;
+ }
+
+ /**
+ * Gets the formula as an excel string
+ *
+ * @return the formula as an excel string
+ * @exception FormulaException
+ */
+ public String getFormula() throws FormulaException
+ {
+ if (formulaString == null)
+ {
+ byte[] tokens = new byte[data.length - 22];
+ System.arraycopy(data, 22, tokens, 0, tokens.length);
+ FormulaParser fp = new FormulaParser
+ (tokens, this, externalSheet, nameTable,
+ getSheet().getWorkbook().getSettings());
+ fp.parse();
+ formulaString = fp.getFormula();
+ }
+
+ return formulaString;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/SupbookRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/SupbookRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/SupbookRecord.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,338 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+import jxl.biff.StringHelper;
+
+/**
+ * A record containing the references to the various sheets (internal and
+ * external) referenced by formulas in this workbook
+ */
+public class SupbookRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(SupbookRecord.class);
+
+ /**
+ * The type of this supbook record
+ */
+ private Type type;
+
+ /**
+ * The number of sheets - internal & external supbooks only
+ */
+ private int numSheets;
+
+ /**
+ * The name of the external file
+ */
+ private String fileName;
+
+ /**
+ * The names of the external sheets
+ */
+ private String[] sheetNames;
+
+ /**
+ * The type of supbook this refers to
+ */
+ private static class Type {};
+
+
+ public static final Type INTERNAL = new Type();
+ public static final Type EXTERNAL = new Type();
+ public static final Type ADDIN = new Type();
+ public static final Type LINK = new Type();
+ public static final Type UNKNOWN = new Type();
+
+ /**
+ * Constructs this object from the raw data
+ *
+ * @param t the raw data
+ * @param ws the workbook settings
+ */
+ SupbookRecord(Record t, WorkbookSettings ws)
+ {
+ super(t);
+ byte[] data = getRecord().getData();
+
+ // First deduce the type
+ if (data.length == 4)
+ {
+ if (data[2] == 0x01 && data[3] == 0x04)
+ {
+ type = INTERNAL;
+ }
+ else if (data[2] == 0x01 && data[3] == 0x3a)
+ {
+ type = ADDIN;
+ }
+ else
+ {
+ type = UNKNOWN;
+ }
+ }
+ else if (data[0] == 0 && data[1] == 0)
+ {
+ type = LINK;
+ }
+ else
+ {
+ type = EXTERNAL;
+ }
+
+ if (type == INTERNAL)
+ {
+ numSheets = IntegerHelper.getInt(data[0], data[1]);
+ }
+
+ if (type == EXTERNAL)
+ {
+ readExternal(data, ws);
+ }
+ }
+
+ /**
+ * Reads the external data records
+ *
+ * @param data the data
+ * @param ws the workbook settings
+ */
+ private void readExternal(byte[] data, WorkbookSettings ws)
+ {
+ numSheets = IntegerHelper.getInt(data[0], data[1]);
+
+ // subtract file name encoding from the length
+ int ln = IntegerHelper.getInt(data[2], data[3]) - 1;
+ int pos = 0;
+
+ if (data[4] == 0)
+ {
+ // non-unicode string
+ int encoding = data[5];
+ pos = 6;
+ if (encoding == 0)
+ {
+ fileName = StringHelper.getString(data, ln, pos, ws);
+ pos += ln;
+ }
+ else
+ {
+ fileName = getEncodedFilename(data, ln, pos);
+ pos += ln;
+ }
+ }
+ else
+ {
+ // unicode string
+ int encoding = IntegerHelper.getInt(data[5], data[6]);
+ pos = 7;
+ if (encoding == 0)
+ {
+ fileName = StringHelper.getUnicodeString(data, ln, pos);
+ pos += ln * 2;
+ }
+ else
+ {
+ fileName = getUnicodeEncodedFilename(data, ln, pos);
+ pos += ln * 2;
+ }
+ }
+
+ sheetNames = new String[numSheets];
+
+ for (int i = 0; i < sheetNames.length; i++)
+ {
+ ln = IntegerHelper.getInt(data[pos], data[pos + 1]);
+
+ if (data[pos + 2] == 0x0)
+ {
+ sheetNames[i] = StringHelper.getString(data, ln, pos + 3, ws);
+ pos += ln + 3;
+ }
+ else if (data[pos + 2] == 0x1)
+ {
+ sheetNames[i] = StringHelper.getUnicodeString(data, ln, pos + 3);
+ pos += ln * 2 + 3;
+ }
+ }
+ }
+
+ /**
+ * Gets the type of this supbook record
+ *
+ * @return the type of this supbook
+ */
+ public Type getType()
+ {
+ return type;
+ }
+
+ /**
+ * Gets the number of sheets. This will only be non-zero for internal
+ * and external supbooks
+ *
+ * @return the number of sheets
+ */
+ public int getNumberOfSheets()
+ {
+ return numSheets;
+ }
+
+ /**
+ * Gets the name of the external file
+ *
+ * @return the name of the external file
+ */
+ public String getFileName()
+ {
+ return fileName;
+ }
+
+ /**
+ * Gets the name of the external sheet
+ *
+ * @param i the index of the external sheet
+ * @return the name of the sheet
+ */
+ public String getSheetName(int i)
+ {
+ return sheetNames[i];
+ }
+
+ /**
+ * Gets the data - used when copying a spreadsheet
+ *
+ * @return the raw external sheet data
+ */
+ public byte[] getData()
+ {
+ return getRecord().getData();
+ }
+
+ /**
+ * Gets the encoded string from the data array
+ *
+ * @param data the data
+ * @param ln length of the string
+ * @param pos the position in the array
+ * @return the string
+ */
+ private String getEncodedFilename(byte[] data, int ln, int pos)
+ {
+ StringBuffer buf = new StringBuffer();
+ int endpos = pos + ln;
+ while (pos < endpos)
+ {
+ char c = (char) data[pos];
+
+ if (c == '\u0001')
+ {
+ // next character is a volume letter
+ pos++;
+ c = (char) data[pos];
+ buf.append(c);
+ buf.append(":\\\\");
+ }
+ else if (c == '\u0002')
+ {
+ // file is on the same volume
+ buf.append('\\');
+ }
+ else if (c == '\u0003')
+ {
+ // down directory
+ buf.append('\\');
+ }
+ else if (c == '\u0004')
+ {
+ // up directory
+ buf.append("..\\");
+ }
+ else
+ {
+ // just add on the character
+ buf.append(c);
+ }
+
+ pos++;
+ }
+
+ return buf.toString();
+ }
+
+ /**
+ * Gets the encoded string from the data array
+ *
+ * @param data the data
+ * @param ln length of the string
+ * @param pos the position in the array
+ * @return the string
+ */
+ private String getUnicodeEncodedFilename(byte[] data, int ln, int pos)
+ {
+ StringBuffer buf = new StringBuffer();
+ int endpos = pos + ln * 2;
+ while (pos < endpos)
+ {
+ char c = (char) IntegerHelper.getInt(data[pos], data[pos + 1]);
+
+ if (c == '\u0001')
+ {
+ // next character is a volume letter
+ pos += 2;
+ c = (char) IntegerHelper.getInt(data[pos], data[pos + 1]);
+ buf.append(c);
+ buf.append(":\\\\");
+ }
+ else if (c == '\u0002')
+ {
+ // file is on the same volume
+ buf.append('\\');
+ }
+ else if (c == '\u0003')
+ {
+ // down directory
+ buf.append('\\');
+ }
+ else if (c == '\u0004')
+ {
+ // up directory
+ buf.append("..\\");
+ }
+ else
+ {
+ // just add on the character
+ buf.append(c);
+ }
+
+ pos += 2;
+ }
+
+ return buf.toString();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/TopMarginRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/TopMarginRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/TopMarginRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,37 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import jxl.biff.Type;
+
+/**
+ * Record for the left margin settings
+ */
+class TopMarginRecord extends MarginRecord
+{
+ /**
+ * Constructor
+ * @param r the record
+ */
+ TopMarginRecord(Record r)
+ {
+ super(Type.TOPMARGIN, r);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/VerticalPageBreaksRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/VerticalPageBreaksRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/VerticalPageBreaksRecord.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,108 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * Contains the cell dimensions of this worksheet
+ */
+class VerticalPageBreaksRecord extends RecordData
+{
+ /**
+ * The logger
+ */
+ private final Logger logger = Logger.getLogger
+ (VerticalPageBreaksRecord.class);
+
+ /**
+ * The row page breaks
+ */
+ private int[] columnBreaks;
+
+ /**
+ * Dummy indicators for overloading the constructor
+ */
+ private static class Biff7 {};
+ public static Biff7 biff7 = new Biff7();
+
+ /**
+ * Constructs the dimensions from the raw data
+ *
+ * @param t the raw data
+ */
+ public VerticalPageBreaksRecord(Record t)
+ {
+ super(t);
+
+ byte[] data = t.getData();
+
+ int numbreaks = IntegerHelper.getInt(data[0], data[1]);
+ int pos = 2;
+ columnBreaks = new int[numbreaks];
+
+ for (int i = 0; i < numbreaks; i++)
+ {
+ columnBreaks[i] = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ pos += 6;
+ }
+ }
+
+ /**
+ * Constructs the dimensions from the raw data
+ *
+ * @param t the raw data
+ * @param biff7 an indicator to initialise this record for biff 7 format
+ */
+ public VerticalPageBreaksRecord(Record t, Biff7 biff7)
+ {
+ super(t);
+
+ byte[] data = t.getData();
+ int numbreaks = IntegerHelper.getInt(data[0], data[1]);
+ int pos = 2;
+ columnBreaks = new int[numbreaks];
+ for (int i = 0; i < numbreaks; i++)
+ {
+ columnBreaks[i] = IntegerHelper.getInt(data[pos], data[pos + 1]);
+ pos += 2;
+ }
+ }
+
+ /**
+ * Gets the row breaks
+ *
+ * @return the row breaks on the current sheet
+ */
+ public int[] getColumnBreaks()
+ {
+ return columnBreaks;
+ }
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/Window2Record.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/Window2Record.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/Window2Record.java 17 Aug 2012 14:50:56 -0000 1.1
@@ -0,0 +1,208 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import common.Logger;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.RecordData;
+
+/**
+ * Contains the cell dimensions of this worksheet
+ */
+class Window2Record extends RecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(Window2Record.class);
+
+ /**
+ * Selected flag
+ */
+ private boolean selected;
+ /**
+ * Show grid lines flag
+ */
+ private boolean showGridLines;
+ /**
+ * Display zero values flag
+ */
+ private boolean displayZeroValues;
+ /**
+ * The window contains frozen panes
+ */
+ private boolean frozenPanes;
+ /**
+ * The window contains panes that are frozen but not split
+ */
+ private boolean frozenNotSplit;
+ /**
+ * The view mode: normal or pagebreakpreview
+ */
+ private boolean pageBreakPreviewMode;
+
+ /**
+ * The page break preview magnification
+ */
+ private int pageBreakPreviewMagnification;
+
+ /**
+ * The normal view magnification
+ */
+ private int normalMagnification;
+
+ // Dummy overload
+ private static class Biff7 {};
+ public static final Biff7 biff7 = new Biff7();
+
+ /**
+ * Constructs the dimensions from the raw data
+ *
+ * @param t the raw data
+ */
+ public Window2Record(Record t)
+ {
+ super(t);
+ byte[] data = t.getData();
+
+ int options = IntegerHelper.getInt(data[0], data[1]);
+
+ selected = ((options & 0x200) != 0);
+ showGridLines = ((options & 0x02) != 0);
+ frozenPanes = ((options & 0x08) != 0);
+ displayZeroValues = ((options & 0x10) != 0);
+ frozenNotSplit = ((options & 0x100) != 0);
+ pageBreakPreviewMode = ((options & 0x800) != 0);
+
+ pageBreakPreviewMagnification = IntegerHelper.getInt(data[10], data[11]);
+ normalMagnification = IntegerHelper.getInt(data[12], data[13]);
+ }
+
+ /**
+ * Constructs the dimensions from the raw data. Dummy overload for
+ * biff7 workbooks
+ *
+ * @param t the raw data
+ * @param dummy the overload
+ */
+ public Window2Record(Record t, Biff7 biff7)
+ {
+ super(t);
+ byte[] data = t.getData();
+
+ int options = IntegerHelper.getInt(data[0], data[1]);
+
+ selected = ((options & 0x200) != 0);
+ showGridLines = ((options & 0x02) != 0);
+ frozenPanes = ((options & 0x08) != 0);
+ displayZeroValues = ((options & 0x10) != 0);
+ frozenNotSplit = ((options & 0x100) != 0);
+ pageBreakPreviewMode = ((options & 0x800) != 0);
+ }
+
+ /**
+ * Accessor for the selected flag
+ *
+ * @return TRUE if this sheet is selected, FALSE otherwise
+ */
+ public boolean isSelected()
+ {
+ return selected;
+ }
+
+ /**
+ * Accessor for the show grid lines flag
+ *
+ * @return TRUE to show grid lines, FALSE otherwise
+ */
+ public boolean getShowGridLines()
+ {
+ return showGridLines;
+ }
+
+ /**
+ * Accessor for the zero values flag
+ *
+ * @return TRUE if this sheet displays zero values, FALSE otherwise
+ */
+ public boolean getDisplayZeroValues()
+ {
+ return displayZeroValues;
+ }
+
+ /**
+ * Accessor for the frozen panes flag
+ *
+ * @return TRUE if this contains frozen panes, FALSE otherwise
+ */
+ public boolean getFrozen()
+ {
+ return frozenPanes;
+ }
+
+ /**
+ * Accessor for the frozen not split flag
+ *
+ * @return TRUE if this contains frozen, FALSE otherwise
+ */
+ public boolean getFrozenNotSplit()
+ {
+ return frozenNotSplit;
+ }
+
+ /**
+ * Accessor for the page break preview mode
+ *
+ * @return TRUE if this sheet is in page break preview, FALSE otherwise
+ */
+ public boolean isPageBreakPreview()
+ {
+ return pageBreakPreviewMode;
+ }
+
+ /**
+ * Accessor for the page break preview magnification
+ *
+ * @return the cached paged break preview magnfication factor in percent
+ */
+ public int getPageBreakPreviewMagnificaiton()
+ {
+ return pageBreakPreviewMagnification;
+ }
+
+ /**
+ * Accessor for the normal view magnification
+ *
+ * @return the cached normal view magnfication factor in percent
+ */
+ public int getNormalMagnificaiton()
+ {
+ return normalMagnification;
+ }
+
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/read/biff/WorkbookParser.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/read/biff/WorkbookParser.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/read/biff/WorkbookParser.java 17 Aug 2012 14:50:57 -0000 1.1
@@ -0,0 +1,1235 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.read.biff;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.Cell;
+import jxl.Range;
+import jxl.Sheet;
+import jxl.Workbook;
+import jxl.WorkbookSettings;
+import jxl.biff.BuiltInName;
+import jxl.biff.CellReferenceHelper;
+import jxl.biff.EmptyCell;
+import jxl.biff.FontRecord;
+import jxl.biff.Fonts;
+import jxl.biff.FormatRecord;
+import jxl.biff.FormattingRecords;
+import jxl.biff.NumFormatRecordsException;
+import jxl.biff.PaletteRecord;
+import jxl.biff.RangeImpl;
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.XFRecord;
+import jxl.biff.drawing.DrawingGroup;
+import jxl.biff.drawing.MsoDrawingGroupRecord;
+import jxl.biff.drawing.Origin;
+import jxl.biff.formula.ExternalSheet;
+
+/**
+ * Parses the biff file passed in, and builds up an internal representation of
+ * the spreadsheet
+ */
+public class WorkbookParser extends Workbook
+ implements ExternalSheet, WorkbookMethods
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(WorkbookParser.class);
+
+ /**
+ * The excel file
+ */
+ private File excelFile;
+ /**
+ * The number of open bofs
+ */
+ private int bofs;
+ /**
+ * Indicates whether or not the dates are based around the 1904 date system
+ */
+ private boolean nineteenFour;
+ /**
+ * The shared string table
+ */
+ private SSTRecord sharedStrings;
+ /**
+ * The names of all the worksheets
+ */
+ private ArrayList boundsheets;
+ /**
+ * The xf records
+ */
+ private FormattingRecords formattingRecords;
+ /**
+ * The fonts used by this workbook
+ */
+ private Fonts fonts;
+
+ /**
+ * The sheets contained in this workbook
+ */
+ private ArrayList sheets;
+
+ /**
+ * The last sheet accessed
+ */
+ private SheetImpl lastSheet;
+
+ /**
+ * The index of the last sheet retrieved
+ */
+ private int lastSheetIndex;
+
+ /**
+ * The named records found in this workbook
+ */
+ private HashMap namedRecords;
+
+ /**
+ * The list of named records
+ */
+ private ArrayList nameTable;
+
+ /**
+ * The list of add in functions
+ */
+ private ArrayList addInFunctions;
+
+ /**
+ * The external sheet record. Used by formulas, and names
+ */
+ private ExternalSheetRecord externSheet;
+
+ /**
+ * The list of supporting workbooks - used by formulas
+ */
+ private ArrayList supbooks;
+
+ /**
+ * The bof record for this workbook
+ */
+ private BOFRecord workbookBof;
+
+ /**
+ * The Mso Drawing Group record for this workbook
+ */
+ private MsoDrawingGroupRecord msoDrawingGroup;
+
+ /**
+ * The property set record associated with this workbook
+ */
+ private ButtonPropertySetRecord buttonPropertySet;
+
+ /**
+ * Workbook protected flag
+ */
+ private boolean wbProtected;
+
+ /**
+ * Contains macros flag
+ */
+ private boolean containsMacros;
+
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings settings;
+
+ /**
+ * The drawings contained in this workbook
+ */
+ private DrawingGroup drawingGroup;
+
+ /**
+ * The country record (containing the language and regional settings)
+ * for this workbook
+ */
+ private CountryRecord countryRecord;
+
+ /**
+ * Constructs this object from the raw excel data
+ *
+ * @param f the excel 97 biff file
+ * @param s the workbook settings
+ */
+ public WorkbookParser(File f, WorkbookSettings s)
+ {
+ super();
+ excelFile = f;
+ boundsheets = new ArrayList(10);
+ fonts = new Fonts();
+ formattingRecords = new FormattingRecords(fonts);
+ sheets = new ArrayList(10);
+ supbooks = new ArrayList(10);
+ namedRecords = new HashMap();
+ lastSheetIndex = -1;
+ wbProtected = false;
+ containsMacros = false;
+ settings = s;
+ }
+
+ /**
+ * Gets the sheets within this workbook.
+ * NOTE: Use of this method for
+ * very large worksheets can cause performance and out of memory problems.
+ * Use the alternative method getSheet() to retrieve each sheet individually
+ *
+ * @return an array of the individual sheets
+ */
+ public Sheet[] getSheets()
+ {
+ Sheet[] sheetArray = new Sheet[getNumberOfSheets()];
+ return (Sheet[]) sheets.toArray(sheetArray);
+ }
+
+ /**
+ * Interface method from WorkbookMethods - gets the specified
+ * sheet within this workbook
+ *
+ * @param index the zero based index of the required sheet
+ * @return The sheet specified by the index
+ */
+ public Sheet getReadSheet(int index)
+ {
+ return getSheet(index);
+ }
+
+ /**
+ * Gets the specified sheet within this workbook
+ *
+ * @param index the zero based index of the required sheet
+ * @return The sheet specified by the index
+ */
+ public Sheet getSheet(int index)
+ {
+ // First see if the last sheet index is the same as this sheet index.
+ // If so, then the same sheet is being re-requested, so simply
+ // return it instead of rereading it
+ if ((lastSheet != null) && lastSheetIndex == index)
+ {
+ return lastSheet;
+ }
+
+ // Flush out all of the cached data in the last sheet
+ if (lastSheet != null)
+ {
+ lastSheet.clear();
+
+ if (!settings.getGCDisabled())
+ {
+ System.gc();
+ }
+ }
+
+ lastSheet = (SheetImpl) sheets.get(index);
+ lastSheetIndex = index;
+ lastSheet.readSheet();
+
+ return lastSheet;
+ }
+
+ /**
+ * Gets the sheet with the specified name from within this workbook
+ *
+ * @param name the sheet name
+ * @return The sheet with the specified name, or null if it is not found
+ */
+ public Sheet getSheet(String name)
+ {
+ // Iterate through the boundsheet records
+ int pos = 0;
+ boolean found = false;
+ Iterator i = boundsheets.iterator();
+ BoundsheetRecord br = null;
+
+ while (i.hasNext() && !found)
+ {
+ br = (BoundsheetRecord) i.next();
+
+ if (br.getName().equals(name))
+ {
+ found = true;
+ }
+ else
+ {
+ pos++;
+ }
+ }
+
+ return found ? getSheet(pos) : null;
+ }
+
+ /**
+ * Gets the sheet names
+ *
+ * @return an array of strings containing the sheet names
+ */
+ public String[] getSheetNames()
+ {
+ String[] names = new String[boundsheets.size()];
+
+ BoundsheetRecord br = null;
+ for (int i = 0; i < names.length; i++)
+ {
+ br = (BoundsheetRecord) boundsheets.get(i);
+ names[i] = br.getName();
+ }
+
+ return names;
+ }
+
+
+ /**
+ * Package protected function which gets the real internal sheet index
+ * based upon the external sheet reference. This is used for extern sheet
+ * references which are specified in formulas
+ *
+ * @param index the external sheet reference
+ * @return the actual sheet index
+ */
+ public int getExternalSheetIndex(int index)
+ {
+ // For biff7, the whole external reference thing works differently
+ // Hopefully for our purposes sheet references will all be local
+ if (workbookBof.isBiff7())
+ {
+ return index;
+ }
+
+ Assert.verify(externSheet != null);
+
+ int firstTab = externSheet.getFirstTabIndex(index);
+
+ return firstTab;
+ }
+
+ /**
+ * Package protected function which gets the real internal sheet index
+ * based upon the external sheet reference. This is used for extern sheet
+ * references which are specified in formulas
+ *
+ * @param index the external sheet reference
+ * @return the actual sheet index
+ */
+ public int getLastExternalSheetIndex(int index)
+ {
+ // For biff7, the whole external reference thing works differently
+ // Hopefully for our purposes sheet references will all be local
+ if (workbookBof.isBiff7())
+ {
+ return index;
+ }
+
+ Assert.verify(externSheet != null);
+
+ int lastTab = externSheet.getLastTabIndex(index);
+
+ return lastTab;
+ }
+
+ /**
+ * Gets the name of the external sheet specified by the index
+ *
+ * @param index the external sheet index
+ * @return the name of the external sheet
+ */
+ public String getExternalSheetName(int index)
+ {
+ // For biff7, the whole external reference thing works differently
+ // Hopefully for our purposes sheet references will all be local
+ if (workbookBof.isBiff7())
+ {
+ BoundsheetRecord br = (BoundsheetRecord) boundsheets.get(index);
+
+ return br.getName();
+ }
+
+ int supbookIndex = externSheet.getSupbookIndex(index);
+ SupbookRecord sr = (SupbookRecord) supbooks.get(supbookIndex);
+
+ int firstTab = externSheet.getFirstTabIndex(index);
+ int lastTab = externSheet.getLastTabIndex(index);
+ String firstTabName = "";
+ String lastTabName = "";
+
+ if (sr.getType() == SupbookRecord.INTERNAL)
+ {
+ // It's an internal reference - get the name from the boundsheets list
+ if (firstTab == 65535)
+ {
+ firstTabName = "#REF";
+ }
+ else
+ {
+ BoundsheetRecord br = (BoundsheetRecord) boundsheets.get(firstTab);
+ firstTabName = br.getName();
+ }
+
+ if (lastTab==65535)
+ {
+ lastTabName = "#REF";
+ }
+ else
+ {
+ BoundsheetRecord br = (BoundsheetRecord) boundsheets.get(lastTab);
+ lastTabName = br.getName();
+ }
+
+ String sheetName = (firstTab == lastTab) ? firstTabName :
+ firstTabName + ':' + lastTabName;
+
+ // if the sheet name contains apostrophes then escape them
+ sheetName = sheetName.indexOf('\'') == -1 ? sheetName :
+ StringHelper.replace(sheetName, "\'", "\'\'");
+
+
+ // if the sheet name contains spaces, then enclose in quotes
+ return sheetName.indexOf(' ') == -1 ? sheetName :
+ '\'' + sheetName + '\'';
+ }
+ else if (sr.getType() == SupbookRecord.EXTERNAL)
+ {
+ // External reference - get the sheet name from the supbook record
+ StringBuffer sb = new StringBuffer();
+ java.io.File fl = new java.io.File(sr.getFileName());
+ sb.append("'");
+ sb.append(fl.getAbsolutePath());
+ sb.append("[");
+ sb.append(fl.getName());
+ sb.append("]");
+ sb.append((firstTab == 65535) ? "#REF" : sr.getSheetName(firstTab));
+ if (lastTab != firstTab)
+ {
+ sb.append(sr.getSheetName(lastTab));
+ }
+ sb.append("'");
+ return sb.toString();
+ }
+
+ // An unknown supbook - return unkown
+ return "[UNKNOWN]";
+ }
+
+ /**
+ * Gets the name of the external sheet specified by the index
+ *
+ * @param index the external sheet index
+ * @return the name of the external sheet
+ */
+ public String getLastExternalSheetName(int index)
+ {
+ // For biff7, the whole external reference thing works differently
+ // Hopefully for our purposes sheet references will all be local
+ if (workbookBof.isBiff7())
+ {
+ BoundsheetRecord br = (BoundsheetRecord) boundsheets.get(index);
+
+ return br.getName();
+ }
+
+ int supbookIndex = externSheet.getSupbookIndex(index);
+ SupbookRecord sr = (SupbookRecord) supbooks.get(supbookIndex);
+
+ int lastTab = externSheet.getLastTabIndex(index);
+
+ if (sr.getType() == SupbookRecord.INTERNAL)
+ {
+ // It's an internal reference - get the name from the boundsheets list
+ if (lastTab == 65535)
+ {
+ return "#REF";
+ }
+ else
+ {
+ BoundsheetRecord br = (BoundsheetRecord) boundsheets.get(lastTab);
+ return br.getName();
+ }
+ }
+ else if (sr.getType() == SupbookRecord.EXTERNAL)
+ {
+ // External reference - get the sheet name from the supbook record
+ StringBuffer sb = new StringBuffer();
+ java.io.File fl = new java.io.File(sr.getFileName());
+ sb.append("'");
+ sb.append(fl.getAbsolutePath());
+ sb.append("[");
+ sb.append(fl.getName());
+ sb.append("]");
+ sb.append((lastTab == 65535) ? "#REF" : sr.getSheetName(lastTab));
+ sb.append("'");
+ return sb.toString();
+ }
+
+ // An unknown supbook - return unkown
+ return "[UNKNOWN]";
+ }
+
+ /**
+ * Returns the number of sheets in this workbook
+ *
+ * @return the number of sheets in this workbook
+ */
+ public int getNumberOfSheets()
+ {
+ return sheets.size();
+ }
+
+ /**
+ * Closes this workbook, and frees makes any memory allocated available
+ * for garbage collection
+ */
+ public void close()
+ {
+ if (lastSheet != null)
+ {
+ lastSheet.clear();
+ }
+ excelFile.clear();
+
+ if (!settings.getGCDisabled())
+ {
+ System.gc();
+ }
+ }
+
+ /**
+ * Adds the sheet to the end of the array
+ *
+ * @param s the sheet to add
+ */
+ final void addSheet(Sheet s)
+ {
+ sheets.add(s);
+ }
+
+ /**
+ * Does the hard work of building up the object graph from the excel bytes
+ *
+ * @exception BiffException
+ * @exception PasswordException if the workbook is password protected
+ */
+ protected void parse() throws BiffException, PasswordException
+ {
+ Record r = null;
+
+ BOFRecord bof = new BOFRecord(excelFile.next());
+ workbookBof = bof;
+ bofs++;
+
+ if (!bof.isBiff8() && !bof.isBiff7())
+ {
+ throw new BiffException(BiffException.unrecognizedBiffVersion);
+ }
+
+ if (!bof.isWorkbookGlobals())
+ {
+ throw new BiffException(BiffException.expectedGlobals);
+ }
+ ArrayList continueRecords = new ArrayList();
+ ArrayList localNames = new ArrayList();
+ nameTable = new ArrayList();
+ addInFunctions = new ArrayList();
+
+ // Skip to the firs worksheet
+ while (bofs == 1)
+ {
+ r = excelFile.next();
+
+ if (r.getType() == Type.SST)
+ {
+ continueRecords.clear();
+ Record nextrec = excelFile.peek();
+ while (nextrec.getType() == Type.CONTINUE)
+ {
+ continueRecords.add(excelFile.next());
+ nextrec = excelFile.peek();
+ }
+
+ // cast the array
+ Record[] records = new Record[continueRecords.size()];
+ records = (Record[]) continueRecords.toArray(records);
+
+ sharedStrings = new SSTRecord(r, records, settings);
+ }
+ else if (r.getType() == Type.FILEPASS)
+ {
+ throw new PasswordException();
+ }
+ else if (r.getType() == Type.NAME)
+ {
+ NameRecord nr = null;
+
+ if (bof.isBiff8())
+ {
+ nr = new NameRecord(r, settings, namedRecords.size());
+
+ }
+ else
+ {
+ nr = new NameRecord(r, settings, namedRecords.size(),
+ NameRecord.biff7);
+ }
+
+ if (nr.isGlobal())
+ {
+ namedRecords.put(nr.getName(), nr);
+ nameTable.add(nr);
+ }
+ else
+ {
+ localNames.add(nr);
+ }
+ }
+ else if (r.getType() == Type.FONT)
+ {
+ FontRecord fr = null;
+
+ if (bof.isBiff8())
+ {
+ fr = new FontRecord(r, settings);
+ }
+ else
+ {
+ fr = new FontRecord(r, settings, FontRecord.biff7);
+ }
+ fonts.addFont(fr);
+ }
+ else if (r.getType() == Type.PALETTE)
+ {
+ PaletteRecord palette = new PaletteRecord(r);
+ formattingRecords.setPalette(palette);
+ }
+ else if (r.getType() == Type.NINETEENFOUR)
+ {
+ NineteenFourRecord nr = new NineteenFourRecord(r);
+ nineteenFour = nr.is1904();
+ }
+ else if (r.getType() == Type.FORMAT)
+ {
+ FormatRecord fr = null;
+ if (bof.isBiff8())
+ {
+ fr = new FormatRecord(r, settings, FormatRecord.biff8);
+ }
+ else
+ {
+ fr = new FormatRecord(r, settings, FormatRecord.biff7);
+ }
+ try
+ {
+ formattingRecords.addFormat(fr);
+ }
+ catch (NumFormatRecordsException e)
+ {
+ e.printStackTrace();
+ // This should not happen. Bomb out
+ Assert.verify(false, e.getMessage());
+ }
+ }
+ else if (r.getType() == Type.XF)
+ {
+ XFRecord xfr = null;
+ if (bof.isBiff8())
+ {
+ xfr = new XFRecord(r, settings, XFRecord.biff8);
+ }
+ else
+ {
+ xfr = new XFRecord(r, settings, XFRecord.biff7);
+ }
+
+ try
+ {
+ formattingRecords.addStyle(xfr);
+ }
+ catch (NumFormatRecordsException e)
+ {
+ // This should not happen. Bomb out
+ Assert.verify(false, e.getMessage());
+ }
+ }
+ else if (r.getType() == Type.BOUNDSHEET)
+ {
+ BoundsheetRecord br = null;
+
+ if (bof.isBiff8())
+ {
+ br = new BoundsheetRecord(r, settings);
+ }
+ else
+ {
+ br = new BoundsheetRecord(r, BoundsheetRecord.biff7);
+ }
+
+ if (br.isSheet())
+ {
+ boundsheets.add(br);
+ }
+ else if (br.isChart() && !settings.getDrawingsDisabled())
+ {
+ boundsheets.add(br);
+ }
+ }
+ else if (r.getType() == Type.EXTERNSHEET)
+ {
+ if (bof.isBiff8())
+ {
+ externSheet = new ExternalSheetRecord(r, settings);
+ }
+ else
+ {
+ externSheet = new ExternalSheetRecord(r, settings,
+ ExternalSheetRecord.biff7);
+ }
+ }
+ else if (r.getType() == Type.CODEPAGE)
+ {
+ CodepageRecord cr = new CodepageRecord(r);
+ settings.setCharacterSet(cr.getCharacterSet());
+ }
+ else if (r.getType() == Type.SUPBOOK)
+ {
+ Record nextrec = excelFile.peek();
+ while (nextrec.getType() == Type.CONTINUE)
+ {
+ r.addContinueRecord(excelFile.next());
+ nextrec = excelFile.peek();
+ }
+
+ SupbookRecord sr = new SupbookRecord(r, settings);
+ supbooks.add(sr);
+ }
+ else if (r.getType() == Type.EXTERNNAME)
+ {
+ ExternalNameRecord enr = new ExternalNameRecord(r, settings);
+
+ if (enr.isAddInFunction())
+ {
+ addInFunctions.add(enr.getName());
+ }
+ }
+ else if (r.getType() == Type.PROTECT)
+ {
+ ProtectRecord pr = new ProtectRecord(r);
+ wbProtected = pr.isProtected();
+ }
+ else if (r.getType() == Type.OBJPROJ)
+ {
+ containsMacros = true;
+ }
+ else if (r.getType() == Type.COUNTRY)
+ {
+ countryRecord = new CountryRecord(r);
+ }
+ else if (r.getType() == Type.MSODRAWINGGROUP)
+ {
+ if (!settings.getDrawingsDisabled())
+ {
+ msoDrawingGroup = new MsoDrawingGroupRecord(r);
+
+ if (drawingGroup == null)
+ {
+ drawingGroup = new DrawingGroup(Origin.READ);
+ }
+
+ drawingGroup.add(msoDrawingGroup);
+
+ Record nextrec = excelFile.peek();
+ while (nextrec.getType() == Type.CONTINUE)
+ {
+ drawingGroup.add(excelFile.next());
+ nextrec = excelFile.peek();
+ }
+ }
+ }
+ else if (r.getType() == Type.BUTTONPROPERTYSET)
+ {
+ buttonPropertySet = new ButtonPropertySetRecord(r);
+ }
+ else if (r.getType() == Type.EOF)
+ {
+ bofs--;
+ }
+ }
+
+ bof = null;
+ if (excelFile.hasNext())
+ {
+ r = excelFile.next();
+
+ if (r.getType() == Type.BOF)
+ {
+ bof = new BOFRecord(r);
+ }
+ }
+
+ // Only get sheets for which there is a corresponding Boundsheet record
+ while (bof != null && getNumberOfSheets() < boundsheets.size())
+ {
+ if (!bof.isBiff8() && !bof.isBiff7())
+ {
+ throw new BiffException(BiffException.unrecognizedBiffVersion);
+ }
+
+ if (bof.isWorksheet())
+ {
+ // Read the sheet in
+ SheetImpl s = new SheetImpl(excelFile,
+ sharedStrings,
+ formattingRecords,
+ bof,
+ workbookBof,
+ nineteenFour,
+ this);
+
+ BoundsheetRecord br = (BoundsheetRecord) boundsheets.get
+ (getNumberOfSheets());
+ s.setName(br.getName());
+ s.setHidden(br.isHidden());
+ addSheet(s);
+ }
+ else if (bof.isChart())
+ {
+ // Read the sheet in
+ SheetImpl s = new SheetImpl(excelFile,
+ sharedStrings,
+ formattingRecords,
+ bof,
+ workbookBof,
+ nineteenFour,
+ this);
+
+ BoundsheetRecord br = (BoundsheetRecord) boundsheets.get
+ (getNumberOfSheets());
+ s.setName(br.getName());
+ s.setHidden(br.isHidden());
+ addSheet(s);
+ }
+ else
+ {
+ logger.warn("BOF is unrecognized");
+
+
+ while (excelFile.hasNext() && r.getType() != Type.EOF)
+ {
+ r = excelFile.next();
+ }
+ }
+
+ // The next record will normally be a BOF or empty padding until
+ // the end of the block is reached. In exceptionally unlucky cases,
+ // the last EOF will coincide with a block division, so we have to
+ // check there is more data to retrieve.
+ // Thanks to liamg for spotting this
+ bof = null;
+ if (excelFile.hasNext())
+ {
+ r = excelFile.next();
+
+ if (r.getType() == Type.BOF)
+ {
+ bof = new BOFRecord(r);
+ }
+ }
+ }
+
+ // Add all the local names to the specific sheets
+ for (Iterator it = localNames.iterator() ; it.hasNext() ;)
+ {
+ NameRecord nr = (NameRecord) it.next();
+
+ if (nr.getBuiltInName() == null)
+ {
+ logger.warn("Usage of a local non-builtin name");
+ }
+ else if (nr.getBuiltInName() == BuiltInName.PRINT_AREA ||
+ nr.getBuiltInName() == BuiltInName.PRINT_TITLES)
+ {
+ // appears to use the internal tab number rather than the
+ // external sheet index
+ SheetImpl s = (SheetImpl) sheets.get(nr.getSheetRef() - 1);
+ s.addLocalName(nr);
+ }
+ }
+ }
+
+ /**
+ * Accessor for the formattingRecords, used by the WritableWorkbook
+ * when creating a copy of this
+ *
+ * @return the formatting records
+ */
+ public FormattingRecords getFormattingRecords()
+ {
+ return formattingRecords;
+ }
+
+ /**
+ * Accessor for the externSheet, used by the WritableWorkbook
+ * when creating a copy of this
+ *
+ * @return the external sheet record
+ */
+ public ExternalSheetRecord getExternalSheetRecord()
+ {
+ return externSheet;
+ }
+
+ /**
+ * Accessor for the MsoDrawingGroup, used by the WritableWorkbook
+ * when creating a copy of this
+ *
+ * @return the Mso Drawing Group record
+ */
+ public MsoDrawingGroupRecord getMsoDrawingGroupRecord()
+ {
+ return msoDrawingGroup;
+ }
+
+ /**
+ * Accessor for the supbook records, used by the WritableWorkbook
+ * when creating a copy of this
+ *
+ * @return the supbook records
+ */
+ public SupbookRecord[] getSupbookRecords()
+ {
+ SupbookRecord[] sr = new SupbookRecord[supbooks.size()];
+ return (SupbookRecord[]) supbooks.toArray(sr);
+ }
+
+ /**
+ * Accessor for the name records. Used by the WritableWorkbook when
+ * creating a copy of this
+ *
+ * @return the array of names
+ */
+ public NameRecord[] getNameRecords()
+ {
+ NameRecord[] na = new NameRecord[nameTable.size()];
+ return (NameRecord[]) nameTable.toArray(na);
+ }
+
+ /**
+ * Accessor for the fonts, used by the WritableWorkbook
+ * when creating a copy of this
+ * @return the fonts used in this workbook
+ */
+ public Fonts getFonts()
+ {
+ return fonts;
+ }
+
+ /**
+ * Returns the cell for the specified location eg. "Sheet1!A4".
+ * This is identical to using the CellReferenceHelper with its
+ * associated performance overheads, consequently it should
+ * be use sparingly
+ *
+ * @param loc the cell to retrieve
+ * @return the cell at the specified location
+ */
+ public Cell getCell(String loc)
+ {
+ Sheet s = getSheet(CellReferenceHelper.getSheet(loc));
+ return s.getCell(loc);
+ }
+
+ /**
+ * Gets the named cell from this workbook. If the name refers to a
+ * range of cells, then the cell on the top left is returned. If
+ * the name cannot be found, null is returned
+ *
+ * @param name the name of the cell/range to search for
+ * @return the cell in the top left of the range if found, NULL
+ * otherwise
+ */
+ public Cell findCellByName(String name)
+ {
+ NameRecord nr = (NameRecord) namedRecords.get(name);
+
+ if (nr == null)
+ {
+ return null;
+ }
+
+ NameRecord.NameRange[] ranges = nr.getRanges();
+
+ // Go and retrieve the first cell in the first range
+ Sheet s = getSheet(getExternalSheetIndex(ranges[0].getExternalSheet()));
+ int col = ranges[0].getFirstColumn();
+ int row = ranges[0].getFirstRow();
+
+ // If the sheet boundaries fall short of the named cell, then return
+ // an empty cell to stop an exception being thrown
+ if (col > s.getColumns() || row > s.getRows())
+ {
+ return new EmptyCell(col, row);
+ }
+
+ Cell cell = s.getCell(col, row);
+
+ return cell;
+ }
+
+ /**
+ * Gets the named range from this workbook. The Range object returns
+ * contains all the cells from the top left to the bottom right
+ * of the range.
+ * If the named range comprises an adjacent range,
+ * the Range[] will contain one object; for non-adjacent
+ * ranges, it is necessary to return an array of length greater than
+ * one.
+ * If the named range contains a single cell, the top left and
+ * bottom right cell will be the same cell
+ *
+ * @param name the name to find
+ * @return the range of cells
+ */
+ public Range[] findByName(String name)
+ {
+ NameRecord nr = (NameRecord) namedRecords.get(name);
+
+ if (nr == null)
+ {
+ return null;
+ }
+
+ NameRecord.NameRange[] ranges = nr.getRanges();
+
+ Range[] cellRanges = new Range[ranges.length];
+
+ for (int i = 0; i < ranges.length; i++)
+ {
+ cellRanges[i] = new RangeImpl
+ (this,
+ getExternalSheetIndex(ranges[i].getExternalSheet()),
+ ranges[i].getFirstColumn(),
+ ranges[i].getFirstRow(),
+ getLastExternalSheetIndex(ranges[i].getExternalSheet()),
+ ranges[i].getLastColumn(),
+ ranges[i].getLastRow());
+ }
+
+ return cellRanges;
+ }
+
+ /**
+ * Gets the named ranges
+ *
+ * @return the list of named cells within the workbook
+ */
+ public String[] getRangeNames()
+ {
+ Object[] keys = namedRecords.keySet().toArray();
+ String[] names = new String[keys.length];
+ System.arraycopy(keys, 0, names, 0, keys.length);
+
+ return names;
+ }
+
+ /**
+ * Method used when parsing formulas to make sure we are trying
+ * to parse a supported biff version
+ *
+ * @return the BOF record
+ */
+ public BOFRecord getWorkbookBof()
+ {
+ return workbookBof;
+ }
+
+ /**
+ * Determines whether the sheet is protected
+ *
+ * @return whether or not the sheet is protected
+ */
+ public boolean isProtected()
+ {
+ return wbProtected;
+ }
+
+ /**
+ * Accessor for the settings
+ *
+ * @return the workbook settings
+ */
+ public WorkbookSettings getSettings()
+ {
+ return settings;
+ }
+
+ /**
+ * Accessor/implementation method for the external sheet reference
+ *
+ * @param sheetName the sheet name to look for
+ * @return the external sheet index
+ */
+ public int getExternalSheetIndex(String sheetName)
+ {
+ return 0;
+ }
+
+ /**
+ * Accessor/implementation method for the external sheet reference
+ *
+ * @param sheetName the sheet name to look for
+ * @return the external sheet index
+ */
+ public int getLastExternalSheetIndex(String sheetName)
+ {
+ return 0;
+ }
+
+ /**
+ * Gets the name at the specified index
+ *
+ * @param index the index into the name table
+ * @return the name of the cell
+ */
+ public String getName(int index)
+ {
+ Assert.verify(index >= 0 && index < nameTable.size());
+ return ((NameRecord) nameTable.get(index)).getName();
+ }
+
+ /**
+ * Gets the index of the name record for the name
+ *
+ * @param name the name to search for
+ * @return the index in the name table
+ */
+ public int getNameIndex(String name)
+ {
+ NameRecord nr = (NameRecord) namedRecords.get(name);
+
+ return nr != null ? nr.getIndex() : 0;
+ }
+
+ /**
+ * Accessor for the drawing group
+ *
+ * @return the drawing group
+ */
+ public DrawingGroup getDrawingGroup()
+ {
+ return drawingGroup;
+ }
+
+ /**
+ * Accessor for the CompoundFile. For this feature to return non-null
+ * value, the propertySets feature in WorkbookSettings must be enabled
+ * and the workbook must contain additional property sets. This
+ * method is used during the workbook copy
+ *
+ * @return the base compound file if it contains additional data items
+ * and property sets are enabled
+ */
+ public CompoundFile getCompoundFile()
+ {
+ return excelFile.getCompoundFile();
+ }
+
+ /**
+ * Accessor for the containsMacros
+ *
+ * @return TRUE if this workbook contains macros, FALSE otherwise
+ */
+ public boolean containsMacros()
+ {
+ return containsMacros;
+ }
+
+ /**
+ * Accessor for the button property set, used during copying
+ *
+ * @return the button property set
+ */
+ public ButtonPropertySetRecord getButtonPropertySet()
+ {
+ return buttonPropertySet;
+ }
+
+ /**
+ * Accessor for the country record, using during copying
+ *
+ * @return the country record read in
+ */
+ public CountryRecord getCountryRecord()
+ {
+ return countryRecord;
+ }
+
+ /**
+ * Accessor for addin function names
+ *
+ * @return list of add in function names
+ */
+ public String[] getAddInFunctionNames()
+ {
+ String[] addins = new String[0];
+ return (String[]) addInFunctions.toArray(addins);
+ }
+
+ /**
+ * Gets the sheet index in this workbook. Used when importing a sheet
+ *
+ * @param sheet the sheet
+ * @return the 0-based sheet index, or -1 if it is not found
+ */
+ public int getIndex(Sheet sheet)
+ {
+ String name = sheet.getName();
+ int index = -1;
+ int pos = 0;
+
+ for (Iterator i = boundsheets.iterator() ; i.hasNext() && index == -1 ;)
+ {
+ BoundsheetRecord br = (BoundsheetRecord) i.next();
+
+ if (br.getName().equals(name))
+ {
+ index = pos;
+ }
+ else
+ {
+ pos++;
+ }
+ }
+
+ return index;
+ }
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/Alignment.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/Alignment.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/Alignment.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,39 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+/**
+ * Enumeration class which contains the various alignments for data within a
+ * cell
+ *
+ * @deprecated Repackaged as jxl.Alignment. This version is retained
+ * for backwards compatibility
+ */
+public final class Alignment extends jxl.format.Alignment
+{
+ /**
+ * Private constructor
+ */
+ private Alignment()
+ {
+ super(0, null);
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/write/Blank.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/Blank.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/Blank.java 17 Aug 2012 14:51:21 -0000 1.1
@@ -0,0 +1,95 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import jxl.Cell;
+import jxl.format.CellFormat;
+import jxl.write.biff.BlankRecord;
+
+/**
+ * A blank cell. Despite not having any contents, it may contain
+ * formatting information. Such cells are typically used when creating
+ * templates
+ */
+public class Blank extends BlankRecord implements WritableCell
+{
+ /**
+ * Creates a cell which, when added to the sheet, will be presented at the
+ * specified column and row co-ordinates
+ *
+ * @param c the column
+ * @param r the row
+ */
+ public Blank(int c, int r)
+ {
+ super(c, r);
+ }
+
+ /**
+ * Creates a cell which, when added to the sheet, will be presented at the
+ * specified column and row co-ordinates
+ * in the manner specified by the CellFormat parameter
+ *
+ * @param c the column
+ * @param r the row
+ * @param st the cell format
+ */
+ public Blank(int c, int r, CellFormat st)
+ {
+ super(c, r, st);
+ }
+
+ /**
+ * Constructor used internally by the application when making a writable
+ * copy of a spreadsheet being read in
+ *
+ * @param lc the cell to copy
+ */
+ public Blank(Cell lc)
+ {
+ super(lc);
+ }
+
+
+ /**
+ * Copy constructor used for deep copying
+ *
+ * @param col the column
+ * @param row the row
+ * @param b the balnk cell to copy
+ */
+ protected Blank(int col, int row, Blank b)
+ {
+ super(col, row, b);
+ }
+
+ /**
+ * Implementation of the deep copy function
+ *
+ * @param col the column which the new cell will occupy
+ * @param row the row which the new cell will occupy
+ * @return a copy of this cell, which can then be added to the sheet
+ */
+ public WritableCell copyTo(int col, int row)
+ {
+ return new Blank(col, row, this);
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/write/BoldStyle.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/BoldStyle.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/BoldStyle.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,37 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+/**
+ * Enumeration class containing the various bold styles for data
+ */
+public final class BoldStyle extends jxl.format.BoldStyle
+{
+ /**
+ * Constructor
+ *
+ * @param val a dummy value
+ */
+ private BoldStyle(int val)
+ {
+ super(0, "");
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/write/Boolean.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/Boolean.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/Boolean.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,103 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import jxl.BooleanCell;
+import jxl.format.CellFormat;
+import jxl.write.biff.BooleanRecord;
+
+/**
+ * A cell, created by user applications, which contains a boolean (or
+ * in some cases an error) value
+ */
+public class Boolean extends BooleanRecord implements WritableCell, BooleanCell
+{
+ /**
+ * Constructs a boolean value, which, when added to a spreadsheet, will
+ * display the specified value at the column/row position indicated.
+ *
+ * @param c the column
+ * @param r the row
+ * @param val the value
+ */
+ public Boolean(int c, int r, boolean val)
+ {
+ super(c, r, val);
+ }
+
+ /**
+ * Constructs a boolean, which, when added to a spreadsheet, will display the
+ * specified value at the column/row position with the specified CellFormat.
+ * The CellFormat may specify font information
+ *
+ * @param c the column
+ * @param r the row
+ * @param val the value
+ * @param st the cell format
+ */
+ public Boolean(int c, int r, boolean val, CellFormat st)
+ {
+ super(c, r, val, st);
+ }
+
+ /**
+ * Constructor used internally by the application when making a writable
+ * copy of a spreadsheet that has been read in
+ *
+ * @param nc the cell to copy
+ */
+ public Boolean(BooleanCell nc)
+ {
+ super(nc);
+ }
+
+ /**
+ * Copy constructor used for deep copying
+ *
+ * @param col the column
+ * @param row the row
+ * @param b the cell to copy
+ */
+ protected Boolean(int col, int row, Boolean b)
+ {
+ super(col, row, b);
+ }
+ /**
+ * Sets the boolean value for this cell
+ *
+ * @param val the value
+ */
+ public void setValue(boolean val)
+ {
+ super.setValue(val);
+ }
+
+ /**
+ * Implementation of the deep copy function
+ *
+ * @param col the column which the new cell will occupy
+ * @param row the row which the new cell will occupy
+ * @return a copy of this cell, which can then be added to the sheet
+ */
+ public WritableCell copyTo(int col, int row)
+ {
+ return new Boolean(col, row, this);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/Border.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/Border.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/Border.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,35 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+/**
+ * @deprecated repackaged as jxl.format.Border
+ */
+public final class Border extends jxl.format.Border
+{
+ /**
+ * Constructor
+ */
+ private Border()
+ {
+ super(null);
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/write/BorderLineStyle.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/BorderLineStyle.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/BorderLineStyle.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,34 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+/**
+ * @deprecated Repackaged as jxl.format.BorderLineStyle
+ */
+public final class BorderLineStyle extends jxl.format.BorderLineStyle
+{
+ /**
+ * Constructor
+ */
+ private BorderLineStyle()
+ {
+ super(0, null);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/Colour.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/Colour.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/Colour.java 17 Aug 2012 14:51:21 -0000 1.1
@@ -0,0 +1,49 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+/**
+ * Enumeration class which contains the various colours available within
+ * the standard Excel colour palette
+ *
+ * @deprecated This has been repackaged as jxl.format.Colour
+ */
+public final class Colour extends jxl.format.Colour
+{
+ /**
+ * Constructor
+ * This is currently just a placeholder for backwards compatibility
+ */
+ private Colour()
+ {
+ super(0, null, 0, 0, 0);
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/DateFormat.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/DateFormat.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/DateFormat.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,52 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import java.text.SimpleDateFormat;
+
+import jxl.biff.DisplayFormat;
+import jxl.write.biff.DateFormatRecord;
+
+/**
+ * A custom user defined number format which may be instantiated within user
+ * applications in order to present date and time values in the appropriate
+ * format.
+ * The string format used to create a DateFormat adheres to the standard
+ * java specification, and JExcelApi makes the necessary modifications so
+ * that it is rendered as its nearest equivalent in Excel.
+ * Once created, this may be used within a CellFormat object, which in turn
+ * is a parameter passed to the constructor of the DateTime cell
+ */
+public class DateFormat extends DateFormatRecord implements DisplayFormat
+{
+ /**
+ * Constructor. The date format that is passed should comply to the standard
+ * Java date formatting conventions
+ *
+ * @param format the date format
+ */
+ public DateFormat(String format)
+ {
+ super(format);
+
+ // Verify that the format is valid
+ SimpleDateFormat df = new SimpleDateFormat(format);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/DateFormats.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/DateFormats.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/DateFormats.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,220 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import jxl.biff.DisplayFormat;
+
+/**
+ * Static class which contains Excels predefined Date formats
+ */
+public final class DateFormats
+{
+ /**
+ * Inner class which holds the format index
+ */
+ private static class BuiltInFormat implements DisplayFormat
+ {
+ /**
+ * The index of this date format
+ */
+ private int index;
+ /**
+ * The excel format
+ */
+ private String formatString;
+
+ /**
+ * Constructor
+ *
+ * @param i the index
+ * @param s the format string
+ */
+ public BuiltInFormat(int i, String s)
+ {
+ index = i;
+ formatString = s;
+ }
+
+ /**
+ * Gets the format index
+ *
+ * @return the format index
+ */
+ public int getFormatIndex()
+ {
+ return index;
+ }
+
+ /**
+ * Interface method which determines whether the index has been set. For
+ * built ins this is always true
+ *
+ * @return TRUE, since this is a built in format
+ */
+ public boolean isInitialized()
+ {
+ return true;
+ }
+ /**
+ * Initialize this format with the specified position. Since this is a
+ * built in format, this is always initialized, so this method body for
+ * this is empty
+ *
+ * @param pos the position in the array
+ */
+ public void initialize(int pos)
+ {
+ }
+ /**
+ * Determines whether this format is a built in format
+ *
+ * @return TRUE, since this is a built in format
+ */
+ public boolean isBuiltIn()
+ {
+ return true;
+ }
+ /**
+ * Accesses the excel format string which is applied to the cell
+ * Note that this is the string that excel uses, and not the java
+ * equivalent
+ *
+ * @return the cell format string
+ */
+ public String getFormatString()
+ {
+ return formatString;
+ }
+
+ /**
+ * Standard equals method
+ *
+ * @param o the object to compare
+ * @return TRUE if the two objects are equal, FALSE otherwise
+ */
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+
+ if (!(o instanceof BuiltInFormat))
+ {
+ return false;
+ }
+
+ BuiltInFormat bif = (BuiltInFormat) o;
+
+ return index == bif.index;
+ }
+
+ /**
+ * Hash code implementation
+ *
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ return index;
+ }
+ }
+
+ // The available built in date formats
+
+ /**
+ * The default format. This is equivalent to a date format of "M/d/yy"
+ */
+ public static final DisplayFormat FORMAT1 =
+ new BuiltInFormat(0x0e, "M/d/yy");
+ /**
+ * The default format. This is equivalent to a date format of "M/d/yy"
+ */
+ public static final DisplayFormat DEFAULT = FORMAT1;
+
+ /**
+ * Equivalent to a date format of "d-MMM-yy"
+ */
+ public static final DisplayFormat FORMAT2 =
+ new BuiltInFormat(0xf, "d-MMM-yy");
+
+ /**
+ * Equivalent to a date format of "d-MMM"
+ */
+ public static final DisplayFormat FORMAT3 =
+ new BuiltInFormat(0x10, "d-MMM");
+
+ /**
+ * Equivalent to a date format of "MMM-yy"
+ */
+ public static final DisplayFormat FORMAT4 =
+ new BuiltInFormat(0x11, "MMM-yy");
+
+ /**
+ * Equivalent to a date format of "h:mm a"
+ */
+ public static final DisplayFormat FORMAT5 =
+ new BuiltInFormat(0x12, "h:mm a");
+
+ /**
+ * Equivalent to a date format of "h:mm:ss a"
+ */
+ public static final DisplayFormat FORMAT6 =
+ new BuiltInFormat(0x13, "h:mm:ss a");
+
+ /**
+ * Equivalent to a date format of "H:mm"
+ */
+ public static final DisplayFormat FORMAT7 =
+ new BuiltInFormat(0x14, "H:mm");
+
+ /**
+ * Equivalent to a date format of "H:mm:ss"
+ */
+ public static final DisplayFormat FORMAT8 =
+ new BuiltInFormat(0x15, "H:mm:ss");
+
+ /**
+ * Equivalent to a date format of "M/d/yy H:mm"
+ */
+ public static final DisplayFormat FORMAT9 =
+ new BuiltInFormat(0x16, "M/d/yy H:mm");
+
+ /**
+ * Equivalent to a date format of "mm:ss"
+ */
+ public static final DisplayFormat FORMAT10 =
+ new BuiltInFormat(0x2d, "mm:ss");
+
+ /**
+ * Equivalent to a date format of "H:mm:ss"
+ */
+ public static final DisplayFormat FORMAT11 =
+ new BuiltInFormat(0x2e, "H:mm:ss");
+
+ /**
+ * Equivalent to a date format of "mm:ss.S"
+ */
+ public static final DisplayFormat FORMAT12 =
+ new BuiltInFormat(0x2f, "H:mm:ss");
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/DateTime.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/DateTime.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/DateTime.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,179 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import java.util.Date;
+
+import jxl.DateCell;
+import jxl.format.CellFormat;
+import jxl.write.biff.DateRecord;
+
+/**
+ * A Date which may be created on the fly by a user application and added to a
+ * spreadsheet
+ *
+ * NOTE: By default, all dates will have local timezone information added to
+ * their UTC value. If this is not desired (eg. if the date entered
+ * represents an interval eg. 9.83s for the 100m world record, then use
+ * the overloaded constructor which indicate that the date passed in was
+ * created under the GMT timezone. It is important that when the date
+ * was created, an instruction like
+ * Calendar.setTimeZone(TimeZone.getTimeZone("GMT"))
+ * was made prior to that
+ */
+public class DateTime extends DateRecord implements WritableCell, DateCell
+{
+ /**
+ * Instance variable for dummy variable overload
+ */
+ public static final GMTDate GMT = new GMTDate();
+
+ /**
+ * Constructor. The date will be displayed with date and time components
+ * using the default date format
+ *
+ * @param c the column
+ * @param r the row
+ * @param d the date
+ */
+ public DateTime(int c, int r, Date d)
+ {
+ super(c, r, d);
+ }
+
+ /**
+ * Constructor, which adjusts the specified date to take timezone
+ * considerations into account. The date passed in will be displayed with
+ * date and time components using the default date format
+ *
+ * @param c the column
+ * @param r the row
+ * @param d the date
+ * @param a dummy overload
+ */
+ public DateTime(int c, int r, Date d, GMTDate a)
+ {
+ super(c, r, d, a);
+ }
+
+ /**
+ * Constructor which takes the format for this cell
+ *
+ * @param c the column
+ * @param r the row
+ * @param st the format
+ * @param d the date
+ */
+ public DateTime(int c, int r, Date d, CellFormat st)
+ {
+ super(c, r, d, st);
+ }
+
+ /**
+ * Constructor, which adjusts the specified date to take timezone
+ * considerations into account
+ *
+ * @param c the column
+ * @param r the row
+ * @param d the date
+ * @param st the cell format
+ * @param a the cummy overload
+ */
+ public DateTime(int c, int r, Date d, CellFormat st, GMTDate a)
+ {
+ super(c, r, d, st, a);
+ }
+
+ /**
+ * Constructor which takes the format for the cell and an indicator
+ * as to whether this cell is a full date time or purely just a time
+ * eg. if the spreadsheet is to contain the world record for 100m, then the
+ * value would be 9.83s, which would be indicated as just a time
+ *
+ * @param c the column
+ * @param r the row
+ * @param st the style
+ * @param tim flag indicating that this represents a time
+ * @param d the date
+ */
+ public DateTime(int c, int r, Date d, CellFormat st, boolean tim)
+ {
+ super(c, r, d, st, tim);
+ }
+
+ /**
+ * A constructor called by the worksheet when creating a writable version
+ * of a spreadsheet that has been read in
+ *
+ * @param dc the date to copy
+ */
+ public DateTime(DateCell dc)
+ {
+ super(dc);
+ }
+
+ /**
+ * Copy constructor used for deep copying
+ *
+ * @param col the column
+ * @param row the row
+ * @param dt the date to copy
+ */
+ protected DateTime(int col, int row, DateTime dt)
+ {
+ super(col, row, dt);
+ }
+
+
+ /**
+ * Sets the date for this cell
+ *
+ * @param d the date
+ */
+ public void setDate(Date d)
+ {
+ super.setDate(d);
+ }
+
+ /**
+ * Sets the date for this cell, performing the necessary timezone adjustments
+ *
+ * @param d the date
+ * @param a the dummy overload
+ */
+ public void setDate(Date d, GMTDate a)
+ {
+ super.setDate(d, a);
+ }
+
+ /**
+ * Implementation of the deep copy function
+ *
+ * @param col the column which the new cell will occupy
+ * @param row the row which the new cell will occupy
+ * @return a copy of this cell, which can then be added to the sheet
+ */
+ public WritableCell copyTo(int col, int row)
+ {
+ return new DateTime(col, row, this);
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/Font.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/Font.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/Font.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,216 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import jxl.format.Colour;
+import jxl.format.ScriptStyle;
+import jxl.format.UnderlineStyle;
+
+/**
+ * A class which is instantiated when the user application wishes to specify
+ * the font for a particular cell
+ *
+ * @deprecated Renamed to writable font
+ */
+public class Font extends WritableFont
+{
+ /**
+ * Objects created with this font name will be rendered within Excel as ARIAL
+ * fonts
+ * @deprecated
+ */
+ public static final FontName ARIAL = WritableFont.ARIAL;
+ /**
+ * Objects created with this font name will be rendered within Excel as TIMES
+ * fonts
+ * @deprecated
+ */
+ public static final FontName TIMES = WritableFont.TIMES;
+
+ // The bold styles
+
+ /**
+ * Indicates that this font should not be presented as bold
+ * @deprecated
+ */
+ public static final BoldStyle NO_BOLD = WritableFont.NO_BOLD;
+ /**
+ * Indicates that this font should be presented in a BOLD style
+ * @deprecated
+ */
+ public static final BoldStyle BOLD = WritableFont.BOLD;
+
+ // The underline styles
+ /**
+ * @deprecated
+ */
+ public static final UnderlineStyle NO_UNDERLINE =
+ UnderlineStyle.NO_UNDERLINE;
+
+ /**
+ * @deprecated
+ */
+ public static final UnderlineStyle SINGLE = UnderlineStyle.SINGLE;
+
+ /**
+ * @deprecated
+ */
+ public static final UnderlineStyle DOUBLE = UnderlineStyle.DOUBLE;
+
+ /**
+ * @deprecated
+ */
+ public static final UnderlineStyle SINGLE_ACCOUNTING =
+ UnderlineStyle.SINGLE_ACCOUNTING;
+
+ /**
+ * @deprecated
+ */
+ public static final UnderlineStyle DOUBLE_ACCOUNTING =
+ UnderlineStyle.DOUBLE_ACCOUNTING;
+
+ // The script styles
+ public static final ScriptStyle NORMAL_SCRIPT = ScriptStyle.NORMAL_SCRIPT;
+ public static final ScriptStyle SUPERSCRIPT = ScriptStyle.SUPERSCRIPT;
+ public static final ScriptStyle SUBSCRIPT = ScriptStyle.SUBSCRIPT;
+
+ /**
+ * Creates a default font, vanilla font of the specified face and with
+ * default point size.
+ *
+ * @param fn the font name
+ * @deprecated Use jxl.write.WritableFont
+ */
+ public Font(FontName fn)
+ {
+ super(fn);
+ }
+
+ /**
+ * Constructs of font of the specified face and of size given by the
+ * specified point size
+ *
+ * @param ps the point size
+ * @param fn the font name
+ * @deprecated use jxl.write.WritableFont
+ */
+ public Font(FontName fn, int ps)
+ {
+ super(fn, ps);
+ }
+
+ /**
+ * Creates a font of the specified face, point size and bold style
+ *
+ * @param ps the point size
+ * @param bs the bold style
+ * @param fn the font name
+ * @deprecated use jxl.write.WritableFont
+ */
+ public Font(FontName fn, int ps, BoldStyle bs)
+ {
+ super(fn, ps, bs);
+ }
+
+ /**
+ * Creates a font of the specified face, point size, bold weight and
+ * italicised option.
+ *
+ * @param ps the point size
+ * @param bs the bold style
+ * @param italic italic flag
+ * @param fn the font name
+ * @deprecated use jxl.write.WritableFont
+ */
+ public Font(FontName fn, int ps, BoldStyle bs, boolean italic)
+ {
+ super(fn, ps, bs, italic);
+ }
+
+ /**
+ * Creates a font of the specified face, point size, bold weight,
+ * italicisation and underline style
+ *
+ * @param ps the point size
+ * @param bs the bold style
+ * @param us underscore flag
+ * @param fn font name
+ * @param it italic flag
+ * @deprecated use jxl.write.WritableFont
+ */
+ public Font(FontName fn,
+ int ps,
+ BoldStyle bs,
+ boolean it,
+ UnderlineStyle us)
+ {
+ super(fn, ps, bs, it, us);
+ }
+
+
+ /**
+ * Creates a font of the specified face, point size, bold style,
+ * italicisation, underline style and colour
+ *
+ * @param ps the point size
+ * @param bs the bold style
+ * @param us the underline style
+ * @param fn the font name
+ * @param it italic flag
+ * @param c the colour
+ * @deprecated use jxl.write.WritableFont
+ */
+ public Font(FontName fn,
+ int ps,
+ BoldStyle bs,
+ boolean it,
+ UnderlineStyle us,
+ Colour c)
+ {
+ super(fn, ps, bs, it, us, c);
+ }
+
+
+ /**
+ * Creates a font of the specified face, point size, bold style,
+ * italicisation, underline style, colour, and script
+ * style (superscript/subscript)
+ *
+ * @param ps the point size
+ * @param bs the bold style
+ * @param us the underline style
+ * @param fn the font name
+ * @param it the italic flag
+ * @param c the colour
+ * @param ss the script style
+ * @deprecated use jxl.write.WritableFont
+ */
+ public Font(FontName fn,
+ int ps,
+ BoldStyle bs,
+ boolean it,
+ UnderlineStyle us,
+ Colour c,
+ ScriptStyle ss)
+ {
+ super(fn, ps, bs, it, us, c, ss);
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/write/Formula.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/Formula.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/Formula.java 17 Aug 2012 14:51:21 -0000 1.1
@@ -0,0 +1,77 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import jxl.format.CellFormat;
+import jxl.write.biff.FormulaRecord;
+
+/**
+ * A cell, created by user applications, which contains a numerical value
+ */
+public class Formula extends FormulaRecord implements WritableCell
+{
+ /**
+ * Constructs the formula
+ *
+ * @param c the column
+ * @param r the row
+ * @param form the formula
+ */
+ public Formula(int c, int r, String form)
+ {
+ super(c, r, form);
+ }
+
+ /**
+ * Constructs a formula
+ *
+ * @param c the column
+ * @param r the row
+ * @param form the formula
+ * @param st the cell style
+ */
+ public Formula(int c, int r, String form, CellFormat st)
+ {
+ super(c, r, form, st);
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param c the column
+ * @param r the row
+ * @param f the record to copy
+ */
+ protected Formula(int c, int r, Formula f)
+ {
+ super(c, r, f);
+ }
+ /**
+ * Implementation of the deep copy function
+ *
+ * @param col the column which the new cell will occupy
+ * @param row the row which the new cell will occupy
+ * @return a copy of this cell, which can then be added to the sheet
+ */
+ public WritableCell copyTo(int col, int row)
+ {
+ return new Formula(col, row, this);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/Label.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/Label.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/Label.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,104 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import jxl.LabelCell;
+import jxl.format.CellFormat;
+import jxl.write.biff.LabelRecord;
+
+/**
+ * A cell containing text which may be created by user applications
+ */
+public class Label extends LabelRecord implements WritableCell, LabelCell
+{
+ /**
+ * Creates a cell which, when added to the sheet, will be presented at the
+ * specified column and row co-ordinates and will contain the specified text
+ *
+ * @param c the column
+ * @param cont the text
+ * @param r the row
+ */
+ public Label(int c, int r, String cont)
+ {
+ super(c, r, cont);
+ }
+
+ /**
+ * Creates a cell which, when added to the sheet, will be presented at the
+ * specified column and row co-ordinates and will present the specified text
+ * in the manner specified by the CellFormat parameter
+ *
+ * @param c the column
+ * @param cont the data
+ * @param r the row
+ * @param st the cell format
+ */
+ public Label(int c, int r, String cont, CellFormat st)
+ {
+ super(c, r, cont, st);
+ }
+
+ /**
+ * Copy constructor used for deep copying
+ *
+ * @param col the column
+ * @param row the row
+ * @param l the label to copy
+ */
+ protected Label(int col, int row, Label l)
+ {
+ super(col, row, l);
+ }
+
+ /**
+ * Constructor used internally by the application when making a writable
+ * copy of a spreadsheet being read in
+ *
+ * @param lc the label to copy
+ */
+ public Label(LabelCell lc)
+ {
+ super(lc);
+ }
+
+ /**
+ * Sets the string contents of this cell
+ *
+ * @param s the new data
+ */
+ public void setString(String s)
+ {
+ super.setString(s);
+ }
+
+ /**
+ * Implementation of the deep copy function
+ *
+ * @param col the column which the new cell will occupy
+ * @param row the row which the new cell will occupy
+ * @return a copy of this cell, which can then be added to the sheet
+ */
+ public WritableCell copyTo(int col, int row)
+ {
+ return new Label(col, row, this);
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/write/Number.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/Number.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/Number.java 17 Aug 2012 14:51:21 -0000 1.1
@@ -0,0 +1,106 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import jxl.NumberCell;
+import jxl.format.CellFormat;
+import jxl.write.biff.NumberRecord;
+
+/**
+ * A cell, created by user applications, which contains a numerical value
+ */
+public class Number extends NumberRecord implements WritableCell, NumberCell
+{
+ /**
+ * Constructs a number, which, when added to a spreadsheet, will display the
+ * specified value at the column/row position indicated. By default, the
+ * cell will display with an accuracy of 3 decimal places
+ *
+ * @param c the column
+ * @param r the row
+ * @param val the value
+ */
+ public Number(int c, int r, double val)
+ {
+ super(c, r, val);
+ }
+
+ /**
+ * Constructs a number, which, when added to a spreadsheet, will display the
+ * specified value at the column/row position with the specified CellFormat.
+ * The CellFormat may specify font information and number format information
+ * such as the number of decimal places
+ *
+ * @param c the column
+ * @param r the row
+ * @param val the value
+ * @param st the cell format
+ */
+ public Number(int c, int r, double val, CellFormat st)
+ {
+ super(c, r, val, st);
+ }
+
+ /**
+ * Constructor used internally by the application when making a writable
+ * copy of a spreadsheet that has been read in
+ *
+ * @param nc the cell to copy
+ */
+ public Number(NumberCell nc)
+ {
+ super(nc);
+ }
+
+ /**
+ * Sets the numerical value for this cell
+ *
+ * @param val the value
+ */
+ public void setValue(double val)
+ {
+ super.setValue(val);
+ }
+
+ /**
+ * Copy constructor used for deep copying
+ *
+ * @param col the column
+ * @param row the row
+ * @param n the number to copy
+ */
+ protected Number(int col, int row, Number n)
+ {
+ super(col, row, n);
+ }
+
+ /**
+ * Implementation of the deep copy function
+ *
+ * @param col the column which the new cell will occupy
+ * @param row the row which the new cell will occupy
+ * @return a copy of this cell, which can then be added to the sheet
+ */
+ public WritableCell copyTo(int col, int row)
+ {
+ return new Number(col, row, this);
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/NumberFormat.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/NumberFormat.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/NumberFormat.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,139 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import java.text.DecimalFormat;
+
+import jxl.biff.DisplayFormat;
+import jxl.write.biff.NumberFormatRecord;
+
+/**
+ * A custom user defined number format, which may be instantiated within user
+ * applications in order to present numerical values to the appropriate level
+ * of accuracy.
+ * The string format used to create a number format adheres to the standard
+ * java specification, and JExcelAPI makes the necessary modifications so
+ * that it is rendered in Excel as the nearest possible equivalent.
+ * Once created, this may be used within a CellFormat object, which in turn
+ * is a parameter passed to the constructor of the Number cell
+ */
+public class NumberFormat extends NumberFormatRecord implements DisplayFormat
+{
+ /**
+ * Pass in to the constructor to bypass the format validation
+ */
+ public static final NonValidatingFormat COMPLEX_FORMAT =
+ new NumberFormatRecord.NonValidatingFormat();
+
+ // Some format strings
+
+ /**
+ * Constant format string for the Euro currency symbol where it precedes
+ * the format
+ */
+ public static final String CURRENCY_EURO_PREFIX = "[$�-2]";
+
+ /**
+ * Constant format string for the Euro currency symbol where it precedes
+ * the format
+ */
+ public static final String CURRENCY_EURO_SUFFIX = "[$�-1]";
+
+ /**
+ * Constant format string for the UK pound sign
+ */
+ public static final String CURRENCY_POUND = "�";
+
+ /**
+ * Constant format string for the Japanese Yen sign
+ */
+ public static final String CURRENCY_JAPANESE_YEN = "[$�-411]";
+
+ /**
+ * Constant format string for the US Dollar sign
+ */
+ public static final String CURRENCY_DOLLAR = "[$$-409]";
+
+ /**
+ * Constant format string for three digit fractions
+ */
+ public static final String FRACTION_THREE_DIGITS = "???/???";
+
+ /**
+ * Constant format string for fractions as halves
+ */
+ public static final String FRACTION_HALVES = "?/2";
+
+ /**
+ * Constant format string for fractions as quarter
+ */
+ public static final String FRACTION_QUARTERS = "?/4";
+
+ /**
+ * Constant format string for fractions as eighths
+ */
+ public static final String FRACTIONS_EIGHTHS = "?/8";
+
+ /**
+ * Constant format string for fractions as sixteenths
+ */
+ public static final String FRACTION_SIXTEENTHS = "?/16";
+
+ /**
+ * Constant format string for fractions as tenths
+ */
+ public static final String FRACTION_TENTHS = "?/10";
+
+ /**
+ * Constant format string for fractions as hundredths
+ */
+ public static final String FRACTION_HUNDREDTHS = "?/100";
+
+ /**
+ * Constructor, taking in the Java compliant number format
+ *
+ * @param format the format string
+ */
+ public NumberFormat(String format)
+ {
+ super(format);
+
+ // Verify that the format is valid
+ DecimalFormat df = new DecimalFormat(format);
+ }
+
+ /**
+ * Constructor, taking in the non-Java compliant number format. This
+ * may be used for currencies and more complex custom formats, which
+ * will not be subject to the standard validation rules.
+ * As there is no validation, there is a resultant risk that the
+ * generated Excel file will be corrupt
+ *
+ * USE THIS CONSTRUCTOR ONLY IF YOU ARE CERTAIN THAT THE NUMBER FORMAT
+ * YOU ARE USING IS EXCEL COMPLIANT
+ *
+ * @param format the format string
+ * @param dummy dummy parameter
+ */
+ public NumberFormat(String format, NonValidatingFormat dummy)
+ {
+ super(format, dummy);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/NumberFormats.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/NumberFormats.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/NumberFormats.java 17 Aug 2012 14:51:21 -0000 1.1
@@ -0,0 +1,304 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import jxl.biff.DisplayFormat;
+import jxl.format.Format;
+
+/**
+ * Static class which contains the available list of built in Number formats
+ */
+public final class NumberFormats
+{
+ /**
+ * Inner class which holds the format index
+ */
+ private static class BuiltInFormat implements DisplayFormat, Format
+ {
+ /**
+ * The built in number format index
+ */
+ private int index;
+
+ /**
+ * The format string
+ */
+ private String formatString;
+
+ /**
+ * Constructor, using the predetermined index
+ *
+ * @param i the index
+ * @param s the string
+ */
+ public BuiltInFormat(int i, String s)
+ {
+ index = i;
+ formatString = s;
+ }
+
+ /**
+ * Accessor for the format index
+ *
+ * @return the index
+ */
+ public int getFormatIndex()
+ {
+ return index;
+ }
+ /**
+ * Accessor to determine if this format has been initialized. Since it is
+ * built in, this will always return TRUE
+ *
+ * @return TRUE, since this is a built in format
+ */
+ public boolean isInitialized()
+ {
+ return true;
+ }
+ /**
+ * Determines whether this format is a built in format
+ *
+ * @return TRUE, since this is a built in numerical format
+ */
+ public boolean isBuiltIn()
+ {
+ return true;
+ }
+ /**
+ * Initializes this format with a dynamically determined index value.
+ * Since this is a built in, and hence the index value is predetermined,
+ * this method has an empty body
+ *
+ * @param pos the pos in the number formats list
+ */
+ public void initialize(int pos)
+ {
+ }
+ /**
+ * Accesses the excel format string which is applied to the cell
+ * Note that this is the string that excel uses, and not the java
+ * equivalent
+ *
+ * @return the cell format string
+ */
+ public String getFormatString()
+ {
+ return formatString;
+ }
+
+ /**
+ * Standard equals method
+ *
+ * @param o the object to compare
+ * @return TRUE if the two objects are equal, FALSE otherwise
+ */
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+
+ if (!(o instanceof BuiltInFormat))
+ {
+ return false;
+ }
+
+ BuiltInFormat bif = (BuiltInFormat) o;
+
+ return index == bif.index;
+ }
+
+ /**
+ * Standard hash code method
+ *
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ return index;
+ }
+ }
+
+
+ // The available built in number formats
+ // First describe the fairly bog standard formats
+
+ /**
+ * The default format. This is equivalent to a number format of '#'
+ */
+ public static final DisplayFormat DEFAULT = new BuiltInFormat(0x0, "#");
+ /**
+ * Formatting for an integer number. This is equivalent to a DecimalFormat
+ * of "0"
+ */
+ public static final DisplayFormat INTEGER = new BuiltInFormat(0x1, "0");
+
+ /**
+ * Formatting for a float. This formats number to two decimal places. It
+ * is equivalent to a DecimalFormat of "0.00"
+ */
+ public static final DisplayFormat FLOAT = new BuiltInFormat(0x2, "0.00");
+
+ /**
+ * Formatting for an integer that has a thousands separator.
+ * Equivalent to a DecimalFormat of "#,##0"
+ */
+ public static final DisplayFormat THOUSANDS_INTEGER =
+ new BuiltInFormat(0x3, "#,##0");
+
+ /**
+ * Formatting for a float that has a thousands separator.
+ * Equivalent to a DecimalFormat of "#,##0.00"
+ */
+ public static final DisplayFormat THOUSANDS_FLOAT =
+ new BuiltInFormat(0x4, "#,##0.00");
+
+ /**
+ * Formatting for an integer which is presented in accounting format
+ * (ie. deficits appear in parentheses)
+ * Equivalent to a DecimalFormat of "$#,##0;($#,##0)"
+ */
+ public static final DisplayFormat ACCOUNTING_INTEGER =
+ new BuiltInFormat(0x5, "$#,##0;($#,##0)");
+
+ /**
+ * As ACCOUNTING_INTEGER except that deficits appear coloured red
+ */
+ public static final DisplayFormat ACCOUNTING_RED_INTEGER =
+ new BuiltInFormat(0x6, "$#,##0;($#,##0)");
+
+ /**
+ * Formatting for an integer which is presented in accounting format
+ * (ie. deficits appear in parentheses)
+ * Equivalent to a DecimalFormat of "$#,##0;($#,##0)"
+ */
+ public static final DisplayFormat ACCOUNTING_FLOAT =
+ new BuiltInFormat(0x7, "$#,##0;($#,##0)");
+
+ /**
+ * As ACCOUNTING_FLOAT except that deficits appear coloured red
+ */
+ public static final DisplayFormat ACCOUNTING_RED_FLOAT =
+ new BuiltInFormat(0x8, "$#,##0;($#,##0)");
+
+ /**
+ * Formatting for an integer presented as a percentage
+ * Equivalent to a DecimalFormat of "0%"
+ */
+ public static final DisplayFormat PERCENT_INTEGER =
+ new BuiltInFormat(0x9, "0%");
+
+ /**
+ * Formatting for a float percentage
+ * Equivalent to a DecimalFormat "0.00%"
+ */
+ public static final DisplayFormat PERCENT_FLOAT =
+ new BuiltInFormat(0xa, "0.00%");
+
+ /**
+ * Formatting for exponential or scientific notation
+ * Equivalent to a DecimalFormat "0.00E00"
+ */
+ public static final DisplayFormat EXPONENTIAL =
+ new BuiltInFormat(0xb, "0.00E00");
+
+ /**
+ * Formatting for one digit fractions
+ */
+ public static final DisplayFormat FRACTION_ONE_DIGIT =
+ new BuiltInFormat(0xc,"?/?");
+
+ /**
+ * Formatting for two digit fractions
+ */
+ public static final DisplayFormat FRACTION_TWO_DIGITS =
+ new BuiltInFormat(0xd,"??/??");
+
+ // Now describe the more obscure formats
+
+ /**
+ * Equivalent to a DecimalFormat "#,##0;(#,##0)"
+ */
+ public static final DisplayFormat FORMAT1 =
+ new BuiltInFormat(0x25, "#,##0;(#,##0)");
+
+ /**
+ * Equivalent to FORMAT1 except deficits are coloured red
+ */
+ public static final DisplayFormat FORMAT2 =
+ new BuiltInFormat(0x26, "#,##0;(#,##0)");
+
+ /**
+ * Equivalent to DecimalFormat "#,##0.00;(#,##0.00)"
+ */
+ public static final DisplayFormat FORMAT3 =
+ new BuiltInFormat(0x27, "#,##0.00;(#,##0.00)");
+
+ /**
+ * Equivalent to FORMAT3 except deficits are coloured red
+ */
+ public static final DisplayFormat FORMAT4 =
+ new BuiltInFormat(0x28, "#,##0.00;(#,##0.00)");
+
+ /**
+ * Equivalent to DecimalFormat "#,##0;(#,##0)"
+ */
+ public static final DisplayFormat FORMAT5 =
+ new BuiltInFormat(0x29, "#,##0;(#,##0)");
+
+ /**
+ * Equivalent to FORMAT5 except deficits are coloured red
+ */
+ public static final DisplayFormat FORMAT6 =
+ new BuiltInFormat(0x2a, "#,##0;(#,##0)");
+
+ /**
+ * Equivalent to DecimalFormat "#,##0.00;(#,##0.00)"
+ */
+ public static final DisplayFormat FORMAT7 =
+ new BuiltInFormat(0x2b, "#,##0.00;(#,##0.00)");
+
+ /**
+ * Equivalent to FORMAT7 except deficits are coloured red
+ */
+ public static final DisplayFormat FORMAT8 =
+ new BuiltInFormat(0x2c, "#,##0.00;(#,##0.00)");
+
+ /**
+ * Equivalent to FORMAT7
+ */
+ public static final DisplayFormat FORMAT9 =
+ new BuiltInFormat(0x2e, "#,##0.00;(#,##0.00)");
+
+ /**
+ * Equivalent to DecimalFormat "##0.0E0"
+ */
+ public static final DisplayFormat FORMAT10 =
+ new BuiltInFormat(0x30, "##0.0E0");
+
+ /**
+ * Forces numbers to be interpreted as text
+ */
+ public static final DisplayFormat TEXT = new BuiltInFormat(0x31, "@");
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/Pattern.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/Pattern.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/Pattern.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,50 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+/**
+ * Enumeration class which contains the various patterns available within
+ * the standard Excel pattern palette
+ *
+ * @deprecated Repackaged as jxl.format.Pattern
+ */
+public final class Pattern extends jxl.format.Pattern
+{
+ /**
+ * Private constructor
+ *
+ * @param val
+ */
+ private Pattern()
+ {
+ super(0, null);
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/VerticalAlignment.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/VerticalAlignment.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/VerticalAlignment.java 17 Aug 2012 14:51:21 -0000 1.1
@@ -0,0 +1,37 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+/**
+ * Enumeration type which describes the vertical alignment of data within a cell
+ *
+ * @deprecated Repackaged as jxl.format.VerticalAlignment
+ */
+public final class VerticalAlignment extends jxl.format.VerticalAlignment
+{
+ /**
+ * Constructor
+ */
+ private VerticalAlignment()
+ {
+ super(0, null);
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/write/WritableCell.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/WritableCell.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/WritableCell.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,62 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import jxl.Cell;
+import jxl.format.CellFormat;
+
+/**
+ * The interface for all writable cells
+ */
+public interface WritableCell extends Cell
+{
+ /**
+ * Sets the cell format for this cell
+ *
+ * @param cf the cell format
+ */
+ public void setCellFormat(CellFormat cf);
+
+ /**
+ * A deep copy. The returned cell still needs to be added to the sheet.
+ * By not automatically adding the cell to the sheet, the client program
+ * may change certain attributes, such as the value or the format
+ *
+ * @param col the column which the new cell will occupy
+ * @param row the row which the new cell will occupy
+ * @return a copy of this cell, which can then be added to the sheet
+ */
+ public WritableCell copyTo(int col, int row);
+
+ /**
+ * Accessor for the cell features
+ *
+ * @return the cell features or NULL if this cell doesn't have any
+ */
+ public WritableCellFeatures getWritableCellFeatures();
+
+ /**
+ * Sets the cell features
+ *
+ * @param cf the cell features
+ */
+ public void setCellFeatures(WritableCellFeatures cf);
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/write/WritableCellFeatures.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/WritableCellFeatures.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/WritableCellFeatures.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,168 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import java.util.Collection;
+
+import jxl.CellFeatures;
+import jxl.biff.BaseCellFeatures;
+
+/**
+ * Container for any additional cell features
+ */
+public class WritableCellFeatures extends CellFeatures
+{
+ // shadow the conditions in the base class so that they appear on
+ // the public generated javadoc
+ public static final ValidationCondition BETWEEN = BaseCellFeatures.BETWEEN;
+ public static final ValidationCondition NOT_BETWEEN =
+ BaseCellFeatures.NOT_BETWEEN;
+ public static final ValidationCondition EQUAL = BaseCellFeatures.EQUAL;
+ public static final ValidationCondition NOT_EQUAL =
+ BaseCellFeatures.NOT_EQUAL;
+ public static final ValidationCondition GREATER_THAN =
+ BaseCellFeatures.GREATER_THAN;
+ public static final ValidationCondition LESS_THAN =
+ BaseCellFeatures.LESS_THAN;
+ public static final ValidationCondition GREATER_EQUAL =
+ BaseCellFeatures.GREATER_EQUAL;
+ public static final ValidationCondition LESS_EQUAL =
+ BaseCellFeatures.LESS_EQUAL;
+
+ /**
+ * Constructor
+ */
+ public WritableCellFeatures()
+ {
+ super();
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param cf the cell to copy
+ */
+ public WritableCellFeatures(CellFeatures cf)
+ {
+ super(cf);
+ }
+
+ /**
+ * Sets the cell comment
+ *
+ * @param s the comment
+ */
+ public void setComment(String s)
+ {
+ super.setComment(s);
+ }
+
+ /**
+ * Sets the cell comment and sets the size of the text box (in cells)
+ * in which the comment is displayed
+ *
+ * @param s the comment
+ * @param width the width of the comment box in cells
+ * @param height the height of the comment box in cells
+ */
+ public void setComment(String s, double width, double height)
+ {
+ super.setComment(s, width, height);
+ }
+
+ /**
+ * Removes the cell comment, if present
+ */
+ public void removeComment()
+ {
+ super.removeComment();
+ }
+
+
+ /**
+ * Removes any data validation, if present
+ */
+ public void removeDataValidation()
+ {
+ super.removeDataValidation();
+ }
+
+ /**
+ * The list of items to validate for this cell. For each object in the
+ * collection, the toString() method will be called and the data entered
+ * will be validated against that string
+ *
+ * @param c the list of valid values
+ */
+ public void setDataValidationList(Collection c)
+ {
+ super.setDataValidationList(c);
+ }
+
+ /**
+ * The list of items to validate for this cell in the form of a cell range.
+ *
+ * @param col1 the first column containing the data to validate against
+ * @param row1 the first row containing the data to validate against
+ * @param col2 the second column containing the data to validate against
+ * @param row2 the second row containing the data to validate against
+ */
+ public void setDataValidationRange(int col1, int row1, int col2, int row2)
+ {
+ super.setDataValidationRange(col1, row1, col2, row2);
+ }
+
+ /**
+ * Sets the data validation based upon a named range
+ *
+ * @param namedRange the workbook named range defining the validation
+ * boundaries
+ */
+ public void setDataValidationRange(String namedRange)
+ {
+ super.setDataValidationRange(namedRange);
+ }
+
+
+ /**
+ * Sets the numeric value against which to validate
+ *
+ * @param val the number
+ * @param c the validation condition
+ */
+ public void setNumberValidation(double val, ValidationCondition c)
+ {
+ super.setNumberValidation(val, c);
+ }
+
+ /**
+ * Sets the numeric range against which to validate the data
+ *
+ * @param val1 the first number
+ * @param val2 the second number
+ * @param c the validation condition
+ */
+ public void setNumberValidation(double val1,
+ double val2,
+ ValidationCondition c)
+ {
+ super.setNumberValidation(val1, val2, c);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/WritableCellFormat.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/WritableCellFormat.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/WritableCellFormat.java 17 Aug 2012 14:51:21 -0000 1.1
@@ -0,0 +1,235 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import jxl.biff.DisplayFormat;
+import jxl.format.Alignment;
+import jxl.format.Border;
+import jxl.format.BorderLineStyle;
+import jxl.format.CellFormat;
+import jxl.format.Colour;
+import jxl.format.Orientation;
+import jxl.format.Pattern;
+import jxl.format.VerticalAlignment;
+import jxl.write.biff.CellXFRecord;
+
+/**
+ * A user specified cell format, which may be reused across many cells.
+ * The constructors takes parameters, such as font details and the numerical
+ * date formats, which specify to Excel how cells with this format should be
+ * displayed.
+ * Once a CellFormat has been added to a Cell which has been added to
+ * a sheet, then the CellFormat becomes immutable (to prevent unforeseen
+ * effects on other cells which share the same format). Attempts to
+ * call the various set... functions on a WritableCellFormat after this
+ * time will result in a runtime exception.
+ */
+public class WritableCellFormat extends CellXFRecord
+{
+ /**
+ * A default constructor, which uses the default font and format.
+ * This constructor should be used in conjunction with the more
+ * advanced two-phase methods setAlignment, setBorder etc.
+ */
+ public WritableCellFormat()
+ {
+ this(WritableWorkbook.ARIAL_10_PT, NumberFormats.DEFAULT);
+ }
+
+ /**
+ * A CellFormat which specifies the font for cells with this format
+ *
+ * @param font the font
+ */
+ public WritableCellFormat(WritableFont font)
+ {
+ this(font, NumberFormats.DEFAULT);
+ }
+
+ /**
+ * A constructor which specifies a date/number format for Cells which
+ * use this format object
+ *
+ * @param format the format
+ */
+ public WritableCellFormat(DisplayFormat format)
+ {
+ this(WritableWorkbook.ARIAL_10_PT, format);
+ }
+
+ /**
+ * A constructor which specifies the font and date/number format for cells
+ * which wish to use this format
+ *
+ * @param font the font
+ * @param format the date/number format
+ */
+ public WritableCellFormat(WritableFont font, DisplayFormat format)
+ {
+ super(font, format);
+ }
+
+ /**
+ * A public copy constructor which can be used for copy formats between
+ * different sheets
+ * @param format the cell format to copy
+ */
+ public WritableCellFormat(CellFormat format)
+ {
+ super(format);
+ }
+
+ /**
+ * Sets the horizontal alignment for this format
+ *
+ * @param a the alignment
+ * @exception WriteException
+ */
+ public void setAlignment(Alignment a) throws WriteException
+ {
+ super.setAlignment(a);
+ }
+
+ /**
+ * Sets the vertical alignment for this format
+ *
+ * @param va the vertical alignment
+ * @exception WriteException
+ */
+ public void setVerticalAlignment(VerticalAlignment va) throws WriteException
+ {
+ super.setVerticalAlignment(va);
+ }
+
+ /**
+ * Sets the text orientation for this format
+ *
+ * @param o the orientation
+ * @exception WriteException
+ */
+ public void setOrientation(Orientation o) throws WriteException
+ {
+ super.setOrientation(o);
+ }
+
+ /**
+ * Sets the wrap indicator for this format. If the wrap is set to TRUE, then
+ * Excel will wrap data in cells with this format so that it fits within the
+ * cell boundaries
+ *
+ * @param w the wrap flag
+ * @exception jxl.write.WriteException
+ */
+ public void setWrap(boolean w) throws WriteException
+ {
+ super.setWrap(w);
+ }
+
+ /**
+ * Sets the specified border for this format
+ *
+ * @param b the border
+ * @param ls the border line style
+ * @exception jxl.write.WriteException
+ */
+ public void setBorder(Border b, BorderLineStyle ls) throws WriteException
+ {
+ super.setBorder(b, ls, Colour.BLACK);
+ }
+
+ /**
+ * Sets the specified border for this format
+ *
+ * @param b the border
+ * @param ls the border line style
+ * @param c the colour of the specified border
+ * @exception jxl.write.WriteException
+ */
+ public void setBorder(Border b, BorderLineStyle ls, Colour c)
+ throws WriteException
+ {
+ super.setBorder(b, ls, c);
+ }
+
+ /**
+ * Sets the background colour for this cell format
+ *
+ * @param c the bacground colour
+ * @exception jxl.write.WriteException
+ */
+ public void setBackground(Colour c) throws WriteException
+ {
+ this.setBackground(c, Pattern.SOLID);
+ }
+
+ /**
+ * Sets the background colour and pattern for this cell format
+ *
+ * @param c the colour
+ * @param p the pattern
+ * @exception jxl.write.WriteException
+ */
+ public void setBackground(Colour c, Pattern p) throws WriteException
+ {
+ super.setBackground(c, p);
+ }
+
+ /**
+ * Sets the shrink to fit flag
+ *
+ * @param s shrink to fit flag
+ * @exception WriteException
+ */
+ public void setShrinkToFit(boolean s) throws WriteException
+ {
+ super.setShrinkToFit(s);
+ }
+
+ /**
+ * Sets the indentation of the cell text
+ *
+ * @param i the indentation
+ */
+ public void setIndentation(int i) throws WriteException
+ {
+ super.setIndentation(i);
+ }
+
+
+ /**
+ * Sets whether or not this XF record locks the cell. For this to
+ * have any effect, the sheet containing cells with this format must
+ * also be locke3d
+ *
+ * @param l the locked flag
+ * @exception WriteException
+ */
+ public void setLocked(boolean l) throws WriteException
+ {
+ super.setLocked(l);
+ }
+
+}
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/WritableFont.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/WritableFont.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/WritableFont.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,360 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import jxl.format.Colour;
+import jxl.format.Font;
+import jxl.format.ScriptStyle;
+import jxl.format.UnderlineStyle;
+import jxl.write.biff.WritableFontRecord;
+
+/**
+ * A class which is instantiated when the user application wishes to specify
+ * the font for a particular cell
+ */
+public class WritableFont extends WritableFontRecord
+{
+ /**
+ * Static inner class used for classifying the font names
+ */
+ public static class FontName
+ {
+ /**
+ * The name
+ */
+ String name;
+
+ /**
+ * Constructor
+ *
+ * @param s the font name
+ */
+ FontName(String s)
+ {
+ name = s;
+ }
+ }
+
+ /**
+ * Static inner class used for the boldness of the fonts
+ */
+ /*private*/ static class BoldStyle
+ {
+ /**
+ * The value
+ */
+ public int value;
+
+ /**
+ * Constructor
+ *
+ * @param val the value
+ */
+ BoldStyle(int val)
+ {
+ value = val;
+ }
+ }
+
+ /**
+ * Objects created with this font name will be rendered within Excel as ARIAL
+ * fonts
+ */
+ public static final FontName ARIAL = new FontName("Arial");
+ /**
+ * Objects created with this font name will be rendered within Excel as TIMES
+ * fonts
+ */
+ public static final FontName TIMES = new FontName("Times New Roman");
+ /**
+ * Objects created with this font name will be rendered within Excel as
+ * COURIER fonts
+ */
+ public static final FontName COURIER = new FontName("Courier New");
+ /**
+ * Objects created with this font name will be rendered within Excel as
+ * TAHOMA fonts
+ */
+ public static final FontName TAHOMA = new FontName("Tahoma");
+
+ // The bold styles
+
+ /**
+ * Indicates that this font should not be presented as bold
+ */
+ public static final BoldStyle NO_BOLD = new BoldStyle(0x190);
+ /**
+ * Indicates that this font should be presented in a BOLD style
+ */
+ public static final BoldStyle BOLD = new BoldStyle(0x2bc);
+
+ /**
+ * The default point size for all Fonts
+ */
+ public static final int DEFAULT_POINT_SIZE = 10;
+
+ /**
+ * Creates a default font, vanilla font of the specified face and with
+ * default point size.
+ *
+ * @param fn the font name
+ */
+ public WritableFont(FontName fn)
+ {
+ this(fn,
+ DEFAULT_POINT_SIZE,
+ NO_BOLD,
+ false,
+ UnderlineStyle.NO_UNDERLINE,
+ Colour.BLACK,
+ ScriptStyle.NORMAL_SCRIPT);
+ }
+
+ /**
+ * Publicly available copy constructor
+ *
+ * @param f the font to copy
+ */
+ public WritableFont(Font f)
+ {
+ super(f);
+ }
+
+ /**
+ * Constructs of font of the specified face and of size given by the
+ * specified point size
+ *
+ * @param ps the point size
+ * @param fn the font name
+ */
+ public WritableFont(FontName fn, int ps)
+ {
+ this(fn, ps, NO_BOLD, false,
+ UnderlineStyle.NO_UNDERLINE,
+ Colour.BLACK,
+ ScriptStyle.NORMAL_SCRIPT);
+ }
+
+ /**
+ * Creates a font of the specified face, point size and bold style
+ *
+ * @param ps the point size
+ * @param bs the bold style
+ * @param fn the font name
+ */
+ public WritableFont(FontName fn, int ps, BoldStyle bs)
+ {
+ this(fn, ps, bs, false,
+ UnderlineStyle.NO_UNDERLINE,
+ Colour.BLACK,
+ ScriptStyle.NORMAL_SCRIPT);
+ }
+
+ /**
+ * Creates a font of the specified face, point size, bold weight and
+ * italicised option.
+ *
+ * @param ps the point size
+ * @param bs the bold style
+ * @param italic italic flag
+ * @param fn the font name
+ */
+ public WritableFont(FontName fn, int ps, BoldStyle bs, boolean italic)
+ {
+ this(fn, ps, bs, italic,
+ UnderlineStyle.NO_UNDERLINE,
+ Colour.BLACK,
+ ScriptStyle.NORMAL_SCRIPT);
+ }
+
+ /**
+ * Creates a font of the specified face, point size, bold weight,
+ * italicisation and underline style
+ *
+ * @param ps the point size
+ * @param bs the bold style
+ * @param us the underline style
+ * @param fn the font name
+ * @param it italic flag
+ */
+ public WritableFont(FontName fn,
+ int ps,
+ BoldStyle bs,
+ boolean it,
+ UnderlineStyle us)
+ {
+ this(fn, ps, bs, it, us, Colour.BLACK, ScriptStyle.NORMAL_SCRIPT);
+ }
+
+
+ /**
+ * Creates a font of the specified face, point size, bold style,
+ * italicisation, underline style and colour
+ *
+ * @param ps the point size
+ * @param bs the bold style
+ * @param us the underline style
+ * @param fn the font name
+ * @param it italic flag
+ * @param c the colour
+ */
+ public WritableFont(FontName fn,
+ int ps,
+ BoldStyle bs,
+ boolean it,
+ UnderlineStyle us,
+ Colour c)
+ {
+ this(fn, ps, bs, it, us, c, ScriptStyle.NORMAL_SCRIPT);
+ }
+
+
+ /**
+ * Creates a font of the specified face, point size, bold style,
+ * italicisation, underline style, colour, and script
+ * style (superscript/subscript)
+ *
+ * @param ps the point size
+ * @param bs the bold style
+ * @param us the underline style
+ * @param fn the font name
+ * @param it the italic flag
+ * @param c the colour
+ * @param ss the script style
+ */
+ public WritableFont(FontName fn,
+ int ps,
+ BoldStyle bs,
+ boolean it,
+ UnderlineStyle us,
+ Colour c,
+ ScriptStyle ss)
+ {
+ super(fn.name, ps, bs.value, it,
+ us.getValue(),
+ c.getValue(), ss.getValue());
+ }
+
+ /**
+ * Sets the point size for this font, if the font hasn't been initialized
+ *
+ * @param pointSize the point size
+ * @exception WriteException, if this font is already in use elsewhere
+ */
+ public void setPointSize(int pointSize) throws WriteException
+ {
+ super.setPointSize(pointSize);
+ }
+
+ /**
+ * Sets the bold style for this font, if the font hasn't been initialized
+ *
+ * @param boldStyle the bold style
+ * @exception WriteException, if this font is already in use elsewhere
+ */
+ public void setBoldStyle(BoldStyle boldStyle) throws WriteException
+ {
+ super.setBoldStyle(boldStyle.value);
+ }
+
+ /**
+ * Sets the italic indicator for this font, if the font hasn't been
+ * initialized
+ *
+ * @param italic the italic flag
+ * @exception WriteException, if this font is already in use elsewhere
+ */
+ public void setItalic(boolean italic) throws WriteException
+ {
+ super.setItalic(italic);
+ }
+
+ /**
+ * Sets the underline style for this font, if the font hasn't been
+ * initialized
+ *
+ * @param us the underline style
+ * @exception WriteException, if this font is already in use elsewhere
+ */
+ public void setUnderlineStyle(UnderlineStyle us) throws WriteException
+ {
+ super.setUnderlineStyle(us.getValue());
+ }
+
+ /**
+ * Sets the colour for this font, if the font hasn't been
+ * initialized
+ *
+ * @param colour the colour
+ * @exception WriteException, if this font is already in use elsewhere
+ */
+ public void setColour(Colour colour) throws WriteException
+ {
+ super.setColour(colour.getValue());
+ }
+
+ /**
+ * Sets the script style (eg. superscript, subscript) for this font,
+ * if the font hasn't been initialized
+ *
+ * @param scriptStyle the colour
+ * @exception WriteException, if this font is already in use elsewhere
+ */
+ public void setScriptStyle(ScriptStyle scriptStyle) throws WriteException
+ {
+ super.setScriptStyle(scriptStyle.getValue());
+ }
+
+ /**
+ * Accessor for the strike-out flag
+ *
+ * @return the strike-out flag
+ */
+ public boolean isStruckout()
+ {
+ return super.isStruckout();
+ }
+
+ /**
+ * Sets Accessor for the strike-out flag
+ *
+ * @param struckout TRUE if this is a struckout font
+ * @return the strike-out flag
+ * @exception WriteException, if this font is already in use elsewhere
+ */
+ public void setStruckout(boolean struckout) throws WriteException
+ {
+ super.setStruckout(struckout);
+ }
+
+ /**
+ * Factory method which creates the specified font name. This method
+ * should be used with care, since the string used to create the font
+ * name must be recognized by Excel's internal processing
+ *
+ * @param fontName the name of the Excel font
+ * @return the font name
+ */
+ public static FontName createFont(String fontName)
+ {
+ return new FontName(fontName);
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/write/WritableHyperlink.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/WritableHyperlink.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/WritableHyperlink.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,248 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import java.io.File;
+import java.net.URL;
+
+import jxl.Hyperlink;
+import jxl.write.biff.HyperlinkRecord;
+
+/**
+ * A writable hyperlink. Provides API to modify the contents of the hyperlink
+ */
+public class WritableHyperlink extends HyperlinkRecord implements Hyperlink
+{
+ /**
+ * Constructor used internally by the worksheet when making a copy
+ * of worksheet
+ *
+ * @param h the hyperlink being read in
+ * @param ws the writable sheet containing the hyperlink
+ */
+ public WritableHyperlink(Hyperlink h, WritableSheet ws)
+ {
+ super(h, ws);
+ }
+
+ /**
+ * Constructs a URL hyperlink in a single cell
+ *
+ * @param col the column containing this hyperlink
+ * @param row the row containing this hyperlink
+ * @param url the hyperlink
+ */
+ public WritableHyperlink(int col, int row, URL url)
+ {
+ this(col, row, col, row, url);
+ }
+
+ /**
+ * Constructs a url hyperlink to a range of cells
+ *
+ * @param col the column containing this hyperlink
+ * @param row the row containing this hyperlink
+ * @param lastcol the last column which activates this hyperlink
+ * @param lastrow the last row which activates this hyperlink
+ * @param url the hyperlink
+ */
+ public WritableHyperlink(int col, int row, int lastcol, int lastrow, URL url)
+ {
+ this(col, row, lastcol, lastrow, url, null);
+ }
+
+ /**
+ * Constructs a url hyperlink to a range of cells
+ *
+ * @param col the column containing this hyperlink
+ * @param row the row containing this hyperlink
+ * @param lastcol the last column which activates this hyperlink
+ * @param lastrow the last row which activates this hyperlink
+ * @param url the hyperlink
+ * @param desc the description text to place in the cell
+ */
+ public WritableHyperlink(int col,
+ int row,
+ int lastcol,
+ int lastrow,
+ URL url,
+ String desc)
+ {
+ super(col, row, lastcol, lastrow, url, desc);
+ }
+
+ /**
+ * Constructs a file hyperlink in a single cell
+ *
+ * @param col the column containing this hyperlink
+ * @param row the row containing this hyperlink
+ * @param file the hyperlink
+ */
+ public WritableHyperlink(int col, int row, File file)
+ {
+ this(col, row, col, row, file, null);
+ }
+
+ /**
+ * Constructs a file hyperlink in a single cell
+ *
+ * @param col the column containing this hyperlink
+ * @param row the row containing this hyperlink
+ * @param file the hyperlink
+ * @param desc the hyperlink description
+ */
+ public WritableHyperlink(int col, int row, File file, String desc)
+ {
+ this(col, row, col, row, file, desc);
+ }
+
+ /**
+ * Constructs a File hyperlink to a range of cells
+ *
+ * @param col the column containing this hyperlink
+ * @param row the row containing this hyperlink
+ * @param lastcol the last column which activates this hyperlink
+ * @param lastrow the last row which activates this hyperlink
+ * @param file the hyperlink
+ */
+ public WritableHyperlink(int col, int row, int lastcol, int lastrow,
+ File file)
+ {
+ super(col, row, lastcol, lastrow, file, null);
+ }
+
+ /**
+ * Constructs a File hyperlink to a range of cells
+ *
+ * @param col the column containing this hyperlink
+ * @param row the row containing this hyperlink
+ * @param lastcol the last column which activates this hyperlink
+ * @param lastrow the last row which activates this hyperlink
+ * @param file the hyperlink
+ * @param desc the description
+ */
+ public WritableHyperlink(int col,
+ int row,
+ int lastcol,
+ int lastrow,
+ File file,
+ String desc)
+ {
+ super(col, row, lastcol, lastrow, file, desc);
+ }
+
+ /**
+ * Constructs a hyperlink to some cells within this workbook
+ *
+ * @param col the column containing this hyperlink
+ * @param row the row containing this hyperlink
+ * @param desc the cell contents for this hyperlink
+ * @param sheet the sheet containing the cells to be linked to
+ * @param destcol the column number of the first destination linked cell
+ * @param destrow the row number of the first destination linked cell
+ */
+ public WritableHyperlink(int col, int row,
+ String desc,
+ WritableSheet sheet,
+ int destcol, int destrow)
+ {
+ this(col, row, col, row,
+ desc,
+ sheet, destcol, destrow, destcol, destrow);
+ }
+
+ /**
+ * Constructs a hyperlink to some cells within this workbook
+ *
+ * @param col the column containing this hyperlink
+ * @param row the row containing this hyperlink
+ * @param lastcol the last column which activates this hyperlink
+ * @param lastrow the last row which activates this hyperlink
+ * @param desc the cell contents for this hyperlink
+ * @param sheet the sheet containing the cells to be linked to
+ * @param destcol the column number of the first destination linked cell
+ * @param destrow the row number of the first destination linked cell
+ * @param lastdestcol the column number of the last destination linked cell
+ * @param lastdestrow the row number of the last destination linked cell
+ */
+ public WritableHyperlink(int col, int row,
+ int lastcol, int lastrow,
+ String desc,
+ WritableSheet sheet,
+ int destcol, int destrow,
+ int lastdestcol, int lastdestrow)
+ {
+ super(col, row, lastcol, lastrow,
+ desc,
+ sheet, destcol, destrow,
+ lastdestcol, lastdestrow);
+ }
+
+ /**
+ * Sets the URL of this hyperlink
+ *
+ * @param url the url
+ */
+ public void setURL(URL url)
+ {
+ super.setURL(url);
+ }
+
+ /**
+ * Sets the file activated by this hyperlink
+ *
+ * @param file the file
+ */
+ public void setFile(File file)
+ {
+ super.setFile(file);
+ }
+
+ /**
+ * Sets the description to appear in the hyperlink cell
+ *
+ * @param desc the description
+ */
+ public void setDescription(String desc)
+ {
+ super.setContents(desc);
+ }
+
+ /**
+ * Sets the location of the cells to be linked to within this workbook
+ *
+ * @param desc the label describing the link
+ * @param sheet the sheet containing the cells to be linked to
+ * @param destcol the column number of the first destination linked cell
+ * @param destrow the row number of the first destination linked cell
+ * @param lastdestcol the column number of the last destination linked cell
+ * @param lastdestrow the row number of the last destination linked cell
+ */
+ public void setLocation(String desc,
+ WritableSheet sheet,
+ int destcol, int destrow,
+ int lastdestcol, int lastdestrow)
+ {
+ super.setLocation(desc, sheet, destcol, destrow, lastdestcol, lastdestrow);
+ }
+
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/WritableImage.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/WritableImage.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/WritableImage.java 17 Aug 2012 14:51:21 -0000 1.1
@@ -0,0 +1,224 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import java.io.File;
+
+import jxl.biff.drawing.Drawing;
+import jxl.biff.drawing.DrawingGroup;
+import jxl.biff.drawing.DrawingGroupObject;
+
+/**
+ * Allows an image to be created, or an existing image to be manipulated
+ * Note that co-ordinates and dimensions are given in cells, so that if for
+ * example the width or height of a cell which the image spans is altered,
+ * the image will have a correspondign distortion
+ */
+public class WritableImage extends Drawing
+{
+ // Shadow these values from the superclass. The only practical reason
+ // for doing this is that they appear nicely in the javadoc
+
+ /**
+ * Image anchor properties which will move and resize an image
+ * along with the cells
+ */
+ public static ImageAnchorProperties MOVE_AND_SIZE_WITH_CELLS =
+ Drawing.MOVE_AND_SIZE_WITH_CELLS;
+
+ /**
+ * Image anchor properties which will move an image
+ * when cells are inserted or deleted
+ */
+ public static ImageAnchorProperties MOVE_WITH_CELLS =
+ Drawing.MOVE_WITH_CELLS;
+
+ /**
+ * Image anchor properties which will leave an image unaffected when
+ * other cells are inserted, removed or resized
+ */
+ public static ImageAnchorProperties NO_MOVE_OR_SIZE_WITH_CELLS =
+ Drawing.NO_MOVE_OR_SIZE_WITH_CELLS;
+
+ /**
+ * Constructor
+ *
+ * @param x the column number at which to position the image
+ * @param y the row number at which to position the image
+ * @param width the number of columns cells which the image spans
+ * @param height the number of rows which the image spans
+ * @param image the source image file
+ */
+ public WritableImage(double x, double y,
+ double width, double height,
+ File image)
+ {
+ super(x, y, width, height, image);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param x the column number at which to position the image
+ * @param y the row number at which to position the image
+ * @param width the number of columns cells which the image spans
+ * @param height the number of rows which the image spans
+ * @param imageData the image data
+ */
+ public WritableImage(double x,
+ double y,
+ double width,
+ double height,
+ byte[] imageData)
+ {
+ super(x, y, width, height, imageData);
+ }
+
+ /**
+ * Constructor, used when copying sheets
+ *
+ * @param d the image to copy
+ * @param dg the drawing group
+ */
+ public WritableImage(DrawingGroupObject d, DrawingGroup dg)
+ {
+ super(d, dg);
+ }
+
+ /**
+ * Accessor for the image position
+ *
+ * @return the column number at which the image is positioned
+ */
+ public double getColumn()
+ {
+ return super.getX();
+ }
+
+ /**
+ * Accessor for the image position
+ *
+ * @param c the column number at which the image should be positioned
+ */
+ public void setColumn(double c)
+ {
+ super.setX(c);
+ }
+
+ /**
+ * Accessor for the image position
+ *
+ * @return the row number at which the image is positions
+ */
+ public double getRow()
+ {
+ return super.getY();
+ }
+
+ /**
+ * Accessor for the image position
+ *
+ * @param c the row number at which the image should be positioned
+ */
+ public void setRow(double c)
+ {
+ super.setY(c);
+ }
+
+ /**
+ * Accessor for the image dimensions
+ *
+ * @return the number of columns this image spans
+ */
+ public double getWidth()
+ {
+ return super.getWidth();
+ }
+
+ /**
+ * Accessor for the image dimensions
+ * Note that the actual size of the rendered image will depend on the
+ * width of the columns it spans
+ *
+ * @param c the number of columns which this image spans
+ */
+ public void setWidth(double c)
+ {
+ super.setWidth(c);
+ }
+
+ /**
+ * Accessor for the image dimensions
+ *
+ * @return the number of rows which this image spans
+ */
+ public double getHeight()
+ {
+ return super.getHeight();
+ }
+
+ /**
+ * Accessor for the image dimensions
+ * Note that the actual size of the rendered image will depend on the
+ * height of the rows it spans
+ *
+ * @param c the number of rows which this image should span
+ */
+ public void setHeight(double c)
+ {
+ super.setHeight(c);
+ }
+
+ /**
+ * Accessor for the image file
+ *
+ * @return the file which the image references
+ */
+ public File getImageFile()
+ {
+ return super.getImageFile();
+ }
+
+ /**
+ * Accessor for the image data
+ *
+ * @return the image data
+ */
+ public byte[] getImageData()
+ {
+ return super.getImageData();
+ }
+
+ /**
+ * Accessor for the anchor properties
+ */
+ public void setImageAnchor(ImageAnchorProperties iap)
+ {
+ super.setImageAnchor(iap);
+ }
+
+ /**
+ * Accessor for the anchor properties
+ */
+ public ImageAnchorProperties getImageAnchor()
+ {
+ return super.getImageAnchor();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/WritableImage.java2
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/WritableImage.java2,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/WritableImage.java2 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,181 @@
+/*********************************************************************
+*
+* Copyright (C) 2003 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import java.io.File;
+
+import jxl.biff.drawing.Drawing;
+import jxl.biff.drawing.DrawingGroupObject;
+import jxl.biff.drawing.DrawingGroup;
+
+/**
+ * Allows an image to be created, or an existing image to be manipulated
+ * Note that co-ordinates and dimensions are given in cells, so that if for
+ * example the width or height of a cell which the image spans is altered,
+ * the image will have a correspondign distortion
+ */
+public class WritableImage extends Drawing
+{
+ /**
+ * Constructor
+ *
+ * @param x the column number at which to position the image
+ * @param y the row number at which to position the image
+ * @param width the number of columns cells which the image spans
+ * @param height the number of rows which the image spans
+ * @param image the source image file
+ */
+ public WritableImage(double x, double y,
+ double width, double height,
+ File image)
+ {
+ super(x, y, width, height, image);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param x the column number at which to position the image
+ * @param y the row number at which to position the image
+ * @param width the number of columns cells which the image spans
+ * @param height the number of rows which the image spans
+ * @param image the image data
+ */
+ public WritableImage(double x, double y,
+ double width, double height,
+ byte[] imageData)
+ {
+ super(x, y, width, height, imageData);
+ }
+
+ /**
+ * Constructor, used when copying sheets
+ *
+ * @param d the image to copy
+ */
+ public WritableImage(DrawingGroupObject d, DrawingGroup dg)
+ {
+ super(d, dg);
+ }
+
+ /**
+ * Accessor for the image position
+ *
+ * @return the column number at which the image is positioned
+ */
+ public double getColumn()
+ {
+ return super.getX();
+ }
+
+ /**
+ * Accessor for the image position
+ *
+ * @param c the column number at which the image should be positioned
+ */
+ public void setColumn(double c)
+ {
+ super.setX(c);
+ }
+
+ /**
+ * Accessor for the image position
+ *
+ * @return the row number at which the image is positions
+ */
+ public double getRow()
+ {
+ return super.getY();
+ }
+
+ /**
+ * Accessor for the image position
+ *
+ * @param c the row number at which the image should be positioned
+ */
+ public void setRow(double c)
+ {
+ super.setY(c);
+ }
+
+ /**
+ * Accessor for the image dimensions
+ *
+ * @return the number of columns this image spans
+ */
+ public double getWidth()
+ {
+ return super.getWidth();
+ }
+
+ /**
+ * Accessor for the image dimensions
+ * Note that the actual size of the rendered image will depend on the
+ * width of the columns it spans
+ *
+ * @param c the number of columns which this image spans
+ */
+ public void setWidth(double c)
+ {
+ super.setWidth(c);
+ }
+
+ /**
+ * Accessor for the image dimensions
+ *
+ * @return the number of rows which this image spans
+ */
+ public double getHeight()
+ {
+ return super.getHeight();
+ }
+
+ /**
+ * Accessor for the image dimensions
+ * Note that the actual size of the rendered image will depend on the
+ * height of the rows it spans
+ *
+ * @param c the number of rows which this image should span
+ */
+ public void setHeight(double c)
+ {
+ super.setHeight(c);
+ }
+
+ /**
+ * Accessor for the image file
+ *
+ * @return the file which the image references
+ */
+ public File getImageFile()
+ {
+ return super.getImageFile();
+ }
+
+ /**
+ * Accessor for the image data
+ *
+ * @return the image data
+ */
+ public byte[] getImageData()
+ {
+ return super.getImageData();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/WritableSheet.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/WritableSheet.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/WritableSheet.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,409 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import jxl.CellView;
+import jxl.Range;
+import jxl.Sheet;
+import jxl.format.CellFormat;
+import jxl.format.PageOrientation;
+import jxl.format.PaperSize;
+import jxl.write.biff.RowsExceededException;
+
+/**
+ * Interface for a worksheet that may be modified. The most
+ * important modification for a sheet is to have cells added to it
+ */
+public interface WritableSheet extends Sheet
+{
+ /**
+ * Adds a cell to this sheet
+ * The RowsExceededException may be caught if client code wishes to
+ * explicitly trap the case where too many rows have been written
+ * to the current sheet. If this behaviour is not desired, it is
+ * sufficient simply to handle the WriteException, since this is a base
+ * class of RowsExceededException
+ *
+ * @param cell the cell to add
+ * @exception jxl.write..WriteException
+ * @exception jxl.write.biff.RowsExceededException
+ */
+ public void addCell(WritableCell cell)
+ throws WriteException, RowsExceededException;
+ /**
+ * Sets the name of this sheet
+ *
+ * @param name the name of the sheet
+ */
+ public void setName(String name);
+ /**
+ * Indicates whether or not this sheet is hidden
+ *
+ * @param hidden hidden flag
+ * @deprecated use the SheetSettings bean instead
+ */
+ public void setHidden(boolean hidden);
+ /**
+ * Indicates whether or not this sheet is protected
+ *
+ * @param prot Protected flag
+ * @deprecated use the SheetSettings bean instead
+ */
+ public void setProtected(boolean prot);
+
+ /**
+ * Sets the width of the column on this sheet, in characters. This causes
+ * Excel to resize the entire column.
+ * If the columns specified already has view information associated
+ * with it, then it is replaced by the new data
+ *
+ * @param col the column to be formatted
+ * @param width the width of the column
+ */
+ public void setColumnView(int col, int width);
+
+ /**
+ * Sets the width and style of every cell in the specified column.
+ * If the columns specified already has view information associated
+ * with it, then it is replaced by the new data
+ *
+ * @param col the column to be formatted
+ * @param format the format of every cell in the column
+ * @param width the width of the column, in characters
+ * @deprecated Use the CellView bean instead
+ */
+ public void setColumnView(int col, int width, CellFormat format);
+
+ /**
+ * Sets the view for this column
+ *
+ * @param col the column on which to set the view
+ * @param view the view to set
+ */
+ public void setColumnView(int col, CellView view);
+
+ /**
+ * Sets the height of the specified row, as well as its collapse status
+ *
+ * @param row the row to be formatted
+ * @param height the row height in characters
+ * @exception jxl.write.biff.RowsExceededException
+ */
+ public void setRowView(int row, int height)
+ throws RowsExceededException;
+
+ /**
+ * Sets the properties of the specified row
+ *
+ * @param row the row to be formatted
+ * @param collapsed indicates whether the row is collapsed
+ * @exception jxl.write.biff.RowsExceededException
+ */
+ public void setRowView(int row, boolean collapsed)
+ throws RowsExceededException;
+
+ /**
+ * Sets the height of the specified row, as well as its collapse status
+ *
+ * @param row the row to be formatted
+ * @param height the row height in 1/20th of a point
+ * @param collapsed indicates whether the row is collapsed
+ * @exception jxl.write.biff.RowsExceededException
+ */
+ public void setRowView(int row, int height,
+ boolean collapsed)
+ throws RowsExceededException;
+
+ /**
+ * Sets the view for this column
+ *
+ * @param row the column on which to set the view
+ * @param view the view to set
+ * @exception RowsExceededException
+ */
+ public void setRowView(int row, CellView view) throws RowsExceededException;
+
+ /**
+ * Gets the writable cell from this sheet. Use of this method allows
+ * the returned cell to be modified by the users application
+ *
+ * @param column the column
+ * @param row the row
+ * @return the cell at the specified position
+ */
+ public WritableCell getWritableCell(int column, int row);
+
+ /**
+ * Returns the cell for the specified location eg. "A4". Note that this
+ * method is identical to calling getCell(CellReferenceHelper.getColumn(loc),
+ * CellReferenceHelper.getRow(loc)) and its implicit performance
+ * overhead for string parsing. As such,this method should therefore
+ * be used sparingly
+ *
+ * @param loc the cell reference
+ * @return the cell at the specified co-ordinates
+ */
+ public WritableCell getWritableCell(String loc);
+
+ /**
+ * Gets the writable hyperlinks from this sheet. The hyperlinks
+ * that are returned may be modified by user applications
+ *
+ * @return the writable hyperlinks
+ */
+ public WritableHyperlink[] getWritableHyperlinks();
+
+ /**
+ * Inserts a blank row into this spreadsheet. If the row is out of range
+ * of the rows in the sheet, then no action is taken
+ *
+ * @param row the row to insert
+ */
+ public void insertRow(int row);
+
+ /**
+ * Inserts a blank column into this spreadsheet. If the column is out of
+ * range of the columns in the sheet, then no action is taken
+ *
+ * @param col the column to insert
+ */
+ public void insertColumn(int col);
+
+ /**
+ * Removes a column from this spreadsheet. If the column is out of range
+ * of the columns in the sheet, then no action is taken
+ *
+ * @param col the column to remove
+ */
+ public void removeColumn(int col);
+
+ /**
+ * Removes a row from this spreadsheet. If the row is out of
+ * range of the columns in the sheet, then no action is taken
+ *
+ * @param row the row to remove
+ */
+ public void removeRow(int row);
+
+ /**
+ * Merges the specified cells. Any clashes or intersections between
+ * merged cells are resolved when the spreadsheet is written out
+ *
+ * @param col1 the column number of the top left cell
+ * @param row1 the row number of the top left cell
+ * @param col2 the column number of the bottom right cell
+ * @param row2 the row number of the bottom right cell
+ * @return the Range object representing the merged cells
+ * @exception jxl.write..WriteException
+ * @exception jxl.write.biff.RowsExceededException
+ */
+ public Range mergeCells(int col1, int row1, int col2, int row2)
+ throws WriteException, RowsExceededException;
+
+ /**
+ * Sets a row grouping
+ *
+ * @param row1 the first row of the group
+ * @param row2 the last row of the group
+ * @param collapsed should the group be collapsed?
+ * @exception WriteException
+ * @exception RowsExceededException
+ */
+ public void setRowGroup(int row1, int row2, boolean collapsed)
+ throws WriteException, RowsExceededException;
+
+ /**
+ * Unsets a row grouping
+ *
+ * @param row1 the first row to unset
+ * @param row2 the last row to unset
+ * @exception WriteException
+ * @exception RowsExceededException
+ */
+ public void unsetRowGroup(int row1, int row2)
+ throws WriteException, RowsExceededException;
+
+ /**
+ * Sets a column grouping
+ *
+ * @param col1 the first column of the group
+ * @param col2 the last column of the group
+ * @param collapsed should the group be collapsed?
+ * @exception WriteException
+ * @exception RowsExceededException
+ */
+ public void setColumnGroup(int col1, int col2, boolean collapsed)
+ throws WriteException, RowsExceededException;
+
+ /**
+ * Unsets a column grouping
+ *
+ * @param col1 the first column to unset
+ * @param col2 the last column to unset
+ * @exception WriteException
+ * @exception RowsExceededException
+ */
+ public void unsetColumnGroup(int col1, int col2)
+ throws WriteException, RowsExceededException;
+
+ /**
+ * Unmerges the specified cells. The Range passed in should be one that
+ * has been previously returned as a result of the getMergedCells method
+ *
+ * @param r the range of cells to unmerge
+ */
+ public void unmergeCells(Range r);
+
+ /**
+ * Adds the specified hyperlink. Adding a hyperlink causes any populated
+ * cells in the range of the hyperlink to be set to empty
+ * If the cells which activate this hyperlink clash with any other cells,
+ * they are still added to the worksheet and it is left to Excel to
+ * handle this.
+ *
+ * @param h the hyperlink
+ * @exception jxl.write..WriteException
+ * @exception jxl.write.biff.RowsExceededException
+ */
+ public void addHyperlink(WritableHyperlink h)
+ throws WriteException, RowsExceededException;;
+
+ /**
+ * Removes the specified hyperlink. Note that if you merely set the
+ * cell contents to be an Empty cell, then the cells containing the
+ * hyperlink will still be active. The contents of the cell which
+ * activate the hyperlink are removed.
+ * The hyperlink passed in must be a hyperlink retrieved using the
+ * getHyperlinks method
+ *
+ * @param h the hyperlink to remove.
+ */
+ public void removeHyperlink(WritableHyperlink h);
+
+ /**
+ * Removes the specified hyperlink. Note that if you merely set the
+ * cell contents to be an Empty cell, then the cells containing the
+ * hyperlink will still be active.
+ * If the preserveLabel field is set, the cell contents of the
+ * hyperlink are preserved, although the hyperlink is deactivated. If
+ * this value is FALSE, the cell contents are removed
+ * The hyperlink passed in must be a hyperlink retrieved using the
+ * getHyperlinks method
+ *
+ * @param h the hyperlink to remove.
+ * @param preserveLabel if TRUE preserves the label contents, if FALSE
+ * removes them
+ */
+ public void removeHyperlink(WritableHyperlink h, boolean preserveLabel);
+
+ /**
+ * Sets the header for this page
+ *
+ * @param l the print header to print on the left side
+ * @param c the print header to print in the centre
+ * @param r the print header to print on the right hand side
+ * @deprecated use the SheetSettings bean
+ */
+ public void setHeader(String l, String c, String r);
+
+ /**
+ * Sets the footer for this page
+ *
+ * @param l the print header to print on the left side
+ * @param c the print header to print in the centre
+ * @param r the print header to print on the right hand side
+ * @deprecated use the SheetSettings bean
+ */
+ public void setFooter(String l, String c, String r);
+
+ /**
+ * Sets the page setup details
+ *
+ * @param p the page orientation
+ */
+ public void setPageSetup(PageOrientation p);
+
+ /**
+ * Sets the page setup details
+ *
+ * @param p the page orientation
+ * @param hm the header margin, in inches
+ * @param fm the footer margin, in inches
+ */
+ public void setPageSetup(PageOrientation p, double hm, double fm);
+
+ /**
+ * Sets the page setup details
+ *
+ * @param p the page orientation
+ * @param ps the paper size
+ * @param hm the header margin, in inches
+ * @param fm the footer margin, in inches
+ */
+ public void setPageSetup(PageOrientation p, PaperSize ps,
+ double hm, double fm);
+
+ /**
+ * Forces a page break at the specified row
+ *
+ * @param row the row to break at
+ */
+ public void addRowPageBreak(int row);
+
+ /**
+ * Forces a page break at the specified column
+ *
+ * @param col the column to break at
+ */
+ public void addColumnPageBreak(int col);
+
+ /**
+ * Adds an image to the sheet
+ *
+ * @param image the image to add
+ */
+ public void addImage(WritableImage image);
+
+ /**
+ * Accessor for the number of images on the sheet
+ *
+ * @return the number of images on this sheet
+ */
+ public int getNumberOfImages();
+
+ /**
+ * Accessor for the image
+ *
+ * @param i the 0 based image number
+ * @return the image at the specified position
+ */
+ public WritableImage getImage(int i);
+
+ /**
+ * Removes the specified image from the sheet. The image passed in
+ * must be the same instance as that previously retrieved using the
+ * getImage() method
+ *
+ * @param wi the image to remove
+ */
+ public void removeImage(WritableImage wi);
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/WritableWorkbook.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/WritableWorkbook.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/WritableWorkbook.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,310 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import java.io.IOException;
+
+import jxl.Range;
+import jxl.Sheet;
+import jxl.Workbook;
+import jxl.format.Colour;
+import jxl.format.UnderlineStyle;
+
+/**
+ * A writable workbook
+ */
+public abstract class WritableWorkbook
+{
+ // Globally available stuff
+
+ /**
+ * The default font for Cell formats
+ */
+ public static final WritableFont ARIAL_10_PT =
+ new WritableFont(WritableFont.ARIAL);
+
+ /**
+ * The font used for hyperlinks
+ */
+ public static final WritableFont HYPERLINK_FONT =
+ new WritableFont(WritableFont.ARIAL,
+ WritableFont.DEFAULT_POINT_SIZE,
+ WritableFont.NO_BOLD,
+ false,
+ UnderlineStyle.SINGLE,
+ Colour.BLUE);
+
+ /**
+ * The default style for cells
+ */
+ public static final WritableCellFormat NORMAL_STYLE =
+ new WritableCellFormat(ARIAL_10_PT, NumberFormats.DEFAULT);
+
+ /**
+ * The style used for hyperlinks
+ */
+ public static final WritableCellFormat HYPERLINK_STYLE =
+ new WritableCellFormat(HYPERLINK_FONT);
+
+ /**
+ * A cell format used to hide the cell contents
+ */
+ public static final WritableCellFormat HIDDEN_STYLE =
+ new WritableCellFormat(new DateFormat(";;;"));
+
+ /**
+ * Constructor used by the implemenation class
+ */
+ protected WritableWorkbook()
+ {
+ }
+
+ /**
+ * Gets the sheets within this workbook. Use of this method for
+ * large worksheets can cause performance problems.
+ *
+ * @return an array of the individual sheets
+ */
+ public abstract WritableSheet[] getSheets();
+
+ /**
+ * Gets the sheet names
+ *
+ * @return an array of strings containing the sheet names
+ */
+ public abstract String[] getSheetNames();
+
+ /**
+ * Gets the specified sheet within this workbook
+ *
+ * @param index the zero based index of the reQuired sheet
+ * @return The sheet specified by the index
+ * @exception IndexOutOfBoundsException when index refers to a non-existent
+ * sheet
+ */
+ public abstract WritableSheet getSheet(int index)
+ throws IndexOutOfBoundsException;
+
+ /**
+ * Gets the sheet with the specified name from within this workbook
+ *
+ * @param name the sheet name
+ * @return The sheet with the specified name, or null if it is not found
+ */
+ public abstract WritableSheet getSheet(String name);
+
+ /**
+ * Returns the cell for the specified location eg. "Sheet1!A4".
+ * This is identical to using the CellReferenceHelper with its
+ * associated performance overheads, consequently it should
+ * be use sparingly
+ *
+ * @param loc the cell to retrieve
+ * @return the cell at the specified location
+ */
+ public abstract WritableCell getWritableCell(String loc);
+
+ /**
+ * Returns the number of sheets in this workbook
+ *
+ * @return the number of sheets in this workbook
+ */
+ public abstract int getNumberOfSheets();
+
+ /**
+ * Closes this workbook, and makes any memory allocated available
+ * for garbage collection. Also closes the underlying output stream
+ * if necessary.
+ *
+ * @exception IOException
+ * @exception WriteException
+ */
+ public abstract void close() throws IOException, WriteException;
+
+ /**
+ * Creates, and returns a worksheet at the specified position
+ * with the specified name
+ * If the index specified is less than or equal to zero, the new sheet
+ * is created at the beginning of the workbook. If the index is greater
+ * than the number of sheet, then the sheet is created at the
+ * end of the workbook.
+ *
+ * @param name the sheet name
+ * @param index the index number at which to insert
+ * @return the new sheet
+ */
+ public abstract WritableSheet createSheet(String name, int index);
+
+ /**
+ * Imports a sheet from a different workbook. Does a deep copy on all
+ * elements within that sheet
+ *
+ * @param name the name of the new sheet
+ * @param index the position for the new sheet within this workbook
+ * @param sheet the sheet (from another workbook) to merge into this one
+ * @return the new sheet
+ */
+ public abstract WritableSheet importSheet(String name, int index, Sheet s);
+
+ /**
+ * Copy sheet within the same workbook. The sheet specified is copied to
+ * the new sheet name at the position
+ *
+ * @param s the index of the sheet to copy
+ * @param name the name of the new sheet
+ * @param index the position of the new sheet
+ */
+ public abstract void copySheet(int s, String name, int index);
+
+ /**
+ * Copies the specified sheet and places it at the index
+ * specified by the parameter
+ *
+ * @param s the name of the sheet to copy
+ * @param name the name of the new sheet
+ * @param index the position of the new sheet
+ */
+ public abstract void copySheet(String s, String name, int index);
+
+ /**
+ * Removes the sheet at the specified index from this workbook
+ *
+ * @param index the sheet index to remove
+ */
+ public abstract void removeSheet(int index);
+
+ /**
+ * Moves the specified sheet within this workbook to another index
+ * position.
+ *
+ * @param fromIndex the zero based index of the required sheet
+ * @param toIndex the zero based index of the required sheet
+ * @return the sheet that has been moved
+ */
+ public abstract WritableSheet moveSheet(int fromIndex, int toIndex);
+
+ /**
+ * Writes out the data held in this workbook in Excel format
+ *
+ * @exception IOException
+ */
+ public abstract void write() throws IOException;
+
+ /**
+ * Indicates whether or not this workbook is protected
+ *
+ * @param prot Protected flag
+ */
+ public abstract void setProtected(boolean prot);
+
+ /**
+ * Sets the RGB value for the specified colour for this workbook
+ *
+ * @param c the colour whose RGB value is to be overwritten
+ * @param r the red portion to set (0-255)
+ * @param g the green portion to set (0-255)
+ * @param b the blue portion to set (0-255)
+ */
+ public abstract void setColourRGB(Colour c, int r, int g, int b);
+
+ /**
+ * This method can be used to create a writable clone of some other
+ * workbook
+ *
+ * @param w the workdoock to copy
+ * @deprecated Copying now occurs implicitly as part of the overloaded
+ * factory method Workbook.createWorkbood
+ */
+ public void copy(Workbook w)
+ {
+ // Was an abstract method - leave the method body blank
+ }
+
+ /**
+ * Gets the named cell from this workbook. The name refers to a
+ * range of cells, then the cell on the top left is returned. If
+ * the name cannot be, null is returned
+ *
+ * @param name the name of the cell/range to search for
+ * @return the cell in the top left of the range if found, NULL
+ * otherwise
+ */
+ public abstract WritableCell findCellByName(String name);
+
+ /**
+ * Gets the named range from this workbook. The Range object returns
+ * contains all the cells from the top left to the bottom right
+ * of the range.
+ * If the named range comprises an adjacent range,
+ * the Range[] will contain one object; for non-adjacent
+ * ranges, it is necessary to return an array of length greater than
+ * one.
+ * If the named range contains a single cell, the top left and
+ * bottom right cell will be the same cell
+ *
+ * @param name the name of the cell/range to search for
+ * @return the range of cells
+ */
+ public abstract Range[] findByName(String name);
+
+ /**
+ * Gets the named ranges
+ *
+ * @return the list of named cells within the workbook
+ */
+ public abstract String[] getRangeNames();
+
+ /**
+ * Removes the specified named range from the workbook. Note that
+ * removing a name could cause formulas which use that name to
+ * calculate their results incorrectly
+ *
+ * @param name the name to remove
+ */
+ public abstract void removeRangeName(String name);
+
+ /**
+ * Add new named area to this workbook with the given information.
+ *
+ * @param name name to be created.
+ * @param sheet sheet containing the name
+ * @param firstCol first column this name refers to.
+ * @param firstRow first row this name refers to.
+ * @param lastCol last column this name refers to.
+ * @param lastRow last row this name refers to.
+ */
+ public abstract void addNameArea(String name,
+ WritableSheet sheet,
+ int firstCol,
+ int firstRow,
+ int lastCol,
+ int lastRow);
+
+ /**
+ * Sets a new output file. This allows the same workbook to be
+ * written to various different output files without having to
+ * read in any templates again
+ *
+ * @param fileName the file name
+ * @exception IOException
+ */
+ public abstract void setOutputFile(java.io.File fileName)
+ throws IOException;
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/WriteException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/WriteException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/WriteException.java 17 Aug 2012 14:51:22 -0000 1.1
@@ -0,0 +1,38 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write;
+
+import jxl.JXLException;
+
+/**
+ * Exception thrown when using the API to generate an Excel file
+ */
+public abstract class WriteException extends JXLException
+{
+ /**
+ * Constructs this exception with the specified message
+ *
+ * @param s the message
+ */
+ protected WriteException(String s)
+ {
+ super(s);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ArbitraryRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ArbitraryRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ArbitraryRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,73 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Logger;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Writes out some arbitrary record data. Used during the debug process
+ */
+class ArbitraryRecord extends WritableRecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(ArbitraryRecord.class);
+
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param type the biff code
+ * @param d the data
+ */
+ public ArbitraryRecord(int type, byte[] d)
+ {
+ super(Type.createType(type));
+
+ data = d;
+ logger.warn("ArbitraryRecord of type " + type + " created");
+ }
+
+ /**
+ * Retrieves the data to be written to the binary file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/BOFRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/BOFRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/BOFRecord.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,116 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record to indicate the beginning of a new stream in the Compound
+ * File
+ */
+class BOFRecord extends WritableRecordData
+{
+ /**
+ * The data to write to the file
+ */
+ private byte[] data;
+
+ // Dummy types for constructor overloading
+ private static class WorkbookGlobalsBOF{};
+ private static class SheetBOF{};
+
+ public final static WorkbookGlobalsBOF workbookGlobals
+ = new WorkbookGlobalsBOF();
+ public final static SheetBOF sheet = new SheetBOF();
+
+ /**
+ * Constructor for generating a workbook globals BOF record
+ *
+ * @param dummy - a dummy argument for overloading purposes
+ */
+ public BOFRecord(WorkbookGlobalsBOF dummy)
+ {
+ super(Type.BOF);
+
+ // Create the data as biff 8 format with a substream type of
+ // workbook globals
+ data = new byte[]
+ {(byte) 0x0,
+ (byte) 0x6,
+ (byte) 0x5, // substream type
+ (byte) 0x0, // substream type
+ (byte) 0xf2, // rupBuild
+ (byte) 0x15, // rupBuild
+ (byte) 0xcc, // rupYear
+ (byte) 0x07, // rupYear
+ (byte) 0x0, // bfh
+ (byte) 0x0, // bfh
+ (byte) 0x0, // bfh
+ (byte) 0x0, // bfh
+ (byte) 0x6, // sfo
+ (byte) 0x0, // sfo,
+ (byte) 0x0, // sfo
+ (byte) 0x0 // sfo
+ };
+ }
+
+ /**
+ * Constructor for generating a sheet BOF record
+ *
+ * @param dummy - a dummy argument for overloading purposes
+ */
+ public BOFRecord(SheetBOF dummy)
+ {
+ super(Type.BOF);
+
+ // Create the data as biff 8 format with a substream type of
+ // worksheet
+ data = new byte[]
+ {(byte) 0x0,
+ (byte) 0x6,
+ (byte) 0x10, // substream type
+ (byte) 0x0, // substream type
+ (byte) 0xf2, // rupBuild
+ (byte) 0x15, // rupBuild
+ (byte) 0xcc, // rupYear
+ (byte) 0x07, // rupYear
+ (byte) 0x0, // bfh
+ (byte) 0x0, // bfh
+ (byte) 0x0, // bfh
+ (byte) 0x0, // bfh
+ (byte) 0x6, // sfo
+ (byte) 0x0, // sfo,
+ (byte) 0x0, // sfo
+ (byte) 0x0 // sfo
+ };
+ }
+
+ /**
+ * Gets the data for writing to the output file
+ *
+ * @return the binary data for writing
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/BackupRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/BackupRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/BackupRecord.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,70 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record which indicates whether Excel should save backup versions of the
+ * file
+ */
+class BackupRecord extends WritableRecordData
+{
+ /**
+ * Flag to indicate whether or not Excel should make backups
+ */
+ private boolean backup;
+ /**
+ * The data array
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param bu backup flag
+ */
+ public BackupRecord(boolean bu)
+ {
+ super(Type.BACKUP);
+
+ backup = bu;
+
+ // Hard code in an unprotected workbook
+ data = new byte[2];
+
+ if (backup)
+ {
+ IntegerHelper.getTwoBytes(1, data, 0);
+ }
+ }
+
+ /**
+ * Returns the binary data for writing to the output file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/BlankRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/BlankRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/BlankRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,109 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Logger;
+
+import jxl.Cell;
+import jxl.CellType;
+import jxl.biff.Type;
+import jxl.format.CellFormat;
+
+/**
+ * A blank record, which is used to contain formatting information
+ */
+public abstract class BlankRecord extends CellValue
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(BlankRecord.class);
+
+ /**
+ * Consructor used when creating a label from the user API
+ *
+ * @param c the column
+ * @param cont the contents
+ * @param r the row
+ */
+ protected BlankRecord(int c, int r)
+ {
+ super(Type.BLANK, c, r);
+ }
+
+ /**
+ * Constructor used when creating a label from the API. This is
+ * overloaded to allow formatting information to be passed to the record
+ *
+ * @param c the column
+ * @param r the row
+ * @param st the format applied to the cell
+ */
+ protected BlankRecord(int c, int r, CellFormat st)
+ {
+ super(Type.BLANK, c, r, st);
+ }
+
+ /**
+ * Constructor used when copying a formatted blank cell from a read only
+ * spreadsheet
+ *
+ * @param c the blank cell to copy
+ */
+ protected BlankRecord(Cell c)
+ {
+ super(Type.BLANK, c);
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param c the column
+ * @param r the row
+ * @param b the record to copy
+ */
+ protected BlankRecord(int c, int r, BlankRecord br)
+ {
+ super(Type.BLANK, c, r, br);
+ }
+
+ /**
+ * Returns the content type of this cell
+ *
+ * @return the content type for this cell
+ */
+ public CellType getType()
+ {
+ return CellType.EMPTY;
+ }
+
+ /**
+ * Quick and dirty function to return the contents of this cell as a string.
+ *
+ * @return the contents of this cell as a string
+ */
+ public String getContents()
+ {
+ return "";
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/BookboolRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/BookboolRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/BookboolRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,68 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Writes out the workbook option flag (should it save the external
+ * link options)
+ */
+class BookboolRecord extends WritableRecordData
+{
+ /**
+ * The external link option flag
+ */
+ private boolean externalLink;
+ /**
+ * The binary data to write out
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param extlink the external link options flag
+ */
+ public BookboolRecord(boolean extlink)
+ {
+ super(Type.BOOKBOOL);
+
+ externalLink = extlink;
+ data = new byte[2];
+
+ if (!externalLink)
+ {
+ IntegerHelper.getTwoBytes(1, data, 0);
+ }
+ }
+
+ /**
+ * Gets the binary data to write to the output file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/BooleanRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/BooleanRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/BooleanRecord.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,161 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+
+import jxl.BooleanCell;
+import jxl.CellType;
+import jxl.biff.Type;
+import jxl.format.CellFormat;
+
+
+/**
+ * A boolean cell's last calculated value
+ */
+public abstract class BooleanRecord extends CellValue
+{
+ /**
+ * The boolean value of this cell. If this cell represents an error,
+ * this will be false
+ */
+ private boolean value;
+
+ /**
+ * Constructor invoked by the user API
+ *
+ * @param c the column
+ * @param r the row
+ * @param val the value
+ */
+ protected BooleanRecord(int c, int r, boolean val)
+ {
+ super(Type.BOOLERR, c, r);
+ value = val;
+ }
+
+ /**
+ * Overloaded constructor invoked from the API, which takes a cell
+ * format
+ *
+ * @param c the column
+ * @param r the row
+ * @param val the value
+ * @param st the cell format
+ */
+ protected BooleanRecord(int c, int r, boolean val, CellFormat st)
+ {
+ super(Type.BOOLERR, c, r, st);
+ value = val;
+ }
+
+ /**
+ * Constructor used when copying a workbook
+ *
+ * @param nc the number to copy
+ */
+ protected BooleanRecord(BooleanCell nc)
+ {
+ super(Type.BOOLERR, nc);
+ value = nc.getValue();
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param c the column
+ * @param r the row
+ * @param br the record to copy
+ */
+ protected BooleanRecord(int c, int r, BooleanRecord br)
+ {
+ super(Type.BOOLERR, c, r, br);
+ value = br.value;
+ }
+
+ /**
+ * Interface method which Gets the boolean value stored in this cell. If
+ * this cell contains an error, then returns FALSE. Always query this cell
+ * type using the accessor method isError() prior to calling this method
+ *
+ * @return TRUE if this cell contains TRUE, FALSE if it contains FALSE or
+ * an error code
+ */
+ public boolean getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns the numerical value as a string
+ *
+ * @return The numerical value of the formula as a string
+ */
+ public String getContents()
+ {
+ // return Boolean.toString(value) - only available in 1.4 or later
+ return (new Boolean(value)).toString();
+ }
+
+ /**
+ * Returns the cell type
+ *
+ * @return The cell type
+ */
+ public CellType getType()
+ {
+ return CellType.BOOLEAN;
+ }
+
+ /**
+ * Sets the value
+ *
+ * @param val the boolean value
+ */
+ protected void setValue(boolean val)
+ {
+ value = val;
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] celldata = super.getData();
+ byte[] data = new byte[celldata.length + 2];
+ System.arraycopy(celldata, 0, data, 0, celldata.length);
+
+ if (value)
+ {
+ data[celldata.length] = 1;
+ }
+
+ return data;
+ }
+
+}
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/BottomMarginRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/BottomMarginRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/BottomMarginRecord.java 17 Aug 2012 14:51:08 -0000 1.1
@@ -0,0 +1,33 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+
+/**
+ * The settings for the left margin
+ */
+class BottomMarginRecord extends MarginRecord
+{
+ BottomMarginRecord(double v)
+ {
+ super(Type.BOTTOMMARGIN, v);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/BoundsheetRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/BoundsheetRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/BoundsheetRecord.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,119 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record which stores the sheet name, the sheet type and the stream
+ * position
+ */
+class BoundsheetRecord extends WritableRecordData
+{
+ /**
+ * Hidden flag
+ */
+ private boolean hidden;
+
+ /**
+ * Chart only flag
+ */
+ private boolean chartOnly;
+
+ /**
+ * The name of the sheet
+ */
+ private String name;
+
+ /**
+ * The data to write to the output file
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param n the sheet name
+ */
+ public BoundsheetRecord(String n)
+ {
+ super(Type.BOUNDSHEET);
+ name = n;
+ hidden = false;
+ chartOnly = false;
+ }
+
+ /**
+ * Sets the hidden flag
+ */
+ void setHidden()
+ {
+ hidden = true;
+ }
+
+ /**
+ * Sets the chart only flag
+ */
+ void setChartOnly()
+ {
+ chartOnly = true;
+ }
+
+ /**
+ * Gets the data to write out to the binary file
+ *
+ * @return the data to write out
+ */
+ public byte[] getData()
+ {
+ data = new byte[name.length() * 2 + 8];
+
+ if (chartOnly)
+ {
+ data[5] = 0x02;
+ }
+ else
+ {
+ data[5] = 0; // set stream type to worksheet
+ }
+
+ if (hidden)
+ {
+ data[4] = 0x1;
+ data[5] = 0x0;
+ }
+
+ data[6] = (byte) name.length();
+ data[7] = 1;
+ StringHelper.getUnicodeBytes(name, data, 8);
+
+ return data;
+ }
+}
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ButtonPropertySetRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ButtonPropertySetRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ButtonPropertySetRecord.java 17 Aug 2012 14:51:08 -0000 1.1
@@ -0,0 +1,72 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Any arbitrary excel record. Used during development only
+ */
+class ButtonPropertySetRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ */
+ public ButtonPropertySetRecord(jxl.read.biff.ButtonPropertySetRecord bps)
+ {
+ super(Type.BUTTONPROPERTYSET);
+
+ data = bps.getData();
+ }
+
+ /**
+ * Constructor
+ */
+ public ButtonPropertySetRecord(ButtonPropertySetRecord bps)
+ {
+ super(Type.BUTTONPROPERTYSET);
+
+ data = bps.getData();
+ }
+
+ /**
+ * Retrieves the data to be written to the binary file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/CalcCountRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/CalcCountRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/CalcCountRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,68 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record which stores the maximum iterations option from the Options
+ * dialog box
+ */
+class CalcCountRecord extends WritableRecordData
+{
+ /**
+ * The iteration count
+ */
+ private int calcCount;
+ /**
+ * The binary data to write to the output file
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param cnt the count indicator
+ */
+ public CalcCountRecord(int cnt)
+ {
+ super(Type.CALCCOUNT);
+ calcCount = cnt;
+ }
+
+
+ /**
+ * Gets the data to write out to the file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[2];
+
+ IntegerHelper.getTwoBytes(calcCount, data, 0);
+
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/CalcModeRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/CalcModeRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/CalcModeRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,95 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * The calculation mode for the workbook, as set from the Options
+ * dialog box
+ */
+class CalcModeRecord extends WritableRecordData
+{
+ /**
+ * The calculation mode (manual, automatic)
+ */
+ private CalcMode calculationMode;
+
+ private static class CalcMode
+ {
+ /**
+ * The indicator as written to the output file
+ */
+ int value;
+
+ /**
+ * Constructor
+ *
+ * @param m
+ */
+ public CalcMode(int m)
+ {
+ value = m;
+ }
+ }
+
+ /**
+ * Manual calculation
+ */
+ static CalcMode manual = new CalcMode(0);
+ /**
+ * Automatic calculation
+ */
+ static CalcMode automatic = new CalcMode(1);
+ /**
+ * Automatic calculation, except tables
+ */
+ static CalcMode automaticNoTables = new CalcMode(-1);
+
+ /**
+ * Constructor
+ *
+ * @param cm the calculation mode
+ */
+ public CalcModeRecord(CalcMode cm)
+ {
+ super(Type.CALCMODE);
+ calculationMode = cm;
+ }
+
+
+ /**
+ * Gets the binary to data to write to the output file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[2];
+
+ IntegerHelper.getTwoBytes(calculationMode.value, data, 0);
+
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/CellValue.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/CellValue.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/CellValue.java 17 Aug 2012 14:51:08 -0000 1.1
@@ -0,0 +1,640 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.Cell;
+import jxl.CellFeatures;
+import jxl.Sheet;
+import jxl.biff.DataValidation;
+import jxl.biff.DataValiditySettingsRecord;
+import jxl.biff.FormattingRecords;
+import jxl.biff.IntegerHelper;
+import jxl.biff.NumFormatRecordsException;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+import jxl.biff.XFRecord;
+import jxl.biff.drawing.ComboBox;
+import jxl.biff.drawing.Comment;
+import jxl.format.CellFormat;
+import jxl.write.WritableCell;
+import jxl.write.WritableCellFeatures;
+import jxl.write.WritableWorkbook;
+
+/**
+ * Abstract class which stores the common data used for cells, such
+ * as row, column and formatting information.
+ * Any record which directly represents the contents of a cell, such
+ * as labels and numbers, are derived from this class
+ * data store
+ */
+public abstract class CellValue extends WritableRecordData
+ implements WritableCell
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(CellValue.class);
+
+ /**
+ * The row in the worksheet at which this cell is located
+ */
+ private int row;
+
+ /**
+ * The column in the worksheet at which this cell is located
+ */
+ private int column;
+
+ /**
+ * The format applied to this cell
+ */
+ private XFRecord format;
+
+ /**
+ * A handle to the formatting records, used in case we want
+ * to change the format of the cell once it has been added
+ * to the spreadsheet
+ */
+ private FormattingRecords formattingRecords;
+
+ /**
+ * A flag to indicate that this record is already referenced within
+ * a worksheet
+ */
+ private boolean referenced;
+
+ /**
+ * A handle to the sheet
+ */
+ private WritableSheetImpl sheet;
+
+ /**
+ * The cell features
+ */
+ private WritableCellFeatures features;
+
+ /**
+ * Internal copied flag, to prevent cell features being added multiple
+ * times to the drawing array
+ */
+ private boolean copied;
+
+ /**
+ * Constructor used when building writable cells from the Java API
+ *
+ * @param c the column
+ * @param t the type indicator
+ * @param r the row
+ */
+ protected CellValue(Type t, int c, int r)
+ {
+ this(t, c, r, WritableWorkbook.NORMAL_STYLE);
+ copied = false;
+ }
+
+ /**
+ * Constructor used when creating a writable cell from a read-only cell
+ * (when copying a workbook)
+ *
+ * @param c the cell to clone
+ * @param t the type of this cell
+ */
+ protected CellValue(Type t, Cell c)
+ {
+ this(t, c.getColumn(), c.getRow());
+ copied = true;
+
+ format = (XFRecord) c.getCellFormat();
+
+ if (c.getCellFeatures() != null)
+ {
+ features = new WritableCellFeatures(c.getCellFeatures());
+ features.setWritableCell(this);
+ }
+ }
+
+ /**
+ * Overloaded constructor used when building writable cells from the
+ * Java API which also takes a format
+ *
+ * @param c the column
+ * @param t the cell type
+ * @param r the row
+ * @param st the format to apply to this cell
+ */
+ protected CellValue(Type t, int c, int r, CellFormat st)
+ {
+ super(t);
+ row = r;
+ column = c;
+ format = (XFRecord) st;
+ referenced = false;
+ copied = false;
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param c the column
+ * @param t the cell type
+ * @param r the row
+ * @param cv the value to copy
+ */
+ protected CellValue(Type t, int c, int r, CellValue cv)
+ {
+ super(t);
+ row = r;
+ column = c;
+ format = cv.format;
+ referenced = false;
+ copied = false; // used during a deep copy, so the cell features need
+ // to be added again
+
+ if (cv.features != null)
+ {
+ features = new WritableCellFeatures(cv.features);
+ features.setWritableCell(this);
+ }
+ }
+
+ /**
+ * An API function which sets the format to apply to this cell
+ *
+ * @param cf the format to apply to this cell
+ */
+ public void setCellFormat(CellFormat cf)
+ {
+ format = (XFRecord) cf;
+
+ // If the referenced flag has not been set, this cell has not
+ // been added to the spreadsheet, so we don't need to perform
+ // any further logic
+ if (!referenced)
+ {
+ return;
+ }
+
+ // The cell has already been added to the spreadsheet, so the
+ // formattingRecords reference must be initialized
+ Assert.verify(formattingRecords != null);
+
+ addCellFormat();
+ }
+
+ /**
+ * Returns the row number of this cell
+ *
+ * @return the row number of this cell
+ */
+ public int getRow()
+ {
+ return row;
+ }
+
+ /**
+ * Returns the column number of this cell
+ *
+ * @return the column number of this cell
+ */
+ public int getColumn()
+ {
+ return column;
+ }
+
+ /**
+ * Indicates whether or not this cell is hidden, by virtue of either
+ * the entire row or column being collapsed
+ *
+ * @return TRUE if this cell is hidden, FALSE otherwise
+ */
+ public boolean isHidden()
+ {
+ ColumnInfoRecord cir = sheet.getColumnInfo(column);
+
+ if (cir != null && cir.getWidth() == 0)
+ {
+ return true;
+ }
+
+ RowRecord rr = sheet.getRowInfo(row);
+
+ if (rr != null && (rr.getRowHeight() == 0 || rr.isCollapsed()))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Gets the data to write to the output file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] mydata = new byte[6];
+ IntegerHelper.getTwoBytes(row, mydata, 0);
+ IntegerHelper.getTwoBytes(column, mydata, 2);
+ IntegerHelper.getTwoBytes(format.getXFIndex(), mydata, 4);
+ return mydata;
+ }
+
+ /**
+ * Called when the cell is added to the worksheet in order to indicate
+ * that this object is already added to the worksheet
+ * This method also verifies that the associated formats and formats
+ * have been initialized correctly
+ *
+ * @param fr the formatting records
+ * @param ss the shared strings used within the workbook
+ * @param s the sheet this is being added to
+ */
+ void setCellDetails(FormattingRecords fr, SharedStrings ss,
+ WritableSheetImpl s)
+ {
+ referenced = true;
+ sheet = s;
+ formattingRecords = fr;
+
+ addCellFormat();
+ addCellFeatures();
+ }
+
+ /**
+ * Internal method to see if this cell is referenced within the workbook.
+ * Once this has been placed in the workbook, it becomes immutable
+ *
+ * @return TRUE if this cell has been added to a sheet, FALSE otherwise
+ */
+ final boolean isReferenced()
+ {
+ return referenced;
+ }
+
+ /**
+ * Gets the internal index of the formatting record
+ *
+ * @return the index of the format record
+ */
+ final int getXFIndex()
+ {
+ return format.getXFIndex();
+ }
+
+ /**
+ * API method which gets the format applied to this cell
+ *
+ * @return the format for this cell
+ */
+ public CellFormat getCellFormat()
+ {
+ return format;
+ }
+
+ /**
+ * Increments the row of this cell by one. Invoked by the sheet when
+ * inserting rows
+ */
+ void incrementRow()
+ {
+ row++;
+
+ if (features != null)
+ {
+ Comment c = features.getCommentDrawing();
+ if (c != null)
+ {
+ c.setX(column);
+ c.setY(row);
+ }
+ }
+ }
+
+ /**
+ * Decrements the row of this cell by one. Invoked by the sheet when
+ * removing rows
+ */
+ void decrementRow()
+ {
+ row--;
+
+ if (features != null)
+ {
+ Comment c = features.getCommentDrawing();
+ if ( c!= null)
+ {
+ c.setX(column);
+ c.setY(row);
+ }
+
+ if (features.hasDropDown())
+ {
+ logger.warn("need to change value for drop down drawing");
+ }
+ }
+ }
+
+ /**
+ * Increments the column of this cell by one. Invoked by the sheet when
+ * inserting columns
+ */
+ void incrementColumn()
+ {
+ column++;
+
+ if (features != null)
+ {
+ Comment c = features.getCommentDrawing();
+ if (c != null)
+ {
+ c.setX(column);
+ c.setY(row);
+ }
+ }
+
+ }
+
+ /**
+ * Decrements the column of this cell by one. Invoked by the sheet when
+ * removing columns
+ */
+ void decrementColumn()
+ {
+ column--;
+
+ if (features != null)
+ {
+ Comment c = features.getCommentDrawing();
+ if (c != null)
+ {
+ c.setX(column);
+ c.setY(row);
+ }
+ }
+
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Notifies all
+ * RCIR cells of this change. The default implementation here does nothing
+ *
+ * @param s the sheet on which the column was inserted
+ * @param sheetIndex the sheet index on which the column was inserted
+ * @param col the column number which was inserted
+ */
+ void columnInserted(Sheet s, int sheetIndex, int col)
+ {
+ }
+
+ /**
+ * Called when a column is removed on the specified sheet. Notifies all
+ * RCIR cells of this change. The default implementation here does nothing
+ *
+ * @param s the sheet on which the column was inserted
+ * @param sheetIndex the sheet index on which the column was inserted
+ * @param col the column number which was inserted
+ */
+ void columnRemoved(Sheet s, int sheetIndex, int col)
+ {
+ }
+
+ /**
+ * Called when a row is inserted on the specified sheet. Notifies all
+ * RCIR cells of this change. The default implementation here does nothing
+ *
+ * @param s the sheet on which the column was inserted
+ * @param sheetIndex the sheet index on which the column was inserted
+ * @param row the column number which was inserted
+ */
+ void rowInserted(Sheet s, int sheetIndex, int row)
+ {
+ }
+
+ /**
+ * Called when a row is inserted on the specified sheet. Notifies all
+ * RCIR cells of this change. The default implementation here does nothing
+ *
+ * @param s the sheet on which the row was removed
+ * @param sheetIndex the sheet index on which the column was removed
+ * @param row the column number which was removed
+ */
+ void rowRemoved(Sheet s, int sheetIndex, int row)
+ {
+ }
+
+ /**
+ * Accessor for the sheet containing this cell
+ *
+ * @return the sheet containing this cell
+ */
+ protected WritableSheetImpl getSheet()
+ {
+ return sheet;
+ }
+
+ /**
+ * Adds the format information to the shared records. Performs the necessary
+ * checks (and clones) to ensure that the formats are not shared.
+ * Called from setCellDetails and setCellFormat
+ */
+ private void addCellFormat()
+ {
+ // Check to see if the format is one of the shared Workbook defaults. If
+ // so, then get hold of the Workbook's specific instance
+ Styles styles = sheet.getWorkbook().getStyles();
+ format = styles.getFormat(format);
+
+ try
+ {
+ if (!format.isInitialized())
+ {
+ formattingRecords.addStyle(format);
+ }
+ }
+ catch (NumFormatRecordsException e)
+ {
+ logger.warn("Maximum number of format records exceeded. Using " +
+ "default format.");
+ format = styles.getNormalStyle();
+ }
+ }
+
+ /**
+ * Accessor for the cell features
+ *
+ * @return the cell features or NULL if this cell doesn't have any
+ */
+ public CellFeatures getCellFeatures()
+ {
+ return features;
+ }
+
+ /**
+ * Accessor for the cell features
+ *
+ * @return the cell features or NULL if this cell doesn't have any
+ */
+ public WritableCellFeatures getWritableCellFeatures()
+ {
+ return features;
+ }
+
+ /**
+ * Sets the cell features
+ *
+ * @param cf the cell features
+ */
+ public void setCellFeatures(WritableCellFeatures cf)
+ {
+ if (features != null)
+ {
+ logger.warn("current cell features not null - overwriting");
+ }
+
+ features = cf;
+ cf.setWritableCell(this);
+
+ // If the cell is already on the worksheet, then add the cell features
+ // to the workbook
+ if (referenced)
+ {
+ addCellFeatures();
+ }
+ }
+
+ /**
+ * Handles any addition cell features, such as comments or data
+ * validation. Called internally from this class when a cell is
+ * added to the workbook, and also externally from BaseCellFeatures
+ * following a call to setComment
+ */
+ public final void addCellFeatures()
+ {
+ if (features == null)
+ {
+ return;
+ }
+
+ if (copied == true)
+ {
+ copied = false;
+
+ return;
+ }
+
+ if (features.getComment() != null)
+ {
+ Comment comment = new Comment(features.getComment(),
+ column, row);
+ comment.setWidth(features.getCommentWidth());
+ comment.setHeight(features.getCommentHeight());
+ sheet.addDrawing(comment);
+ sheet.getWorkbook().addDrawing(comment);
+ features.setCommentDrawing(comment);
+ }
+
+ if (features.hasDataValidation())
+ {
+ try
+ {
+ features.getDVParser().setCell(column,
+ row,
+ sheet.getWorkbook(),
+ sheet.getWorkbook(),
+ sheet.getWorkbookSettings());
+ }
+ catch (jxl.biff.formula.FormulaException e)
+ {
+ e.printStackTrace();
+ Assert.verify(false);
+ }
+ sheet.addValidationCell(this);
+ if (!features.hasDropDown())
+ {
+ return;
+ }
+
+ // Get the combo box drawing object for list validations
+ if (sheet.getComboBox() == null)
+ {
+ ComboBox cb = new ComboBox();
+ sheet.addDrawing(cb);
+ sheet.getWorkbook().addDrawing(cb);
+ sheet.setComboBox(cb);
+ }
+
+ features.setComboBox(sheet.getComboBox());
+ }
+ }
+
+ /**
+ * Removes the cell features from the Workbook/Worksheet. Called when
+ * a cell is being removed/replaced from a worksheet
+ */
+ public final void removeCellFeatures()
+ {
+ if (features == null)
+ {
+ return;
+ }
+
+ // Remove the comment
+ features.removeComment();
+
+ // Remove the data validation
+ features.removeDataValidation();
+ }
+
+
+ /**
+ * Called by the cell features to remove a comment
+ *
+ * @param c the comment to remove
+ */
+ public final void removeComment(Comment c)
+ {
+ sheet.removeDrawing(c);
+ }
+
+ /**
+ * Called by the cell features to remove the data validation
+ */
+ public final void removeDataValidation()
+ {
+ sheet.removeDataValidation(this);
+ }
+
+ /**
+ * Called when doing a copy of a writable object to indicate the source
+ * was writable than a read only copy and certain things (most notably
+ * the comments will need to be re-evaluated)
+ *
+ * @param boolean the copied flag
+ */
+ final void setCopied(boolean c)
+ {
+ copied = c;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/CellXFRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/CellXFRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/CellXFRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,238 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.DisplayFormat;
+import jxl.biff.FontRecord;
+import jxl.biff.XFRecord;
+import jxl.format.Alignment;
+import jxl.format.Border;
+import jxl.format.BorderLineStyle;
+import jxl.format.CellFormat;
+import jxl.format.Colour;
+import jxl.format.Orientation;
+import jxl.format.Pattern;
+import jxl.format.VerticalAlignment;
+import jxl.write.WriteException;
+
+/**
+ * A cell XF Record
+ */
+public class CellXFRecord extends XFRecord
+{
+ /**
+ * Constructor
+ *
+ * @param fnt the font
+ * @param form the format
+ */
+ protected CellXFRecord(FontRecord fnt, DisplayFormat form )
+ {
+ super(fnt, form);
+ setXFDetails(XFRecord.cell,0);
+ }
+
+ /**
+ * Copy constructor. Invoked when copying formats to handle cell merging
+ *
+ * @param fmt the format to copy
+ */
+ CellXFRecord(XFRecord fmt )
+ {
+ super(fmt);
+ setXFDetails(XFRecord.cell,0);
+ }
+
+ /**
+ * A public copy constructor which can be used for copy formats between
+ * different sheets
+ */
+ protected CellXFRecord(CellFormat format)
+ {
+ super(format);
+ }
+
+ /**
+ * Sets the alignment for the cell
+ *
+ * @exception WriteException
+ * @param a the alignment
+ */
+ public void setAlignment(Alignment a) throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+ super.setXFAlignment(a);
+ }
+
+ /**
+ * Sets the background for the cell
+ *
+ * @exception WriteException
+ * @param c the background colour
+ * @param p the background patter
+ */
+ public void setBackground(Colour c, Pattern p) throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+ super.setXFBackground(c, p);
+ super.setXFCellOptions(0x4000);
+ }
+
+ /**
+ * Sets whether or not this XF record locks the cell
+ *
+ * @param l the locked flag
+ * @exception WriteException
+ */
+ public void setLocked(boolean l) throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+ super.setXFLocked(l);
+ super.setXFCellOptions(0x8000);
+ }
+
+ /**
+ * Sets the indentation of the cell text
+ *
+ * @param i the indentation
+ */
+ public void setIndentation(int i) throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+ super.setXFIndentation(i);
+ }
+
+ /**
+ * Sets the shrink to fit flag
+ *
+ * @param b the shrink to fit flag
+ */
+ public void setShrinkToFit(boolean s) throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+ super.setXFShrinkToFit(s);
+ }
+
+ /**
+ * Sets the vertical alignment for cells with this style
+ *
+ * @exception WriteException
+ * @param va the vertical alignment
+ */
+ public void setVerticalAlignment(VerticalAlignment va)
+ throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+
+ super.setXFVerticalAlignment(va);
+ }
+
+ /**
+ * Sets the text orientation for cells with this style
+ *
+ * @exception WriteException
+ * @param o the orientation
+ */
+ public void setOrientation(Orientation o)
+ throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+
+ super.setXFOrientation(o);
+ }
+
+ /**
+ * Sets the text wrapping for cells with this style. If the parameter is
+ * set to TRUE, then data in this cell will be wrapped around, and the
+ * cell's height adjusted accordingly
+ *
+ * @exception WriteException
+ * @param w the wrap
+ */
+ public void setWrap(boolean w) throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+
+ super.setXFWrap(w);
+ }
+
+ /**
+ * Sets the border style for cells with this format
+ *
+ * @exception WriteException
+ * @param b the border
+ * @param ls the line for the specified border
+ */
+ public void setBorder(Border b, BorderLineStyle ls, Colour c)
+ throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+
+ if (b == Border.ALL)
+ {
+ // Apply to all
+ super.setXFBorder(Border.LEFT, ls, c);
+ super.setXFBorder(Border.RIGHT, ls, c);
+ super.setXFBorder(Border.TOP, ls, c);
+ super.setXFBorder(Border.BOTTOM, ls, c);
+ return;
+ }
+
+ if (b == Border.NONE)
+ {
+ // Apply to all
+ super.setXFBorder(Border.LEFT, BorderLineStyle.NONE, Colour.BLACK);
+ super.setXFBorder(Border.RIGHT, BorderLineStyle.NONE, Colour.BLACK);
+ super.setXFBorder(Border.TOP, BorderLineStyle.NONE, Colour.BLACK);
+ super.setXFBorder(Border.BOTTOM, BorderLineStyle.NONE, Colour.BLACK);
+ return;
+ }
+
+ super.setXFBorder(b, ls, c);
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/CodepageRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/CodepageRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/CodepageRecord.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,56 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores the default character set in operation when the workbook was
+ * saved
+ */
+class CodepageRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ */
+ public CodepageRecord()
+ {
+ super(Type.CODEPAGE);
+
+ // Hard code inthe ANSI character set for Microsoft
+ data = new byte[] {(byte) 0xe4, (byte) 0x4};
+ }
+
+ /**
+ * Retrieves the data for output to binary file
+ *
+ * @return the data to be written
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ColumnInfoRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ColumnInfoRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ColumnInfoRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,422 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+
+import jxl.biff.FormattingRecords;
+import jxl.biff.IndexMapping;
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+import jxl.biff.XFRecord;
+
+/**
+ * Describes the column formatting for a particular column
+ */
+class ColumnInfoRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+ /**
+ * The column number which this format applies to
+ */
+ private int column;
+ /**
+ * The style for the column
+ */
+ private XFRecord style;
+ /**
+ * The index for the style of this column
+ */
+ private int xfIndex;
+
+ /**
+ * The width of the column in 1/256 of a character
+ */
+ private int width;
+
+ /**
+ * Flag to indicate the hidden status of this column
+ */
+ private boolean hidden;
+
+ /**
+ * The column's outline level
+ */
+ private int outlineLevel;
+
+ /**
+ * Column collapsed flag
+ */
+ private boolean collapsed;
+
+
+ /**
+ * Constructor used when setting column information from the user
+ * API
+ *
+ * @param w the width of the column in characters
+ * @param col the column to format
+ * @param xf the style for the column
+ */
+ public ColumnInfoRecord(int col, int w, XFRecord xf)
+ {
+ super(Type.COLINFO);
+
+ column = col;
+ width = w;
+ style = xf;
+ xfIndex = style.getXFIndex();
+ hidden = false;
+ }
+
+ /**
+ * Copy constructor used when copying from sheet to sheet within the
+ * same workbook
+ *
+ * @param the record to copy
+ */
+ public ColumnInfoRecord(ColumnInfoRecord cir)
+ {
+ super(Type.COLINFO);
+
+ column = cir.column;
+ width = cir.width;
+ style = cir.style;
+ xfIndex = cir.xfIndex;
+ hidden = cir.hidden;
+ outlineLevel = cir.outlineLevel;
+ collapsed = cir.collapsed;
+
+ }
+
+
+ /**
+ * Constructor used when copying an existing spreadsheet
+ *
+ * @param col the column number
+ * @param cir the column info record read in
+ * @param fr the format records
+ */
+ public ColumnInfoRecord(jxl.read.biff.ColumnInfoRecord cir,
+ int col,
+ FormattingRecords fr)
+ {
+ super(Type.COLINFO);
+
+ column = col;
+ width = cir.getWidth();
+ xfIndex = cir.getXFIndex();
+ style = fr.getXFRecord(xfIndex);
+ outlineLevel = cir.getOutlineLevel();
+ collapsed = cir.getCollapsed();
+ }
+
+ /**
+ * Constructor used when importing a sheet from another
+ * spreadsheet
+ *
+ * @param col the column number
+ * @param cir the column info record read in
+ */
+ public ColumnInfoRecord(jxl.read.biff.ColumnInfoRecord cir,
+ int col)
+ {
+ super(Type.COLINFO);
+
+ column = col;
+ width = cir.getWidth();
+ xfIndex = cir.getXFIndex();
+ outlineLevel = cir.getOutlineLevel();
+ collapsed = cir.getCollapsed();
+ }
+
+ /**
+ * Gets the column this format applies to
+ *
+ * @return the column which is formatted
+ */
+ public int getColumn()
+ {
+ return column;
+ }
+
+ /**
+ * Increments the column. Called when inserting a new column into
+ * the sheet
+ */
+ public void incrementColumn()
+ {
+ column++;
+ }
+
+ /**
+ * Decrements the column. Called when removing a column from
+ * the sheet
+ */
+ public void decrementColumn()
+ {
+ column--;
+ }
+
+ /**
+ * Accessor for the width
+ *
+ * @return the width
+ */
+ int getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Sets the width. Used when autosizing columns
+ *
+ * @param w the new width
+ */
+ void setWidth(int w)
+ {
+ width = w;
+ }
+
+ /**
+ * Gets the binary data to be written to the output file
+ *
+ * @return the data to write to file
+ */
+ public byte[] getData()
+ {
+ data = new byte[0x0c];
+
+ IntegerHelper.getTwoBytes(column, data, 0);
+ IntegerHelper.getTwoBytes(column, data, 2);
+ IntegerHelper.getTwoBytes(width, data, 4);
+ IntegerHelper.getTwoBytes(xfIndex, data, 6);
+
+ // int options = 0x2;
+ int options = 0x6 | (outlineLevel << 8);
+ if (hidden)
+ {
+ options |= 0x1;
+ }
+
+ outlineLevel = ((options & 0x700) / 0x100);
+
+ if (collapsed)
+ {
+ options |= 0x1000;
+ }
+
+ IntegerHelper.getTwoBytes(options, data, 8);
+ // IntegerHelper.getTwoBytes(2, data, 10);
+
+ return data;
+ }
+
+ /**
+ * Gets the cell format associated with this column info record
+ *
+ * @return the cell format for this column
+ */
+ public XFRecord getCellFormat()
+ {
+ return style;
+ }
+
+ /**
+ * Sets the cell format. Used when importing spreadsheets
+ *
+ * @param xfr the xf record
+ */
+ public void setCellFormat(XFRecord xfr)
+ {
+ style = xfr;
+ }
+
+ /**
+ * Accessor for the xf index, used when importing from another spreadsheet
+ *
+ * @return the xf index
+ */
+ public int getXfIndex()
+ {
+ return xfIndex;
+ }
+
+ /**
+ * Rationalizes the sheets xf index mapping
+ * @param xfmapping the index mapping
+ */
+ void rationalize(IndexMapping xfmapping)
+ {
+ xfIndex = xfmapping.getNewIndex(xfIndex);
+ }
+
+ /**
+ * Sets this column to be hidden (or otherwise)
+ *
+ * @param h TRUE if the column is to be hidden, FALSE otherwise
+ */
+ void setHidden(boolean h)
+ {
+ hidden = h;
+ }
+
+ /**
+ * Accessor for the hidden flag
+ *
+ * @return TRUE if this column is hidden, FALSE otherwise
+ */
+ boolean getHidden()
+ {
+ return hidden;
+ }
+
+ /**
+ * Standard equals method
+ *
+ * @return TRUE if these objects are equal, FALSE otherwise
+ */
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+
+ if (!(o instanceof ColumnInfoRecord))
+ {
+ return false;
+ }
+
+ ColumnInfoRecord cir = (ColumnInfoRecord) o;
+
+ if (column != cir.column ||
+ xfIndex != cir.xfIndex ||
+ width != cir.width ||
+ hidden != cir.hidden ||
+ outlineLevel != cir.outlineLevel ||
+ collapsed != cir.collapsed)
+ {
+ return false;
+ }
+
+ if ((style == null && cir.style != null) ||
+ (style != null && cir.style == null))
+ {
+ return false;
+ }
+
+ return style.equals(cir.style);
+ }
+
+ /**
+ * Standard hashCode method
+ *
+ * @return the hashCode
+ */
+ public int hashCode()
+ {
+ int hashValue = 137;
+ int oddPrimeNumber = 79;
+
+ hashValue = hashValue * oddPrimeNumber + column;
+ hashValue = hashValue * oddPrimeNumber + xfIndex;
+ hashValue = hashValue * oddPrimeNumber + width;
+ hashValue = hashValue * oddPrimeNumber + (hidden ? 1:0);
+
+ if (style != null)
+ {
+ hashValue ^= style.hashCode();
+ }
+
+ return hashValue;
+ }
+
+ /**
+ * Accessor for the column's outline level
+ *
+ * @return the column's outline level
+ */
+ public int getOutlineLevel()
+ {
+ return outlineLevel;
+ }
+
+ /**
+ * Accessor for whether the column is collapsed
+ *
+ * @return the column's collapsed state
+ */
+ public boolean getCollapsed()
+ {
+ return collapsed;
+ }
+
+ /**
+ * Increments the column's outline level. This is how groups are made
+ * as well
+ */
+ public void incrementOutlineLevel()
+ {
+ outlineLevel++;
+ }
+
+ /**
+ * Decrements the column's outline level. This removes it from a
+ * grouping level. If
+ * all outline levels are gone the uncollapse the column.
+ */
+ public void decrementOutlineLevel()
+ {
+ if (0 < outlineLevel)
+ {
+ outlineLevel--;
+ }
+
+ if (0==outlineLevel)
+ {
+ collapsed = false;
+ }
+ }
+
+ /**
+ * Sets the column's outline level
+ *
+ * @param level the column's outline level
+ */
+ public void setOutlineLevel(int level)
+ {
+ outlineLevel = level;
+ }
+
+ /**
+ * Sets the column's collapsed state
+ *
+ * @param value the column's collapsed state
+ */
+ public void setCollapsed(boolean value)
+ {
+ collapsed = value;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ColumnsExceededException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ColumnsExceededException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ColumnsExceededException.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,35 @@
+/*********************************************************************
+*
+* Copyright (C) 2005 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+/**
+ * Exception thrown when attempting to add a column to a spreadsheet which
+ * has already reached the maximum amount
+ */
+public class ColumnsExceededException extends JxlWriteException
+{
+ /**
+ * Constructor
+ */
+ public ColumnsExceededException()
+ {
+ super(maxColumnsExceeded);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/CompoundFile.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/CompoundFile.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/CompoundFile.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,1160 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.biff.BaseCompoundFile;
+import jxl.biff.IntegerHelper;
+import jxl.read.biff.BiffException;
+
+/**
+ * Writes out a compound file
+ *
+ * Header block is -1
+ * Excel data is e..n (where e is the head extension blocks, normally 0 and
+ * n is at least 8)
+ * Summary information (8 blocks)
+ * Document summary (8 blocks)
+ * BBD is block p..q (where p=e+n+16 and q-p+1 is the number of BBD blocks)
+ * Property storage block is q+b...r (normally 1 block) (where b is the number
+ * of BBD blocks)
+ */
+final class CompoundFile extends BaseCompoundFile
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(CompoundFile.class);
+
+ /**
+ * The stream to which the jumbled up data is written to
+ */
+ private OutputStream out;
+ /**
+ * The organized biff records which form the actual excel data
+ */
+ private ExcelDataOutput excelData;
+
+ /**
+ * The size of the array
+ */
+ private int size;
+
+ /**
+ * The size the excel data should be in order to comply with the
+ * general compound file format
+ */
+ private int requiredSize;
+
+ /**
+ * The number of blocks it takes to store the big block depot
+ */
+ private int numBigBlockDepotBlocks;
+
+ /**
+ * The number of blocks it takes to store the small block depot chain
+ */
+ private int numSmallBlockDepotChainBlocks;
+
+ /**
+ * The number of blocks it takes to store the small block depot
+ */
+ private int numSmallBlockDepotBlocks;
+
+ /**
+ * The number of extension blocks required for the header to describe
+ * the BBD
+ */
+ private int numExtensionBlocks;
+
+ /**
+ * The extension block for the header
+ */
+ private int extensionBlock;
+
+ /**
+ * The number of blocks it takes to store the excel data
+ */
+ private int excelDataBlocks;
+
+ /**
+ * The start block of the root entry
+ */
+ private int rootStartBlock;
+
+ /**
+ * The start block of the excel data
+ */
+ private int excelDataStartBlock;
+
+ /**
+ * The start block of the big block depot
+ */
+ private int bbdStartBlock;
+
+ /**
+ * The start block of the small block depot
+ */
+ private int sbdStartBlockChain;
+
+ /**
+ * The start block of the small block depot
+ */
+ private int sbdStartBlock;
+
+ /**
+ * The number of big blocks required for additional property sets
+ */
+ private int additionalPropertyBlocks;
+
+ /**
+ * The number of small blocks
+ */
+ private int numSmallBlocks;
+
+ /**
+ * The total number of property sets in this compound file
+ */
+ private int numPropertySets;
+
+ /**
+ * The number of blocks required to store the root entry property sets
+ * and small block depot
+ */
+ private int numRootEntryBlocks;
+
+ /**
+ * The list of additional, non standard property sets names
+ */
+ private ArrayList additionalPropertySets;
+
+ /**
+ * The map of standard property sets, keyed on name
+ */
+ private HashMap standardPropertySets;
+
+ /**
+ * Structure used to store the property set and the data
+ */
+ private static final class ReadPropertyStorage
+ {
+ PropertyStorage propertyStorage;
+ byte[] data;
+ int number;
+
+ ReadPropertyStorage(PropertyStorage ps, byte[] d, int n)
+ {
+ propertyStorage = ps;
+ data = d;
+ number = n;
+ }
+ }
+
+
+ // The following member variables are used across methods when
+ // writing out the big block depot
+ /**
+ * The current position within the bbd. Used when writing out the
+ * BBD
+ */
+ private int bbdPos;
+
+ /**
+ * The current bbd block
+ */
+ private byte[] bigBlockDepot;
+
+
+ /**
+ * Constructor
+ *
+ * @param l the length of the data
+ * @param os the output stream to write to
+ * @param data the excel data
+ * @param rcf the read compound
+ */
+ public CompoundFile(ExcelDataOutput data, int l, OutputStream os,
+ jxl.read.biff.CompoundFile rcf)
+ throws CopyAdditionalPropertySetsException, IOException
+ {
+ super();
+ size = l;
+ excelData = data;
+
+ readAdditionalPropertySets(rcf);
+
+ numRootEntryBlocks = 1;
+ numPropertySets = 4 +
+ (additionalPropertySets != null ? additionalPropertySets.size() : 0);
+
+
+ if (additionalPropertySets != null)
+ {
+ numSmallBlockDepotChainBlocks = getBigBlocksRequired(numSmallBlocks * 4);
+ numSmallBlockDepotBlocks = getBigBlocksRequired
+ (numSmallBlocks * SMALL_BLOCK_SIZE);
+
+ numRootEntryBlocks += getBigBlocksRequired
+ (additionalPropertySets.size() * PROPERTY_STORAGE_BLOCK_SIZE);
+ }
+
+
+ int blocks = getBigBlocksRequired(l);
+
+ // First pad the data out so that it fits nicely into a whole number
+ // of blocks
+ if (l < SMALL_BLOCK_THRESHOLD)
+ {
+ requiredSize = SMALL_BLOCK_THRESHOLD;
+ }
+ else
+ {
+ requiredSize = blocks * BIG_BLOCK_SIZE;
+ }
+
+ out = os;
+
+
+ // Do the calculations
+ excelDataBlocks = requiredSize/BIG_BLOCK_SIZE;
+ numBigBlockDepotBlocks = 1;
+
+ int blockChainLength = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4;
+
+ int startTotalBlocks = excelDataBlocks +
+ 8 + // summary block
+ 8 + // document information
+ additionalPropertyBlocks +
+ numSmallBlockDepotBlocks +
+ numSmallBlockDepotChainBlocks +
+ numRootEntryBlocks;
+
+ int totalBlocks = startTotalBlocks + numBigBlockDepotBlocks;
+
+ // Calculate the number of BBD blocks needed to hold this info
+ numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks /
+ (double) (BIG_BLOCK_SIZE/4));
+
+ // Does this affect the total?
+ totalBlocks = startTotalBlocks + numBigBlockDepotBlocks;
+
+ // And recalculate
+ numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks /
+ (double) (BIG_BLOCK_SIZE/4));
+
+ // Does this affect the total?
+ totalBlocks = startTotalBlocks + numBigBlockDepotBlocks;
+
+ // See if the excel bbd chain can fit into the header block.
+ // Remember to allow for the end of chain indicator
+ if (numBigBlockDepotBlocks > blockChainLength - 1 )
+ {
+ // Sod it - we need an extension block. We have to go through
+ // the whole tiresome calculation again
+ extensionBlock = 0;
+
+ // Compute the number of extension blocks
+ int bbdBlocksLeft = numBigBlockDepotBlocks - blockChainLength + 1;
+
+ numExtensionBlocks = (int) Math.ceil((double) bbdBlocksLeft /
+ (double) (BIG_BLOCK_SIZE/4 - 1));
+
+ // Modify the total number of blocks required and recalculate the
+ // the number of bbd blocks
+ totalBlocks = startTotalBlocks +
+ numExtensionBlocks +
+ numBigBlockDepotBlocks;
+ numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks /
+ (double) (BIG_BLOCK_SIZE/4));
+
+ // The final total
+ totalBlocks = startTotalBlocks +
+ numExtensionBlocks +
+ numBigBlockDepotBlocks;
+ }
+ else
+ {
+ extensionBlock = -2;
+ numExtensionBlocks = 0;
+ }
+
+ // Set the excel data start block to be after the header (and
+ // its extensions)
+ excelDataStartBlock = numExtensionBlocks;
+
+ // Set the start block of the small block depot
+ sbdStartBlock = -2;
+ if (additionalPropertySets != null && numSmallBlockDepotBlocks != 0)
+ {
+ sbdStartBlock = excelDataStartBlock +
+ excelDataBlocks +
+ additionalPropertyBlocks +
+ 16;
+ }
+
+ // Set the sbd chain start block to be after the excel data and the
+ // small block depot
+ sbdStartBlockChain = -2;
+
+ if (sbdStartBlock != -2)
+ {
+ sbdStartBlockChain = sbdStartBlock + numSmallBlockDepotBlocks;
+ }
+
+ // Set the bbd start block to be after all the excel data
+ if (sbdStartBlockChain != -2)
+ {
+ bbdStartBlock = sbdStartBlockChain +
+ numSmallBlockDepotChainBlocks;
+ }
+ else
+ {
+ bbdStartBlock = excelDataStartBlock +
+ excelDataBlocks +
+ additionalPropertyBlocks +
+ 16;
+ }
+
+ // Set the root start block to be after all the big block depot blocks
+ rootStartBlock = bbdStartBlock +
+ numBigBlockDepotBlocks;
+
+
+ if (totalBlocks != rootStartBlock + numRootEntryBlocks)
+ {
+ logger.warn("Root start block and total blocks are inconsistent " +
+ " generated file may be corrupt");
+ logger.warn("RootStartBlock " + rootStartBlock + " totalBlocks " + totalBlocks);
+ }
+ }
+
+ /**
+ * Reads the additional property sets from the read in compound file
+ *
+ * @param readCompoundFile the file read in
+ * @exception CopyAdditionalPropertySetsException
+ * @exception IOException
+ */
+ private void readAdditionalPropertySets
+ (jxl.read.biff.CompoundFile readCompoundFile)
+ throws CopyAdditionalPropertySetsException, IOException
+ {
+ if (readCompoundFile == null)
+ {
+ return;
+ }
+
+ additionalPropertySets = new ArrayList();
+ standardPropertySets = new HashMap();
+ int blocksRequired = 0;
+
+ int numPropertySets = readCompoundFile.getNumberOfPropertySets();
+
+ for (int i = 0 ; i < numPropertySets ; i++)
+ {
+ PropertyStorage ps = readCompoundFile.getPropertySet(i);
+
+ boolean standard = false;
+
+ if (ps.name.equalsIgnoreCase(ROOT_ENTRY_NAME))
+ {
+ standard = true;
+ ReadPropertyStorage rps = new ReadPropertyStorage(ps, null, i);
+ standardPropertySets.put(ROOT_ENTRY_NAME, rps);
+ }
+
+ // See if it is a standard property set
+ for (int j = 0 ; j < STANDARD_PROPERTY_SETS.length && !standard ; j++)
+ {
+ if (ps.name.equalsIgnoreCase(STANDARD_PROPERTY_SETS[j]))
+ {
+ // See if it comes directly off the root entry
+ PropertyStorage ps2 = readCompoundFile.findPropertyStorage(ps.name);
+ Assert.verify(ps2 != null);
+
+ if (ps2 == ps)
+ {
+ standard = true;
+ ReadPropertyStorage rps = new ReadPropertyStorage(ps, null, i);
+ standardPropertySets.put(STANDARD_PROPERTY_SETS[j], rps);
+ }
+ }
+ }
+
+ if (!standard)
+ {
+ try
+ {
+ byte[] data = null;
+ if (ps.size > 0 )
+ {
+ data = readCompoundFile.getStream(i);
+ }
+ else
+ {
+ data = new byte[0];
+ }
+ ReadPropertyStorage rps = new ReadPropertyStorage(ps, data, i);
+ additionalPropertySets.add(rps);
+
+ if (data.length > SMALL_BLOCK_THRESHOLD)
+ {
+ int blocks = getBigBlocksRequired(data.length);
+ blocksRequired += blocks;
+ }
+ else
+ {
+ int blocks = getSmallBlocksRequired(data.length);
+ numSmallBlocks += blocks;
+ }
+ }
+ catch (BiffException e)
+ {
+ logger.error(e);
+ throw new CopyAdditionalPropertySetsException();
+ }
+ }
+ }
+
+ additionalPropertyBlocks = blocksRequired;
+ }
+
+ /**
+ * Writes out the excel file in OLE compound file format
+ *
+ * @exception IOException
+ */
+ public void write() throws IOException
+ {
+ writeHeader();
+ writeExcelData();
+ writeDocumentSummaryData();
+ writeSummaryData();
+ writeAdditionalPropertySets();
+ writeSmallBlockDepot();
+ writeSmallBlockDepotChain();
+ writeBigBlockDepot();
+ writePropertySets();
+
+ // Don't flush or close the stream - this is handled by the enclosing File
+ // object
+ }
+
+ /**
+ * Writes out any additional property sets
+ */
+ private void writeAdditionalPropertySets() throws IOException
+ {
+ if (additionalPropertySets == null)
+ {
+ return;
+ }
+
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ;)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+ byte[] data = rps.data;
+
+ if (data.length > SMALL_BLOCK_THRESHOLD)
+ {
+ int numBlocks = getBigBlocksRequired(data.length);
+ int requiredSize = numBlocks * BIG_BLOCK_SIZE;
+
+ out.write(data, 0, data.length);
+
+ byte[] padding = new byte[requiredSize - data.length];
+ out.write(padding, 0, padding.length);
+ }
+ }
+ }
+
+ /**
+ * Writes out the excel data, padding it out with empty bytes as
+ * necessary
+ * Also write out empty
+ *
+ * @exception IOException
+ */
+ private void writeExcelData() throws IOException
+ {
+ excelData.writeData(out);
+
+ byte[] padding = new byte[requiredSize - size];
+ out.write(padding);
+ }
+
+ /**
+ * Write out the document summary data. This is just blank
+ *
+ * @exception IOException
+ */
+ private void writeDocumentSummaryData() throws IOException
+ {
+ byte[] padding = new byte[SMALL_BLOCK_THRESHOLD];
+
+ // Write out the summary information
+ out.write(padding);
+ }
+
+ /**
+ * Write out the summary data. This is just blank
+ *
+ * @exception IOException
+ */
+ private void writeSummaryData() throws IOException
+ {
+ byte[] padding = new byte[SMALL_BLOCK_THRESHOLD];
+
+ // Write out the summary information
+ out.write(padding);
+ }
+
+ /**
+ * Writes the compound file header
+ *
+ * @exception IOException
+ */
+ private void writeHeader() throws IOException
+ {
+ // Build up the header array
+ byte[] headerBlock = new byte[BIG_BLOCK_SIZE];
+ byte[] extensionBlockData = new byte[BIG_BLOCK_SIZE * numExtensionBlocks];
+
+ // Copy in the identifier
+ System.arraycopy(IDENTIFIER, 0, headerBlock, 0, IDENTIFIER.length);
+
+ // Copy in some magic values - no idea what they mean
+ headerBlock[0x18] = 0x3e;
+ headerBlock[0x1a] = 0x3;
+ headerBlock[0x1c] = (byte) 0xfe;
+ headerBlock[0x1d] = (byte) 0xff;
+ headerBlock[0x1e] = 0x9;
+ headerBlock[0x20] = 0x6;
+ headerBlock[0x39] = 0x10;
+
+ // Set the number of BBD blocks
+ IntegerHelper.getFourBytes(numBigBlockDepotBlocks,
+ headerBlock,
+ NUM_BIG_BLOCK_DEPOT_BLOCKS_POS);
+
+ // Set the small block depot chain
+ IntegerHelper.getFourBytes(sbdStartBlockChain,
+ headerBlock,
+ SMALL_BLOCK_DEPOT_BLOCK_POS);
+
+ // Set the number of blocks in the small block depot chain
+ IntegerHelper.getFourBytes(numSmallBlockDepotChainBlocks,
+ headerBlock,
+ NUM_SMALL_BLOCK_DEPOT_BLOCKS_POS);
+
+ // Set the extension block
+ IntegerHelper.getFourBytes(extensionBlock,
+ headerBlock,
+ EXTENSION_BLOCK_POS);
+
+ // Set the number of extension blocks to be the number of BBD blocks - 1
+ IntegerHelper.getFourBytes(numExtensionBlocks,
+ headerBlock,
+ NUM_EXTENSION_BLOCK_POS);
+
+ // Set the root start block
+ IntegerHelper.getFourBytes(rootStartBlock,
+ headerBlock,
+ ROOT_START_BLOCK_POS);
+
+ // Set the block numbers for the BBD. Set the BBD running
+ // after the excel data and summary information
+ int pos = BIG_BLOCK_DEPOT_BLOCKS_POS;
+
+ // See how many blocks fit into the header
+ int blocksToWrite = Math.min(numBigBlockDepotBlocks,
+ (BIG_BLOCK_SIZE -
+ BIG_BLOCK_DEPOT_BLOCKS_POS)/4);
+ int blocksWritten = 0;
+
+ for (int i = 0 ; i < blocksToWrite; i++)
+ {
+ IntegerHelper.getFourBytes(bbdStartBlock + i,
+ headerBlock,
+ pos);
+ pos += 4;
+ blocksWritten++;
+ }
+
+ // Pad out the rest of the header with blanks
+ for (int i = pos; i < BIG_BLOCK_SIZE; i++)
+ {
+ headerBlock[i] = (byte) 0xff;
+ }
+
+ out.write(headerBlock);
+
+ // Write out the extension blocks
+ pos = 0;
+
+ for (int extBlock = 0; extBlock < numExtensionBlocks; extBlock++)
+ {
+ blocksToWrite = Math.min(numBigBlockDepotBlocks - blocksWritten,
+ BIG_BLOCK_SIZE/4 -1);
+
+ for(int j = 0 ; j < blocksToWrite; j++)
+ {
+ IntegerHelper.getFourBytes(bbdStartBlock + blocksWritten + j,
+ extensionBlockData,
+ pos);
+ pos += 4;
+ }
+
+ blocksWritten += blocksToWrite;
+
+ // Indicate the next block, or the termination of the chain
+ int nextBlock = (blocksWritten == numBigBlockDepotBlocks) ?
+ -2 : extBlock+1 ;
+ IntegerHelper.getFourBytes(nextBlock, extensionBlockData, pos);
+ pos +=4;
+ }
+
+ if (numExtensionBlocks > 0)
+ {
+ // Pad out the rest of the extension block with blanks
+ for (int i = pos; i < extensionBlockData.length; i++)
+ {
+ extensionBlockData[i] = (byte) 0xff;
+ }
+
+ out.write(extensionBlockData);
+ }
+ }
+
+ /**
+ * Checks that the data can fit into the current BBD block. If not,
+ * then it moves on to the next block
+ *
+ * @exception IOException
+ */
+ private void checkBbdPos() throws IOException
+ {
+ if (bbdPos >= BIG_BLOCK_SIZE)
+ {
+ // Write out the extension block. This will simply be the next block
+ out.write(bigBlockDepot);
+
+ // Create a new block
+ bigBlockDepot = new byte[BIG_BLOCK_SIZE];
+ bbdPos = 0;
+ }
+ }
+
+ /**
+ * Writes out the big block chain
+ *
+ * @param startBlock the starting block of the big block chain
+ * @param numBlocks the number of blocks in the chain
+ * @exception IOException
+ */
+ private void writeBlockChain(int startBlock, int numBlocks)
+ throws IOException
+ {
+ int blocksToWrite = numBlocks - 1;
+ int blockNumber = startBlock + 1;
+
+ while (blocksToWrite > 0)
+ {
+ int bbdBlocks = Math.min(blocksToWrite, (BIG_BLOCK_SIZE - bbdPos)/4);
+
+ for (int i = 0 ; i < bbdBlocks; i++)
+ {
+ IntegerHelper.getFourBytes(blockNumber, bigBlockDepot, bbdPos);
+ bbdPos +=4 ;
+ blockNumber++;
+ }
+
+ blocksToWrite -= bbdBlocks;
+ checkBbdPos();
+ }
+
+ // Write the end of the block chain
+ IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+ }
+
+ /**
+ * Writes the block chains for the additional property sets
+ *
+ * @exception IOException
+ */
+ private void writeAdditionalPropertySetBlockChains() throws IOException
+ {
+ if (additionalPropertySets == null)
+ {
+ return;
+ }
+
+ int blockNumber = excelDataStartBlock + excelDataBlocks + 16;
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ; )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+ if (rps.data.length > SMALL_BLOCK_THRESHOLD)
+ {
+ int numBlocks = getBigBlocksRequired(rps.data.length);
+
+ writeBlockChain(blockNumber, numBlocks);
+ blockNumber += numBlocks;
+ }
+ }
+ }
+
+ /**
+ * Writes out the chains for the small block depot
+ */
+ private void writeSmallBlockDepotChain() throws IOException
+ {
+ if (sbdStartBlockChain == -2)
+ {
+ return;
+ }
+
+ byte[] smallBlockDepotChain =
+ new byte[numSmallBlockDepotChainBlocks * BIG_BLOCK_SIZE];
+
+ int pos = 0;
+ int sbdBlockNumber = 1;
+
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ; )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+
+ if (rps.data.length <= SMALL_BLOCK_THRESHOLD &&
+ rps.data.length != 0)
+ {
+ int numSmallBlocks = getSmallBlocksRequired(rps.data.length);
+ for (int j = 0 ; j < numSmallBlocks - 1 ; j++)
+ {
+ IntegerHelper.getFourBytes(sbdBlockNumber,
+ smallBlockDepotChain,
+ pos);
+ pos += 4;
+ sbdBlockNumber++;
+ }
+
+ // Write out the end of chain
+ IntegerHelper.getFourBytes(-2, smallBlockDepotChain, pos);
+ pos += 4;
+ sbdBlockNumber++;
+ }
+ }
+
+ out.write(smallBlockDepotChain);
+ }
+
+ /**
+ * Writes out all the data in the small block depot
+ *
+ * @exception
+ */
+ private void writeSmallBlockDepot() throws IOException
+ {
+ if (additionalPropertySets == null)
+ {
+ return;
+ }
+
+ byte[] smallBlockDepot =
+ new byte[numSmallBlockDepotBlocks * BIG_BLOCK_SIZE];
+
+ int pos = 0;
+
+ for (Iterator i = additionalPropertySets.iterator() ; i.hasNext() ; )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+
+ if (rps.data.length <= SMALL_BLOCK_THRESHOLD)
+ {
+ int smallBlocks = getSmallBlocksRequired(rps.data.length);
+ int length = smallBlocks * SMALL_BLOCK_SIZE;
+ System.arraycopy(rps.data, 0, smallBlockDepot, pos, rps.data.length);
+ pos += length;
+ }
+ }
+
+ out.write(smallBlockDepot);
+ }
+
+ /**
+ * Writes out the Big Block Depot
+ *
+ * @exception IOException
+ */
+ private void writeBigBlockDepot() throws IOException
+ {
+ // This is after the excel data, the summary information, the
+ // big block property sets and the small block depot
+ bigBlockDepot = new byte[BIG_BLOCK_SIZE];
+ bbdPos = 0;
+
+ // Write out the extension blocks, indicating them as special blocks
+ for (int i = 0 ; i < numExtensionBlocks; i++)
+ {
+ IntegerHelper.getFourBytes(-3, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+ }
+
+ writeBlockChain(excelDataStartBlock, excelDataBlocks);
+
+ // The excel data has been written. Now write out the rest of it
+
+ // Write the block chain for the summary information
+ int summaryInfoBlock = excelDataStartBlock +
+ excelDataBlocks +
+ additionalPropertyBlocks;
+
+ for (int i = summaryInfoBlock; i < summaryInfoBlock + 7; i++)
+ {
+ IntegerHelper.getFourBytes(i + 1, bigBlockDepot, bbdPos);
+ bbdPos +=4 ;
+ checkBbdPos();
+ }
+
+ // Write the end of the block chain for the summary info block
+ IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+
+ // Write the block chain for the document summary information
+ for (int i = summaryInfoBlock + 8; i < summaryInfoBlock + 15; i++)
+ {
+ IntegerHelper.getFourBytes(i + 1, bigBlockDepot, bbdPos);
+ bbdPos +=4 ;
+ checkBbdPos();
+ }
+
+ // Write the end of the block chain for the document summary
+ IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+
+ // Write out the block chain for the copied property sets, if present
+ writeAdditionalPropertySetBlockChains();
+
+ if (sbdStartBlock != -2)
+ {
+ // Write out the block chain for the small block depot
+ writeBlockChain(sbdStartBlock, numSmallBlockDepotBlocks);
+
+ // Write out the block chain for the small block depot chain
+ writeBlockChain(sbdStartBlockChain, numSmallBlockDepotChainBlocks);
+ }
+
+ // The Big Block Depot immediately follows. Denote these as a special
+ // block
+ for (int i = 0; i < numBigBlockDepotBlocks; i++)
+ {
+ IntegerHelper.getFourBytes(-3, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+ }
+
+ // Write the root entry
+ writeBlockChain(rootStartBlock, numRootEntryBlocks);
+
+ // Pad out the remainder of the block
+ if (bbdPos != 0)
+ {
+ for (int i = bbdPos; i < BIG_BLOCK_SIZE; i++)
+ {
+ bigBlockDepot[i] = (byte) 0xff;
+ }
+ out.write(bigBlockDepot);
+ }
+ }
+
+ /**
+ * Calculates the number of big blocks required to store data of the
+ * specified length
+ *
+ * @param length the length of the data
+ * @return the number of big blocks required to store the data
+ */
+ private int getBigBlocksRequired(int length)
+ {
+ int blocks = length / BIG_BLOCK_SIZE;
+
+ return (length % BIG_BLOCK_SIZE > 0 )? blocks + 1 : blocks;
+ }
+
+ /**
+ * Calculates the number of small blocks required to store data of the
+ * specified length
+ *
+ * @param length the length of the data
+ * @return the number of small blocks required to store the data
+ */
+ private int getSmallBlocksRequired(int length)
+ {
+ int blocks = length / SMALL_BLOCK_SIZE;
+
+ return (length % SMALL_BLOCK_SIZE > 0 )? blocks + 1 : blocks;
+ }
+
+ /**
+ * Writes out the property sets
+ *
+ * @exception IOException
+ */
+ private void writePropertySets() throws IOException
+ {
+ byte[] propertySetStorage = new byte[BIG_BLOCK_SIZE * numRootEntryBlocks];
+
+ int pos = 0;
+ int[] mappings = null;
+
+ // Build up the mappings array
+ if (additionalPropertySets != null)
+ {
+ mappings = new int[numPropertySets];
+
+ // Map the standard ones to the first four
+ for (int i = 0 ; i < STANDARD_PROPERTY_SETS.length ; i++)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ standardPropertySets.get(STANDARD_PROPERTY_SETS[i]);
+
+ if (rps != null)
+ {
+ mappings[rps.number] = i;
+ }
+ else
+ {
+ logger.warn("Standard property set " + STANDARD_PROPERTY_SETS[i] +
+ " not present in source file");
+ }
+ }
+
+ // Now go through the original ones
+ int newMapping = STANDARD_PROPERTY_SETS.length;
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext(); )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+ mappings[rps.number] = newMapping;
+ newMapping++;
+ }
+ }
+
+ int child = 0;
+ int previous = 0;
+ int next = 0;
+
+ // Compute the size of the root property set
+ int size = 0;
+
+ if (additionalPropertySets != null)
+ {
+ // Workbook
+ size += getBigBlocksRequired(requiredSize) * BIG_BLOCK_SIZE;
+
+ // The two information blocks
+ size += getBigBlocksRequired(SMALL_BLOCK_THRESHOLD) * BIG_BLOCK_SIZE;
+ size += getBigBlocksRequired(SMALL_BLOCK_THRESHOLD) * BIG_BLOCK_SIZE;
+
+ // Additional property sets
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext(); )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+ if (rps.propertyStorage.type != 1)
+ {
+ if (rps.propertyStorage.size >= SMALL_BLOCK_THRESHOLD)
+ {
+ size += getBigBlocksRequired(rps.propertyStorage.size) *
+ BIG_BLOCK_SIZE;
+ }
+ else
+ {
+ size += getSmallBlocksRequired(rps.propertyStorage.size) *
+ SMALL_BLOCK_SIZE;
+ }
+ }
+ }
+ }
+
+ // Set the root entry property set
+ PropertyStorage ps = new PropertyStorage(ROOT_ENTRY_NAME);
+ ps.setType(5);
+ ps.setStartBlock(sbdStartBlock);
+ ps.setSize(size);
+ ps.setPrevious(-1);
+ ps.setNext(-1);
+ ps.setColour(0);
+
+ child = 1;
+ if (additionalPropertySets != null)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ standardPropertySets.get(ROOT_ENTRY_NAME);
+ child = mappings[rps.propertyStorage.child];
+ }
+ ps.setChild(child);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+
+ // Set the workbook property set
+ ps = new PropertyStorage(WORKBOOK_NAME);
+ ps.setType(2);
+ ps.setStartBlock(excelDataStartBlock);
+ // start the excel data after immediately after this block
+ ps.setSize(requiredSize);
+ // always use a big block stream - none of that messing around
+ // with small blocks
+
+ previous = 3;
+ next = -1;
+
+ if (additionalPropertySets != null)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ standardPropertySets.get(WORKBOOK_NAME);
+ previous = rps.propertyStorage.previous != -1 ?
+ mappings[rps.propertyStorage.previous] : -1;
+ next = rps.propertyStorage.next != -1 ?
+ mappings[rps.propertyStorage.next] : -1 ;
+ }
+
+ ps.setPrevious(previous);
+ ps.setNext(next);
+ ps.setChild(-1);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+ // Set the summary information
+ ps = new PropertyStorage(SUMMARY_INFORMATION_NAME);
+ ps.setType(2);
+ ps.setStartBlock(excelDataStartBlock + excelDataBlocks);
+ ps.setSize(SMALL_BLOCK_THRESHOLD);
+
+ previous = 1;
+ next = 3;
+
+ if (additionalPropertySets != null)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ standardPropertySets.get(SUMMARY_INFORMATION_NAME);
+
+ if (rps != null)
+ {
+ previous = rps.propertyStorage.previous != - 1 ?
+ mappings[rps.propertyStorage.previous] : -1 ;
+ next = rps.propertyStorage.next != - 1 ?
+ mappings[rps.propertyStorage.next] : -1 ;
+ }
+ }
+
+ ps.setPrevious(previous);
+ ps.setNext(next);
+ ps.setChild(-1);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+ // Set the document summary information
+ ps = new PropertyStorage(DOCUMENT_SUMMARY_INFORMATION_NAME);
+ ps.setType(2);
+ ps.setStartBlock(excelDataStartBlock + excelDataBlocks + 8);
+ ps.setSize(SMALL_BLOCK_THRESHOLD);
+ ps.setPrevious(-1);
+ ps.setNext(-1);
+ ps.setChild(-1);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+
+
+ // Write out the additional property sets
+ if (additionalPropertySets == null)
+ {
+ out.write(propertySetStorage);
+ return;
+ }
+
+ int bigBlock = excelDataStartBlock + excelDataBlocks + 16;
+ int smallBlock = 0;
+
+ for (Iterator i = additionalPropertySets.iterator() ; i.hasNext(); )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+
+ int block = rps.data.length > SMALL_BLOCK_THRESHOLD ?
+ bigBlock : smallBlock;
+
+ ps = new PropertyStorage(rps.propertyStorage.name);
+ ps.setType(rps.propertyStorage.type);
+ ps.setStartBlock(block);
+ ps.setSize(rps.propertyStorage.size);
+ // ps.setColour(rps.propertyStorage.colour);
+
+ previous = rps.propertyStorage.previous != -1 ?
+ mappings[rps.propertyStorage.previous] : -1;
+ next = rps.propertyStorage.next != -1 ?
+ mappings[rps.propertyStorage.next] : -1;
+ child = rps.propertyStorage.child != -1 ?
+ mappings[rps.propertyStorage.child] : -1;
+
+ ps.setPrevious(previous);
+ ps.setNext(next);
+ ps.setChild(child);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+ if (rps.data.length > SMALL_BLOCK_THRESHOLD)
+ {
+ bigBlock += getBigBlocksRequired(rps.data.length);
+ }
+ else
+ {
+ smallBlock += getSmallBlocksRequired(rps.data.length);
+ }
+ }
+
+ out.write(propertySetStorage);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/CompoundFile.java2
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/CompoundFile.java2,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/CompoundFile.java2 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,1217 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.OutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.HashMap;
+
+import common.Assert;
+import common.Logger;
+import jxl.biff.BaseCompoundFile;
+import jxl.biff.IntegerHelper;
+import jxl.read.biff.BiffException;
+
+/**
+ * Writes out a compound file
+ *
+ * Header block is -1
+ * Excel data is e..n (where is the head extension blocks, normally 0 and
+ * n is at least 8)
+ * Summary information (8 blocks)
+ * Document summary (8 blocks)
+ * BBD is block p..q (where p=e+n+16 and q-p+1 is the number of BBD blocks)
+ * Property storage block is q+b...r (normally 1 block) (where b is the number
+ * of BBD blocks)
+ */
+final class CompoundFile extends BaseCompoundFile
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(CompoundFile.class);
+
+ /**
+ * The stream to which the jumbled up data is written to
+ */
+ private OutputStream out;
+ /**
+ * The organized biff records which form the actual excel data
+ */
+ private byte[] excelData;
+
+ /**
+ * The size of the array
+ */
+ private int size;
+
+ /**
+ * The size the excel data should be in order to comply with the
+ * general compound file format
+ */
+ private int requiredSize;
+
+ /**
+ * The number of blocks it takes to store the big block depot
+ */
+ private int numBigBlockDepotBlocks;
+
+ /**
+ * The number of blocks it takes to store the small block depot chain
+ */
+ private int numSmallBlockDepotChainBlocks;
+
+ /**
+ * The number of blocks it takes to store the small block depot
+ */
+ private int numSmallBlockDepotBlocks;
+
+ /**
+ * The number of extension blocks required for the header to describe
+ * the BBD
+ */
+ private int numExtensionBlocks;
+
+ /**
+ * The extension block for the header
+ */
+ private int extensionBlock;
+
+ /**
+ * The number of blocks it takes to store the excel data
+ */
+ private int excelDataBlocks;
+
+ /**
+ * The start block of the root entry
+ */
+ private int rootStartBlock;
+
+ /**
+ * The start block of the excel data
+ */
+ private int excelDataStartBlock;
+
+ /**
+ * The start block of the big block depot
+ */
+ private int bbdStartBlock;
+
+ /**
+ * The start block of the small block depot
+ */
+ private int sbdStartBlockChain;
+
+ /**
+ * The start block of the small block depot
+ */
+ private int sbdStartBlock;
+
+ /**
+ * The number of big blocks required for additional property sets
+ */
+ private int additionalPropertyBlocks;
+
+ /**
+ * The number of small blocks
+ */
+ private int numSmallBlocks;
+
+ /**
+ * The total number of property sets in this compound file
+ */
+ private int numPropertySets;
+
+ /**
+ * The number of blocks required to store the root entry property sets
+ * and small block depot
+ */
+ private int numRootEntryBlocks;
+
+ /**
+ * The list of additional, non standard property sets names
+ */
+ private ArrayList additionalPropertySets;
+
+ /**
+ * A hash map of the original property sets keyed on name
+ */
+ private HashMap readPropertySets;
+
+ /**
+ * The array of standard property set mappings
+ */
+ private int[] standardPropertySetMappings;
+
+ private ReadPropertyStorage rootEntryPropertySet;
+
+ /**
+ * Structure used to store the property set and the data
+ */
+ private static final class ReadPropertyStorage
+ {
+ PropertyStorage propertyStorage;
+ byte[] data;
+ int number;
+
+ ReadPropertyStorage(PropertyStorage ps, byte[] d, int n)
+ {
+ propertyStorage = ps;
+ data = d;
+ number = n;
+ }
+ }
+
+
+ // The following member variables are used across methods when
+ // writing out the big block depot
+ /**
+ * The current position within the bbd. Used when writing out the
+ * BBD
+ */
+ private int bbdPos;
+
+ /**
+ * The current bbd block
+ */
+ private byte[] bigBlockDepot;
+
+
+ /**
+ * Constructor
+ *
+ * @param l the length of the data
+ * @param os the output stream to write to
+ * @param data the excel data
+ * @param rcf the read compound
+ */
+ public CompoundFile(byte[] data, int l, OutputStream os,
+ jxl.read.biff.CompoundFile rcf)
+ throws CopyAdditionalPropertySetsException, IOException
+ {
+ super();
+ size = l;
+ excelData = data;
+
+ readAdditionalPropertySets(rcf);
+
+ numRootEntryBlocks = 1;
+ numPropertySets = 4 +
+ (additionalPropertySets != null ? additionalPropertySets.size() : 0);
+
+ logger.debug("numSmallBlocks " + numSmallBlocks);
+
+ if (additionalPropertySets != null)
+ {
+ /*
+ try
+ {
+ rootEntryPropertySet = new ReadPropertyStorage(rcf.getPropertySet(ROOT_ENTRY_NAME), rcf.getStream(ROOT_ENTRY_NAME), 0);
+ numSmallBlocks += getSmallBlocksRequired(rootEntryPropertySet.data.length);
+ logger.debug("small blocks for root entry " + getSmallBlocksRequired(rootEntryPropertySet.data.length));
+ }
+ catch (BiffException e)
+ {
+ e.printStackTrace();
+ }
+ */
+
+ numSmallBlockDepotChainBlocks = getBigBlocksRequired(numSmallBlocks * 4);
+ numSmallBlockDepotBlocks = getBigBlocksRequired
+ (numSmallBlocks * SMALL_BLOCK_SIZE);
+
+ numRootEntryBlocks += getBigBlocksRequired
+ (additionalPropertySets.size() * PROPERTY_STORAGE_BLOCK_SIZE);
+ }
+
+ logger.debug("root entry requires " + numRootEntryBlocks + " blocks");
+
+ int blocks = getBigBlocksRequired(l);
+
+ // First pad the data out so that it fits nicely into a whole number
+ // of blocks
+ if (l < SMALL_BLOCK_THRESHOLD)
+ {
+ requiredSize = SMALL_BLOCK_THRESHOLD;
+ }
+ else
+ {
+ requiredSize = blocks * BIG_BLOCK_SIZE;
+ }
+
+ out = os;
+
+ // logger.debug("smallBlockDepot requires " + numSmallBlockDepotBlocks + " big blocks");
+
+ // Do the calculations
+ excelDataBlocks = requiredSize/BIG_BLOCK_SIZE;
+ numBigBlockDepotBlocks = 1;
+
+ int blockChainLength = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4;
+
+ int startTotalBlocks = excelDataBlocks +
+ 8 + // summary block
+ 8 + // document information
+ additionalPropertyBlocks +
+ numSmallBlockDepotBlocks +
+ numSmallBlockDepotChainBlocks +
+ numRootEntryBlocks;
+
+ int totalBlocks = startTotalBlocks + numBigBlockDepotBlocks;
+
+ // Calculate the number of BBD blocks needed to hold this info
+ numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks /
+ (double) (BIG_BLOCK_SIZE/4));
+
+ // Does this affect the total?
+ totalBlocks = startTotalBlocks + numBigBlockDepotBlocks;
+
+ // And recalculate
+ numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks /
+ (double) (BIG_BLOCK_SIZE/4));
+
+ // Does this affect the total?
+ totalBlocks = startTotalBlocks + numBigBlockDepotBlocks;
+
+ // See if the excel bbd chain can fit into the header block.
+ // Remember to allow for the end of chain indicator
+ if (numBigBlockDepotBlocks > blockChainLength - 1 )
+ {
+ // Sod it - we need an extension block. We have to go through
+ // the whole tiresome calculation again
+ extensionBlock = 0;
+
+ // Compute the number of extension blocks
+ int bbdBlocksLeft = numBigBlockDepotBlocks - blockChainLength + 1;
+
+ numExtensionBlocks = (int) Math.ceil((double) bbdBlocksLeft /
+ (double) (BIG_BLOCK_SIZE/4 - 1));
+
+ // Modify the total number of blocks required and recalculate the
+ // the number of bbd blocks
+ totalBlocks = startTotalBlocks +
+ numExtensionBlocks +
+ numBigBlockDepotBlocks;
+ numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks /
+ (double) (BIG_BLOCK_SIZE/4));
+
+ // The final total
+ totalBlocks = startTotalBlocks +
+ numExtensionBlocks +
+ numBigBlockDepotBlocks;
+ }
+ else
+ {
+ extensionBlock = -2;
+ numExtensionBlocks = 0;
+ }
+
+ // Set the excel data start block to be after the header (and
+ // its extensions)
+ excelDataStartBlock = numExtensionBlocks;
+
+ logger.debug("excelDataStartBlock " + excelDataStartBlock);
+
+ // Set the start block of the small block depot
+ sbdStartBlock = -2;
+ if (additionalPropertySets != null)
+ {
+ sbdStartBlock = excelDataStartBlock +
+ excelDataBlocks +
+ additionalPropertyBlocks +
+ 16;
+ }
+
+ // Set the sbd chain start block to be after the excel data and the
+ // small block depot
+ sbdStartBlockChain = -2;
+
+ if (sbdStartBlock != -2)
+ {
+ sbdStartBlockChain = sbdStartBlock + numSmallBlockDepotBlocks;
+ }
+
+ logger.debug("sbdStartBlockChain " + sbdStartBlockChain);
+
+ // Set the bbd start block to be after all the excel data
+ if (sbdStartBlockChain != -2)
+ {
+ bbdStartBlock = sbdStartBlockChain +
+ numSmallBlockDepotChainBlocks;
+ }
+ else
+ {
+ bbdStartBlock = excelDataStartBlock +
+ excelDataBlocks +
+ additionalPropertyBlocks +
+ 16;
+ }
+
+ logger.debug("bbdStartBlock " + bbdStartBlock);
+
+ // Set the root start block to be after all the big block depot blocks
+ rootStartBlock = bbdStartBlock +
+ numBigBlockDepotBlocks;
+
+
+ if (totalBlocks != rootStartBlock + numRootEntryBlocks)
+ {
+ logger.warn("Root start block and total blocks are inconsistent " +
+ " generated file may be corrupt");
+ logger.warn("RootStartBlock " + rootStartBlock + " totalBlocks " + totalBlocks);
+ }
+ }
+
+ /**
+ * Reads the additional property sets from the read in compound file
+ *
+ * @return the number of blocks needed to store these property sets
+ */
+ private void readAdditionalPropertySets
+ (jxl.read.biff.CompoundFile readCompoundFile)
+ throws CopyAdditionalPropertySetsException, IOException
+ {
+ if (readCompoundFile == null)
+ {
+ return;
+ }
+
+ additionalPropertySets = new ArrayList();
+ readPropertySets = new HashMap();
+
+ String[] psnames = readCompoundFile.getPropertySetNames();
+ int blocksRequired = 0;
+ standardPropertySetMappings = new int[STANDARD_PROPERTY_SETS.length];
+
+ for (int i = 0 ; i < psnames.length ; i++)
+ {
+ // Add it to the hash map for later
+ PropertyStorage ps = readCompoundFile.getPropertySet(psnames[i]);
+
+ // If the name is non standard, then retrieve the property set
+ // information
+ boolean standard = false;
+ for (int j = 0 ; j < STANDARD_PROPERTY_SETS.length && !standard ; j++)
+ {
+ if (psnames[i].equalsIgnoreCase(STANDARD_PROPERTY_SETS[j]))
+ {
+ standard = true;
+ ReadPropertyStorage rps = new ReadPropertyStorage(ps, null, i);
+ readPropertySets.put(psnames[i], rps);
+ }
+ }
+
+ if (!standard)
+ {
+ try
+ {
+ byte[] data = null;
+ if (ps.size > 0 )
+ {
+ data = readCompoundFile.getStream(ps.name);
+ }
+ else
+ {
+ data = new byte[0];
+ }
+ ReadPropertyStorage rps = new ReadPropertyStorage(ps, data, i);
+ readPropertySets.put(psnames[i], rps);
+ additionalPropertySets.add(rps);
+
+ if (data.length > SMALL_BLOCK_THRESHOLD)
+ {
+ int blocks = getBigBlocksRequired(data.length);
+ blocksRequired += blocks;
+ }
+ else
+ {
+ int blocks = getSmallBlocksRequired(data.length);
+ numSmallBlocks += blocks;
+ }
+ }
+ catch (BiffException e)
+ {
+ logger.error(e);
+ throw new CopyAdditionalPropertySetsException();
+ }
+ }
+ }
+
+ additionalPropertyBlocks = blocksRequired;
+ }
+
+
+ /**
+ * Writes out the excel file in OLE compound file format
+ *
+ * @exception IOException
+ */
+ public void write() throws IOException
+ {
+ writeHeader();
+ writeExcelData();
+ writeDocumentSummaryData();
+ writeSummaryData();
+ writeAdditionalPropertySets();
+ writeSmallBlockDepot();
+ writeSmallBlockDepotChain();
+ writeBigBlockDepot();
+ writePropertySets();
+
+ // Don't flush or close the stream - this is handled by the enclosing File
+ // object
+ }
+
+ /**
+ * Writes out any additional property sets
+ */
+ private void writeAdditionalPropertySets() throws IOException
+ {
+ if (additionalPropertySets == null)
+ {
+ return;
+ }
+
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ;)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+ byte[] data = rps.data;
+
+ if (data.length > SMALL_BLOCK_THRESHOLD)
+ {
+ logger.debug("Writing big block chain for property set " + rps.propertyStorage.name);
+ int numBlocks = getBigBlocksRequired(data.length);
+ int requiredSize = numBlocks * BIG_BLOCK_SIZE;
+
+ out.write(data, 0, data.length);
+
+ byte[] padding = new byte[requiredSize - data.length];
+ out.write(padding, 0, padding.length);
+ }
+ }
+ }
+
+ /**
+ * Writes out the excel data, padding it out with empty bytes as
+ * necessary
+ * Also write out empty
+ *
+ * @exception IOException
+ */
+ private void writeExcelData() throws IOException
+ {
+ logger.debug("num excel data blocks " + excelDataBlocks + " excelData size " + requiredSize);
+ out.write(excelData, 0, size);
+
+ byte[] padding = new byte[requiredSize - size];
+ out.write(padding);
+ }
+
+ /**
+ * Write out the document summary data. This is just blank
+ *
+ * @exception IOException
+ */
+ private void writeDocumentSummaryData() throws IOException
+ {
+ byte[] padding = new byte[SMALL_BLOCK_THRESHOLD];
+
+ // Write out the summary information
+ out.write(padding);
+ }
+
+ /**
+ * Write out the summary data. This is just blank
+ *
+ * @exception IOException
+ */
+ private void writeSummaryData() throws IOException
+ {
+ byte[] padding = new byte[SMALL_BLOCK_THRESHOLD];
+
+ // Write out the summary information
+ out.write(padding);
+ }
+
+ /**
+ * Writes the compound file header
+ *
+ * @exception IOException
+ */
+ private void writeHeader() throws IOException
+ {
+ logger.debug("num extensions blocks for header: " + numExtensionBlocks);
+ // Build up the header array
+ byte[] headerBlock = new byte[BIG_BLOCK_SIZE];
+ byte[] extensionBlockData = new byte[BIG_BLOCK_SIZE * numExtensionBlocks];
+
+ // Copy in the identifier
+ System.arraycopy(IDENTIFIER, 0, headerBlock, 0, IDENTIFIER.length);
+
+ // Copy in some magic values - no idea what they mean
+ headerBlock[0x18] = 0x3e;
+ headerBlock[0x1a] = 0x3;
+ headerBlock[0x1c] = (byte) 0xfe;
+ headerBlock[0x1d] = (byte) 0xff;
+ headerBlock[0x1e] = 0x9;
+ headerBlock[0x20] = 0x6;
+ headerBlock[0x39] = 0x10;
+
+ // Set the number of BBD blocks
+ IntegerHelper.getFourBytes(numBigBlockDepotBlocks,
+ headerBlock,
+ NUM_BIG_BLOCK_DEPOT_BLOCKS_POS);
+
+ // Set the small block depot chain
+ IntegerHelper.getFourBytes(sbdStartBlockChain,
+ headerBlock,
+ SMALL_BLOCK_DEPOT_BLOCK_POS);
+
+ // Set the number of blocks in the small block depot chain
+ logger.debug("numSmallBlockDepotChainBlocks " + numSmallBlockDepotChainBlocks);
+ IntegerHelper.getFourBytes(numSmallBlockDepotChainBlocks,
+ headerBlock,
+ NUM_SMALL_BLOCK_DEPOT_BLOCKS_POS);
+
+ // Set the extension block
+ IntegerHelper.getFourBytes(extensionBlock,
+ headerBlock,
+ EXTENSION_BLOCK_POS);
+
+ // Set the number of extension blocks to be the number of BBD blocks - 1
+ IntegerHelper.getFourBytes(numExtensionBlocks,
+ headerBlock,
+ NUM_EXTENSION_BLOCK_POS);
+
+ // Set the root start block
+ IntegerHelper.getFourBytes(rootStartBlock,
+ headerBlock,
+ ROOT_START_BLOCK_POS);
+
+ // Set the block numbers for the BBD. Set the BBD running
+ // after the excel data and summary information
+ int pos = BIG_BLOCK_DEPOT_BLOCKS_POS;
+
+ // See how many blocks fit into the header
+ int blocksToWrite = Math.min(numBigBlockDepotBlocks,
+ (BIG_BLOCK_SIZE -
+ BIG_BLOCK_DEPOT_BLOCKS_POS)/4);
+ int extensionBlock = 0;
+ int blocksWritten = 0;
+
+ for (int i = 0 ; i < blocksToWrite; i++)
+ {
+ IntegerHelper.getFourBytes(bbdStartBlock + i,
+ headerBlock,
+ pos);
+ pos += 4;
+ blocksWritten++;
+ }
+
+ // Pad out the rest of the header with blanks
+ for (int i = pos; i < BIG_BLOCK_SIZE; i++)
+ {
+ headerBlock[i] = (byte) 0xff;
+ }
+
+ out.write(headerBlock);
+
+ // Write out the extension blocks
+ pos = 0;
+
+ for (int extBlock = 0; extBlock < numExtensionBlocks; extBlock++)
+ {
+ blocksToWrite = Math.min(numBigBlockDepotBlocks - blocksWritten,
+ BIG_BLOCK_SIZE/4 -1);
+
+ for(int j = 0 ; j < blocksToWrite; j++)
+ {
+ IntegerHelper.getFourBytes(bbdStartBlock + blocksWritten + j,
+ extensionBlockData,
+ pos);
+ pos += 4;
+ }
+
+ blocksWritten += blocksToWrite;
+
+ // Indicate the next block, or the termination of the chain
+ int nextBlock = (blocksWritten == numBigBlockDepotBlocks) ?
+ -2 : extBlock+1 ;
+ IntegerHelper.getFourBytes(nextBlock, extensionBlockData, pos);
+ pos +=4;
+ }
+
+ if (numExtensionBlocks > 0)
+ {
+ // Pad out the rest of the extension block with blanks
+ for (int i = pos; i < extensionBlockData.length; i++)
+ {
+ extensionBlockData[i] = (byte) 0xff;
+ }
+
+ out.write(extensionBlockData);
+ }
+ }
+
+ /**
+ * Checks that the data can fit into the current BBD block. If not,
+ * then it moves on to the next block
+ *
+ * @exception IOException
+ */
+ private void checkBbdPos() throws IOException
+ {
+ if (bbdPos >= BIG_BLOCK_SIZE)
+ {
+ // Write out the extension block. This will simply be the next block
+ out.write(bigBlockDepot);
+
+ // Create a new block
+ bigBlockDepot = new byte[BIG_BLOCK_SIZE];
+ bbdPos = 0;
+ }
+ }
+
+ /**
+ * Writes out the big block chain
+ *
+ * @param startBlock the starting block of the big block chain
+ * @param numBlocks the number of blocks in the chain
+ * @exception IOException
+ */
+ private void writeBlockChain(int startBlock, int numBlocks)
+ throws IOException
+ {
+ int blocksToWrite = numBlocks - 1;
+ int blockNumber = startBlock + 1;
+
+ while (blocksToWrite > 0)
+ {
+ int bbdBlocks = Math.min(blocksToWrite, (BIG_BLOCK_SIZE - bbdPos)/4);
+
+ for (int i = 0 ; i < bbdBlocks; i++)
+ {
+ IntegerHelper.getFourBytes(blockNumber, bigBlockDepot, bbdPos);
+ bbdPos +=4 ;
+ blockNumber++;
+ }
+
+ blocksToWrite -= bbdBlocks;
+ checkBbdPos();
+ }
+
+ // Write the end of the block chain
+ IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+ }
+
+ /**
+ * Writes the block chains for the additional property sets
+ *
+ * @exception IOException
+ */
+ private void writeAdditionalPropertySetBlockChains() throws IOException
+ {
+ if (additionalPropertySets == null)
+ {
+ return;
+ }
+
+ int blockNumber = excelDataStartBlock + excelDataBlocks;
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ; )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+ if (rps.data.length > SMALL_BLOCK_THRESHOLD)
+ {
+ String psname = rps.propertyStorage.name;
+ logger.debug("writing big block chain for " + psname);
+ int numBlocks = getBigBlocksRequired(rps.data.length);
+ writeBlockChain(blockNumber, numBlocks);
+ blockNumber += numBlocks;
+ }
+ }
+ }
+
+ /**
+ * Writes out the chains for the small block depot
+ */
+ private void writeSmallBlockDepotChain() throws IOException
+ {
+ if (sbdStartBlockChain == -2)
+ {
+ return;
+ }
+
+ byte[] smallBlockDepotChain =
+ new byte[numSmallBlockDepotChainBlocks * BIG_BLOCK_SIZE];
+
+ int pos = 0;
+ int sbdBlockNumber = 1;
+
+ /*
+ // First write out the small block chain for the standard property storage
+ for (int i = 0 ; i < additionalPropertySets.size() + 4; i++)
+ {
+ IntegerHelper.getFourBytes(sbdBlockNumber,
+ smallBlockDepotChain,
+ pos);
+ pos += 4;
+ sbdBlockNumber++;
+ }
+ */
+
+ /*
+ int numSmallBlocks2 = getSmallBlocksRequired(rootEntryPropertySet.data.length);
+ for (int j = 0 ; j < numSmallBlocks2 - 1 ; j++)
+ {
+ IntegerHelper.getFourBytes(sbdBlockNumber,
+ smallBlockDepotChain,
+ pos);
+ logger.debug("smallBlockChain["+(sbdBlockNumber-1)+"]: " + sbdBlockNumber + " pos " + pos);
+ pos += 4;
+ sbdBlockNumber++;
+ }
+ */
+
+ // Write out the end of chain
+ logger.debug("smallBlockChain["+(sbdBlockNumber-1)+"]: -2");
+ IntegerHelper.getFourBytes(-2, smallBlockDepotChain, pos);
+ pos += 4;
+ sbdBlockNumber++;
+
+
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ; )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+
+ if (rps.data.length <= SMALL_BLOCK_THRESHOLD &&
+ rps.data.length != 0)
+ {
+ int numSmallBlocks = getSmallBlocksRequired(rps.data.length);
+ for (int j = 0 ; j < numSmallBlocks - 1 ; j++)
+ {
+ IntegerHelper.getFourBytes(sbdBlockNumber,
+ smallBlockDepotChain,
+ pos);
+ logger.debug("smallBlockChain["+(sbdBlockNumber-1)+"]: " + sbdBlockNumber + " pos " + pos);
+ pos += 4;
+ sbdBlockNumber++;
+ }
+
+ // Write out the end of chain
+ logger.debug("smallBlockChain["+(sbdBlockNumber-1)+"]: -2");
+ IntegerHelper.getFourBytes(-2, smallBlockDepotChain, pos);
+ pos += 4;
+ sbdBlockNumber++;
+ }
+ }
+
+ out.write(smallBlockDepotChain);
+ }
+
+ /**
+ * Writes out all the data in the small block depot
+ *
+ * @exception
+ */
+ private void writeSmallBlockDepot() throws IOException
+ {
+ if (additionalPropertySets == null)
+ {
+ return;
+ }
+
+ byte[] smallBlockDepot =
+ new byte[numSmallBlockDepotBlocks * BIG_BLOCK_SIZE];
+
+ int pos = 0;
+
+ /*
+ int smallBlocks2 = getSmallBlocksRequired(rootEntryPropertySet.data.length);
+ int length2 = smallBlocks2 * SMALL_BLOCK_SIZE;
+ System.arraycopy(rootEntryPropertySet.data, 0, smallBlockDepot, pos, rootEntryPropertySet.data.length);
+ pos += length2;
+ */
+
+ for (Iterator i = additionalPropertySets.iterator() ; i.hasNext() ; )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+
+ if (rps.data.length <= SMALL_BLOCK_THRESHOLD)
+ {
+ int smallBlocks = getSmallBlocksRequired(rps.data.length);
+ int length = smallBlocks * SMALL_BLOCK_SIZE;
+ System.arraycopy(rps.data, 0, smallBlockDepot, pos, rps.data.length);
+ pos += length;
+ }
+ }
+
+ out.write(smallBlockDepot);
+ }
+
+ /**
+ * Writes out the Big Block Depot
+ *
+ * @exception IOException
+ */
+ private void writeBigBlockDepot() throws IOException
+ {
+ // This is after the excel data, the summary information, the
+ // big block property sets and the small block depot
+ bigBlockDepot = new byte[BIG_BLOCK_SIZE];
+ bbdPos = 0;
+
+ // Write out the extension blocks, indicating them as special blocks
+ for (int i = 0 ; i < numExtensionBlocks; i++)
+ {
+ IntegerHelper.getFourBytes(-3, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+ }
+
+ writeBlockChain(excelDataStartBlock, excelDataBlocks);
+
+ // The excel data has been written. Now write out the rest of it
+
+ // Write the block chain for the summary information
+ int summaryInfoBlock = excelDataStartBlock +
+ excelDataBlocks +
+ additionalPropertyBlocks;
+
+ for (int i = summaryInfoBlock; i < summaryInfoBlock + 7; i++)
+ {
+ IntegerHelper.getFourBytes(i + 1, bigBlockDepot, bbdPos);
+ bbdPos +=4 ;
+ checkBbdPos();
+ }
+
+ // Write the end of the block chain for the summary info block
+ IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+
+ // Write the block chain for the document summary information
+ for (int i = summaryInfoBlock + 8; i < summaryInfoBlock + 15; i++)
+ {
+ IntegerHelper.getFourBytes(i + 1, bigBlockDepot, bbdPos);
+ bbdPos +=4 ;
+ checkBbdPos();
+ }
+
+ // Write the end of the block chain for the document summary
+ IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+
+ // Write out the block chain for the copied property sets, if present
+ writeAdditionalPropertySetBlockChains();
+
+ // Write out the block chain for the small block depot
+ writeBlockChain(sbdStartBlock, numSmallBlockDepotBlocks);
+
+ // Write out the block chain for the small block depot chain
+ logger.debug("numSmallBlockDepotChainBlocks " + numSmallBlockDepotChainBlocks);
+ writeBlockChain(sbdStartBlockChain, numSmallBlockDepotChainBlocks);
+
+
+ // The Big Block Depot immediately follows the document summary. Denote
+ // these as a special block
+ for (int i = 0; i < numBigBlockDepotBlocks; i++)
+ {
+ IntegerHelper.getFourBytes(-3, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+ }
+
+ // Write the root entry
+ writeBlockChain(rootStartBlock, numRootEntryBlocks);
+
+ // Pad out the remainder of the block
+ if (bbdPos != 0)
+ {
+ for (int i = bbdPos; i < BIG_BLOCK_SIZE; i++)
+ {
+ bigBlockDepot[i] = (byte) 0xff;
+ }
+ out.write(bigBlockDepot);
+ }
+ }
+
+ /**
+ * Calculates the number of big blocks required to store data of the
+ * specified length
+ *
+ * @param length the length of the data
+ * @return the number of big blocks required to store the data
+ */
+ private int getBigBlocksRequired(int length)
+ {
+ int blocks = length / BIG_BLOCK_SIZE;
+
+ return (length % BIG_BLOCK_SIZE > 0 )? blocks + 1 : blocks;
+ }
+
+ /**
+ * Calculates the number of small blocks required to store data of the
+ * specified length
+ *
+ * @param length the length of the data
+ * @return the number of small blocks required to store the data
+ */
+ private int getSmallBlocksRequired(int length)
+ {
+ int blocks = length / SMALL_BLOCK_SIZE;
+
+ return (length % SMALL_BLOCK_SIZE > 0 )? blocks + 1 : blocks;
+ }
+
+ /**
+ * Writes out the property sets
+ *
+ * @exception IOException
+ */
+ private void writePropertySets() throws IOException
+ {
+ byte[] propertySetStorage = new byte[BIG_BLOCK_SIZE * numRootEntryBlocks];
+
+ int pos = 0;
+ int[] mappings = null;
+
+ // Build up the mappings array
+ if (additionalPropertySets != null)
+ {
+ mappings = new int[numPropertySets];
+
+ // Map the standard ones to the first four
+ for (int i = 0 ; i < STANDARD_PROPERTY_SETS.length ; i++)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ readPropertySets.get(STANDARD_PROPERTY_SETS[i]);
+ mappings[rps.number] = i;
+ }
+
+ // Now go through the original ones
+ int newMapping = STANDARD_PROPERTY_SETS.length;
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext(); )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+ mappings[rps.number] = newMapping;
+ newMapping++;
+ }
+ }
+
+ int dir = 0;
+ int previous = 0;
+ int next = 0;
+
+ // Compute the size of the root property set
+ int size = 0;
+
+ if (additionalPropertySets != null)
+ {
+ // Workbook
+ size += getBigBlocksRequired(requiredSize) * BIG_BLOCK_SIZE;
+
+ // The two information blocks
+ size += getBigBlocksRequired(SMALL_BLOCK_THRESHOLD) * BIG_BLOCK_SIZE;
+ size += getBigBlocksRequired(SMALL_BLOCK_THRESHOLD) * BIG_BLOCK_SIZE;
+
+ // Additional property sets
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext(); )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+ if (rps.propertyStorage.size >= SMALL_BLOCK_THRESHOLD)
+ {
+ size += getBigBlocksRequired(rps.propertyStorage.size) *
+ BIG_BLOCK_SIZE;
+ }
+ else
+ {
+ size += getSmallBlocksRequired(rps.propertyStorage.size) *
+ SMALL_BLOCK_SIZE;
+ }
+ }
+ }
+ logger.debug("Root entry size is " + size);
+
+ // Set the root entry property set
+ PropertyStorage ps = new PropertyStorage(ROOT_ENTRY_NAME);
+ ps.setType(5);
+ ps.setStartBlock(sbdStartBlock);
+ ps.setSize(size);
+ ps.setPrevious(-1);
+ ps.setNext(-1);
+ ps.setColour(0);
+
+ dir = 2;
+ if (additionalPropertySets != null)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ readPropertySets.get(ROOT_ENTRY_NAME);
+ dir = mappings[rps.propertyStorage.directory];
+ }
+ ps.setDirectory(dir);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+
+ // Set the workbook property set
+ ps = new PropertyStorage(WORKBOOK_NAME);
+ ps.setType(2);
+ ps.setStartBlock(excelDataStartBlock);
+ // start the excel data after immediately after this block
+ ps.setSize(requiredSize);
+ // alway use a big block stream - none of that messing around
+ // with small blocks
+
+ previous = 3;
+
+ if (additionalPropertySets != null)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ readPropertySets.get(WORKBOOK_NAME);
+ previous = mappings[rps.propertyStorage.previous];
+ }
+
+ ps.setPrevious(previous);
+ ps.setNext(-1);
+ ps.setDirectory(-1);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+ // Set the summary information
+ ps = new PropertyStorage(SUMMARY_INFORMATION_NAME);
+ ps.setType(2);
+ ps.setStartBlock(excelDataStartBlock + excelDataBlocks);
+ ps.setSize(SMALL_BLOCK_THRESHOLD);
+
+ previous = 1;
+ next = 3;
+
+ if (additionalPropertySets != null)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ readPropertySets.get(SUMMARY_INFORMATION_NAME);
+
+ previous = rps.propertyStorage.previous != - 1 ?
+ mappings[rps.propertyStorage.previous] : -1 ;
+ next = rps.propertyStorage.next != - 1 ?
+ mappings[rps.propertyStorage.next] : -1 ;
+ }
+
+ ps.setPrevious(previous);
+ ps.setNext(next);
+ ps.setDirectory(-1);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+ // Set the document summary information
+ ps = new PropertyStorage(DOCUMENT_SUMMARY_INFORMATION_NAME);
+ ps.setType(2);
+ ps.setStartBlock(excelDataStartBlock + excelDataBlocks + 8);
+ ps.setSize(SMALL_BLOCK_THRESHOLD);
+ ps.setPrevious(-1);
+ ps.setNext(-1);
+ ps.setDirectory(-1);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+
+
+ // Write out the additional property sets
+ if (additionalPropertySets == null)
+ {
+ out.write(propertySetStorage);
+ return;
+ }
+
+ int bigBlock = excelDataStartBlock + excelDataBlocks + 16;
+ int smallBlock = 0;//getSmallBlocksRequired(rootEntryPropertySet.data.length);
+ int sz = 0;
+
+ for (Iterator i = additionalPropertySets.iterator() ; i.hasNext(); )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+
+ int block = rps.data.length > SMALL_BLOCK_THRESHOLD ?
+ bigBlock : smallBlock;
+
+ ps = new PropertyStorage(rps.propertyStorage.name);
+ ps.setType(rps.propertyStorage.type);
+ ps.setStartBlock(block);
+ ps.setSize(rps.propertyStorage.size);
+ // ps.setColour(rps.propertyStorage.colour);
+
+ previous = rps.propertyStorage.previous != -1 ?
+ mappings[rps.propertyStorage.previous] : -1;
+ next = rps.propertyStorage.next != -1 ?
+ mappings[rps.propertyStorage.next] : -1;
+ dir = rps.propertyStorage.directory != -1 ?
+ mappings[rps.propertyStorage.directory] : -1;
+
+ ps.setPrevious(previous);
+ ps.setNext(next);
+ ps.setDirectory(dir);
+ logger.debug("ps.colour " + ps.colour);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+ if (rps.data.length > SMALL_BLOCK_THRESHOLD)
+ {
+ bigBlock += getBigBlocksRequired(rps.data.length);
+ }
+ else
+ {
+ smallBlock += getSmallBlocksRequired(rps.data.length);
+ }
+ sz += getSmallBlocksRequired(rps.propertyStorage.size);
+ }
+
+ out.write(propertySetStorage);
+ }
+}
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/CompoundFile.java3
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/CompoundFile.java3,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/CompoundFile.java3 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,1020 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.OutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.HashMap;
+
+import common.Assert;
+import common.Logger;
+import jxl.biff.BaseCompoundFile;
+import jxl.biff.IntegerHelper;
+import jxl.read.biff.BiffException;
+
+/**
+ * Writes out a compound file
+ *
+ * Header block is -1
+ * Excel data is e..n (where is the head extension blocks, normally 0 and
+ * n is at least 8)
+ * Summary information (8 blocks)
+ * Document summary (8 blocks)
+ * BBD is block p..q (where p=e+n+16 and q-p+1 is the number of BBD blocks)
+ * Property storage block is q+b...r (normally 1 block) (where b is the number
+ * of BBD blocks)
+ */
+final class CompoundFile extends BaseCompoundFile
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(CompoundFile.class);
+
+ /**
+ * The stream to which the jumbled up data is written to
+ */
+ private OutputStream out;
+ /**
+ * The organized biff records which form the actual excel data
+ */
+ private byte[] excelData;
+
+ /**
+ * The size of the array
+ */
+ private int size;
+
+ /**
+ * The size the excel data should be in order to comply with the
+ * general compound file format
+ */
+ private int requiredSize;
+
+ /**
+ * The number of blocks it takes to store the big block depot
+ */
+ private int numBigBlockDepotBlocks;
+
+ /**
+ * The number of blocks it takes to store the small block depot chain
+ */
+ private int numSmallBlockDepotChainBlocks;
+
+ /**
+ * The number of blocks it takes to store the small block depot
+ */
+ private int numSmallBlockDepotBlocks;
+
+ /**
+ * The number of extension blocks required for the header to describe
+ * the BBD
+ */
+ private int numExtensionBlocks;
+
+ /**
+ * The extension block for the header
+ */
+ private int extensionBlock;
+
+ /**
+ * The number of blocks it takes to store the excel data
+ */
+ private int excelDataBlocks;
+
+ /**
+ * The start block of the root entry
+ */
+ private int rootStartBlock;
+
+ /**
+ * The start block of the excel data
+ */
+ private int excelDataStartBlock;
+
+ /**
+ * The start block of the big block depot
+ */
+ private int bbdStartBlock;
+
+ /**
+ * The number of big blocks required for additional property sets
+ */
+ private int additionalPropertyBlocks;
+
+ /**
+ * The total number of property sets in this compound file
+ */
+ private int numPropertySets;
+
+ /**
+ * The number of blocks required to store the root entry property sets
+ * and small block depot
+ */
+ private int numRootEntryBlocks;
+
+ /**
+ * The list of additional, non standard property sets names
+ */
+ private ArrayList additionalPropertySets;
+
+ /**
+ * A hash map of the original property sets keyed on name
+ */
+ private HashMap readPropertySets;
+
+ /**
+ * The array of standard property set mappings
+ */
+ private int[] standardPropertySetMappings;
+
+ private ReadPropertyStorage rootEntryPropertySet;
+
+ /**
+ * Structure used to store the property set and the data
+ */
+ private static final class ReadPropertyStorage
+ {
+ PropertyStorage propertyStorage;
+ byte[] data;
+ int number;
+
+ ReadPropertyStorage(PropertyStorage ps, byte[] d, int n)
+ {
+ propertyStorage = ps;
+ data = d;
+ number = n;
+ }
+ }
+
+
+ // The following member variables are used across methods when
+ // writing out the big block depot
+ /**
+ * The current position within the bbd. Used when writing out the
+ * BBD
+ */
+ private int bbdPos;
+
+ /**
+ * The current bbd block
+ */
+ private byte[] bigBlockDepot;
+
+
+ /**
+ * Constructor
+ *
+ * @param l the length of the data
+ * @param os the output stream to write to
+ * @param data the excel data
+ * @param rcf the read compound
+ */
+ public CompoundFile(byte[] data, int l, OutputStream os,
+ jxl.read.biff.CompoundFile rcf)
+ throws CopyAdditionalPropertySetsException, IOException
+ {
+ super();
+ size = l;
+ excelData = data;
+
+ readAdditionalPropertySets(rcf);
+
+ numRootEntryBlocks = 1;
+ numPropertySets = 4 +
+ (additionalPropertySets != null ? additionalPropertySets.size() : 0);
+
+ if (additionalPropertySets != null)
+ {
+ try
+ {
+ rootEntryPropertySet = new ReadPropertyStorage(rcf.getPropertySet(ROOT_ENTRY_NAME), rcf.getStream(ROOT_ENTRY_NAME), 0);
+ int blocks = rootEntryPropertySet.data.length >= SMALL_BLOCK_THRESHOLD ?
+ getBigBlocksRequired(rootEntryPropertySet.data.length) :
+ SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE;
+ additionalPropertyBlocks += blocks;
+ }
+ catch(BiffException e)
+ {
+ e.printStackTrace();
+ }
+
+ numRootEntryBlocks += getBigBlocksRequired
+ (additionalPropertySets.size() * PROPERTY_STORAGE_BLOCK_SIZE);
+ }
+
+ logger.debug("root entry requires " + numRootEntryBlocks + " blocks");
+
+ int blocks = getBigBlocksRequired(l);
+
+ // First pad the data out so that it fits nicely into a whole number
+ // of blocks
+ if (l < SMALL_BLOCK_THRESHOLD)
+ {
+ requiredSize = SMALL_BLOCK_THRESHOLD;
+ }
+ else
+ {
+ requiredSize = blocks * BIG_BLOCK_SIZE;
+ }
+
+ out = os;
+
+ // logger.debug("smallBlockDepot requires " + numSmallBlockDepotBlocks + " big blocks");
+
+ // Do the calculations
+ excelDataBlocks = requiredSize/BIG_BLOCK_SIZE;
+ numBigBlockDepotBlocks = 1;
+
+ int blockChainLength = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4;
+
+ int startTotalBlocks = excelDataBlocks +
+ 8 + // summary block
+ 8 + // document information
+ additionalPropertyBlocks +
+ numRootEntryBlocks;
+
+ int totalBlocks = startTotalBlocks + numBigBlockDepotBlocks;
+
+ // Calculate the number of BBD blocks needed to hold this info
+ numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks /
+ (double) (BIG_BLOCK_SIZE/4));
+
+ // Does this affect the total?
+ totalBlocks = startTotalBlocks + numBigBlockDepotBlocks;
+
+ // And recalculate
+ numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks /
+ (double) (BIG_BLOCK_SIZE/4));
+
+ // Does this affect the total?
+ totalBlocks = startTotalBlocks + numBigBlockDepotBlocks;
+
+ // See if the excel bbd chain can fit into the header block.
+ // Remember to allow for the end of chain indicator
+ if (numBigBlockDepotBlocks > blockChainLength - 1 )
+ {
+ // Sod it - we need an extension block. We have to go through
+ // the whole tiresome calculation again
+ extensionBlock = 0;
+
+ // Compute the number of extension blocks
+ int bbdBlocksLeft = numBigBlockDepotBlocks - blockChainLength + 1;
+
+ numExtensionBlocks = (int) Math.ceil((double) bbdBlocksLeft /
+ (double) (BIG_BLOCK_SIZE/4 - 1));
+
+ // Modify the total number of blocks required and recalculate the
+ // the number of bbd blocks
+ totalBlocks = startTotalBlocks +
+ numExtensionBlocks +
+ numBigBlockDepotBlocks;
+ numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks /
+ (double) (BIG_BLOCK_SIZE/4));
+
+ // The final total
+ totalBlocks = startTotalBlocks +
+ numExtensionBlocks +
+ numBigBlockDepotBlocks;
+ }
+ else
+ {
+ extensionBlock = -2;
+ numExtensionBlocks = 0;
+ }
+
+ // Set the excel data start block to be after the header (and
+ // its extensions)
+ excelDataStartBlock = numExtensionBlocks;
+
+ logger.debug("excelDataStartBlock " + excelDataStartBlock);
+
+ // Set the bbd start block to be after all the excel data
+ bbdStartBlock = excelDataStartBlock +
+ excelDataBlocks +
+ additionalPropertyBlocks +
+ 16;
+
+ logger.debug("bbdStartBlock " + bbdStartBlock);
+
+ // Set the root start block to be after all the big block depot blocks
+ rootStartBlock = bbdStartBlock +
+ numBigBlockDepotBlocks;
+
+
+ if (totalBlocks != rootStartBlock + numRootEntryBlocks)
+ {
+ logger.warn("Root start block and total blocks are inconsistent " +
+ " generated file may be corrupt");
+ logger.warn("RootStartBlock " + rootStartBlock + " totalBlocks " + totalBlocks);
+ }
+ }
+
+ /**
+ * Reads the additional property sets from the read in compound file
+ *
+ * @return the number of blocks needed to store these property sets
+ */
+ private void readAdditionalPropertySets
+ (jxl.read.biff.CompoundFile readCompoundFile)
+ throws CopyAdditionalPropertySetsException, IOException
+ {
+ if (readCompoundFile == null)
+ {
+ return;
+ }
+
+ additionalPropertySets = new ArrayList();
+ readPropertySets = new HashMap();
+
+ String[] psnames = readCompoundFile.getPropertySetNames();
+ int blocksRequired = 0;
+ standardPropertySetMappings = new int[STANDARD_PROPERTY_SETS.length];
+
+ for (int i = 0 ; i < psnames.length ; i++)
+ {
+ // Add it to the hash map for later
+ PropertyStorage ps = readCompoundFile.getPropertySet(psnames[i]);
+
+ // If the name is non standard, then retrieve the property set
+ // information
+ boolean standard = false;
+ for (int j = 0 ; j < STANDARD_PROPERTY_SETS.length && !standard ; j++)
+ {
+ if (psnames[i].equalsIgnoreCase(STANDARD_PROPERTY_SETS[j]))
+ {
+ standard = true;
+ ReadPropertyStorage rps = new ReadPropertyStorage(ps, null, i);
+ readPropertySets.put(psnames[i], rps);
+ }
+ }
+
+ if (!standard)
+ {
+ try
+ {
+ byte[] data = null;
+ if (ps.size > 0 )
+ {
+ data = readCompoundFile.getStream(ps.name);
+ }
+ else
+ {
+ data = new byte[0];
+ }
+ ReadPropertyStorage rps = new ReadPropertyStorage(ps, data, i);
+ readPropertySets.put(psnames[i], rps);
+ additionalPropertySets.add(rps);
+
+ int blocks = data.length >= SMALL_BLOCK_THRESHOLD ?
+ getBigBlocksRequired(data.length) :
+ SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE;
+ blocksRequired += blocks;
+ }
+ catch (BiffException e)
+ {
+ logger.error(e);
+ throw new CopyAdditionalPropertySetsException();
+ }
+ }
+ }
+
+ additionalPropertyBlocks = blocksRequired;
+ }
+
+
+ /**
+ * Writes out the excel file in OLE compound file format
+ *
+ * @exception IOException
+ */
+ public void write() throws IOException
+ {
+ writeHeader();
+ writeExcelData();
+ writeDocumentSummaryData();
+ writeSummaryData();
+ writeAdditionalPropertySets();
+ writeBigBlockDepot();
+ writePropertySets();
+
+ // Don't flush or close the stream - this is handled by the enclosing File
+ // object
+ }
+
+ /**
+ * Writes out any additional property sets
+ */
+ private void writeAdditionalPropertySets() throws IOException
+ {
+ if (additionalPropertySets == null)
+ {
+ return;
+ }
+
+
+ logger.debug("Writing property set " + rootEntryPropertySet.propertyStorage.name);
+ int numBlocks2 = rootEntryPropertySet.data.length >= SMALL_BLOCK_THRESHOLD ?
+ getBigBlocksRequired(rootEntryPropertySet.data.length) :
+ SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE;
+ int requiredSize2 = numBlocks2 * BIG_BLOCK_SIZE;
+
+ out.write(rootEntryPropertySet.data, 0, rootEntryPropertySet.data.length);
+
+ byte[] padding2 = new byte[requiredSize2 - rootEntryPropertySet.data.length];
+ out.write(padding2, 0, padding2.length);
+
+ logger.debug("data length " + rootEntryPropertySet.data.length + " Padding " + padding2.length);
+
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ;)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+ byte[] data = rps.data;
+
+ logger.debug("Writing property set " + rps.propertyStorage.name);
+ int numBlocks = data.length >= SMALL_BLOCK_THRESHOLD ?
+ getBigBlocksRequired(data.length) :
+ SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE;
+ int requiredSize = numBlocks * BIG_BLOCK_SIZE;
+
+ out.write(data, 0, data.length);
+
+ byte[] padding = new byte[requiredSize - data.length];
+ out.write(padding, 0, padding.length);
+ }
+ }
+
+ /**
+ * Writes out the excel data, padding it out with empty bytes as
+ * necessary
+ * Also write out empty
+ *
+ * @exception IOException
+ */
+ private void writeExcelData() throws IOException
+ {
+ logger.debug("num excel data blocks " + excelDataBlocks + " excelData size " + requiredSize);
+ out.write(excelData, 0, size);
+
+ byte[] padding = new byte[requiredSize - size];
+ out.write(padding);
+ }
+
+ /**
+ * Write out the document summary data. This is just blank
+ *
+ * @exception IOException
+ */
+ private void writeDocumentSummaryData() throws IOException
+ {
+ byte[] padding = new byte[SMALL_BLOCK_THRESHOLD];
+
+ // Write out the summary information
+ out.write(padding);
+ }
+
+ /**
+ * Write out the summary data. This is just blank
+ *
+ * @exception IOException
+ */
+ private void writeSummaryData() throws IOException
+ {
+ byte[] padding = new byte[SMALL_BLOCK_THRESHOLD];
+
+ // Write out the summary information
+ out.write(padding);
+ }
+
+ /**
+ * Writes the compound file header
+ *
+ * @exception IOException
+ */
+ private void writeHeader() throws IOException
+ {
+ logger.debug("num extensions blocks for header: " + numExtensionBlocks);
+ // Build up the header array
+ byte[] headerBlock = new byte[BIG_BLOCK_SIZE];
+ byte[] extensionBlockData = new byte[BIG_BLOCK_SIZE * numExtensionBlocks];
+
+ // Copy in the identifier
+ System.arraycopy(IDENTIFIER, 0, headerBlock, 0, IDENTIFIER.length);
+
+ // Copy in some magic values - no idea what they mean
+ headerBlock[0x18] = 0x3e;
+ headerBlock[0x1a] = 0x3;
+ headerBlock[0x1c] = (byte) 0xfe;
+ headerBlock[0x1d] = (byte) 0xff;
+ headerBlock[0x1e] = 0x9;
+ headerBlock[0x20] = 0x6;
+ headerBlock[0x39] = 0x10;
+
+ // Set the number of BBD blocks
+ IntegerHelper.getFourBytes(numBigBlockDepotBlocks,
+ headerBlock,
+ NUM_BIG_BLOCK_DEPOT_BLOCKS_POS);
+
+ // Set the small block depot chain to -2 ie. no small block chain
+ IntegerHelper.getFourBytes(-2,
+ headerBlock,
+ SMALL_BLOCK_DEPOT_BLOCK_POS);
+
+ // Set the extension block
+ IntegerHelper.getFourBytes(extensionBlock,
+ headerBlock,
+ EXTENSION_BLOCK_POS);
+
+ // Set the number of extension blocks to be the number of BBD blocks - 1
+ IntegerHelper.getFourBytes(numExtensionBlocks,
+ headerBlock,
+ NUM_EXTENSION_BLOCK_POS);
+
+ // Set the root start block
+ IntegerHelper.getFourBytes(rootStartBlock,
+ headerBlock,
+ ROOT_START_BLOCK_POS);
+
+ // Set the block numbers for the BBD. Set the BBD running
+ // after the excel data and summary information
+ int pos = BIG_BLOCK_DEPOT_BLOCKS_POS;
+
+ // See how many blocks fit into the header
+ int blocksToWrite = Math.min(numBigBlockDepotBlocks,
+ (BIG_BLOCK_SIZE -
+ BIG_BLOCK_DEPOT_BLOCKS_POS)/4);
+ int extensionBlock = 0;
+ int blocksWritten = 0;
+
+ for (int i = 0 ; i < blocksToWrite; i++)
+ {
+ IntegerHelper.getFourBytes(bbdStartBlock + i,
+ headerBlock,
+ pos);
+ pos += 4;
+ blocksWritten++;
+ }
+
+ // Pad out the rest of the header with blanks
+ for (int i = pos; i < BIG_BLOCK_SIZE; i++)
+ {
+ headerBlock[i] = (byte) 0xff;
+ }
+
+ out.write(headerBlock);
+
+ // Write out the extension blocks
+ pos = 0;
+
+ for (int extBlock = 0; extBlock < numExtensionBlocks; extBlock++)
+ {
+ blocksToWrite = Math.min(numBigBlockDepotBlocks - blocksWritten,
+ BIG_BLOCK_SIZE/4 -1);
+
+ for(int j = 0 ; j < blocksToWrite; j++)
+ {
+ IntegerHelper.getFourBytes(bbdStartBlock + blocksWritten + j,
+ extensionBlockData,
+ pos);
+ pos += 4;
+ }
+
+ blocksWritten += blocksToWrite;
+
+ // Indicate the next block, or the termination of the chain
+ int nextBlock = (blocksWritten == numBigBlockDepotBlocks) ?
+ -2 : extBlock+1 ;
+ IntegerHelper.getFourBytes(nextBlock, extensionBlockData, pos);
+ pos +=4;
+ }
+
+ if (numExtensionBlocks > 0)
+ {
+ // Pad out the rest of the extension block with blanks
+ for (int i = pos; i < extensionBlockData.length; i++)
+ {
+ extensionBlockData[i] = (byte) 0xff;
+ }
+
+ out.write(extensionBlockData);
+ }
+ }
+
+ /**
+ * Checks that the data can fit into the current BBD block. If not,
+ * then it moves on to the next block
+ *
+ * @exception IOException
+ */
+ private void checkBbdPos() throws IOException
+ {
+ if (bbdPos >= BIG_BLOCK_SIZE)
+ {
+ // Write out the extension block. This will simply be the next block
+ out.write(bigBlockDepot);
+
+ // Create a new block
+ bigBlockDepot = new byte[BIG_BLOCK_SIZE];
+ bbdPos = 0;
+ }
+ }
+
+ /**
+ * Writes out the big block chain
+ *
+ * @param startBlock the starting block of the big block chain
+ * @param numBlocks the number of blocks in the chain
+ * @exception IOException
+ */
+ private void writeBlockChain(int startBlock, int numBlocks)
+ throws IOException
+ {
+ int blocksToWrite = numBlocks - 1;
+ int blockNumber = startBlock + 1;
+
+ while (blocksToWrite > 0)
+ {
+ int bbdBlocks = Math.min(blocksToWrite, (BIG_BLOCK_SIZE - bbdPos)/4);
+
+ for (int i = 0 ; i < bbdBlocks; i++)
+ {
+ IntegerHelper.getFourBytes(blockNumber, bigBlockDepot, bbdPos);
+ bbdPos +=4 ;
+ blockNumber++;
+ }
+
+ blocksToWrite -= bbdBlocks;
+ checkBbdPos();
+ }
+
+ // Write the end of the block chain
+ IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+ }
+
+ /**
+ * Writes the block chains for the additional property sets
+ *
+ * @exception IOException
+ */
+ private void writeAdditionalPropertySetBlockChains() throws IOException
+ {
+ if (additionalPropertySets == null)
+ {
+ return;
+ }
+
+ int blockNumber = excelDataStartBlock + excelDataBlocks + 16;
+
+ int numBlocks2 = rootEntryPropertySet.data.length >= SMALL_BLOCK_THRESHOLD ?
+ getBigBlocksRequired(rootEntryPropertySet.data.length) :
+ SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE;
+
+ String psname2 = rootEntryPropertySet.propertyStorage.name;
+ logger.debug("writing big block chain for " + psname2 + " block " + blockNumber + " numBlocks " + numBlocks2);
+ writeBlockChain(blockNumber, numBlocks2);
+ blockNumber += numBlocks2;
+
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ; )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+
+ int numBlocks = rps.data.length >= SMALL_BLOCK_THRESHOLD ?
+ getBigBlocksRequired(rps.data.length) :
+ SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE;
+
+ String psname = rps.propertyStorage.name;
+ logger.debug("writing big block chain for " + psname + " block " + blockNumber + " numBlocks " + numBlocks);
+ writeBlockChain(blockNumber, numBlocks);
+ blockNumber += numBlocks;
+ }
+ }
+
+ /**
+ * Writes out the Big Block Depot
+ *
+ * @exception IOException
+ */
+ private void writeBigBlockDepot() throws IOException
+ {
+ // This is after the excel data, the summary information, the
+ // big block property sets and the small block depot
+ bigBlockDepot = new byte[BIG_BLOCK_SIZE];
+ bbdPos = 0;
+
+ // Write out the extension blocks, indicating them as special blocks
+ for (int i = 0 ; i < numExtensionBlocks; i++)
+ {
+ IntegerHelper.getFourBytes(-3, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+ }
+
+ writeBlockChain(excelDataStartBlock, excelDataBlocks);
+
+ // The excel data has been written. Now write out the rest of it
+
+ // Write the block chain for the summary information
+ int summaryInfoBlock = excelDataStartBlock +
+ excelDataBlocks +
+ additionalPropertyBlocks;
+
+ for (int i = summaryInfoBlock; i < summaryInfoBlock + 7; i++)
+ {
+ IntegerHelper.getFourBytes(i + 1, bigBlockDepot, bbdPos);
+ bbdPos +=4 ;
+ checkBbdPos();
+ }
+
+ // Write the end of the block chain for the summary info block
+ IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+
+ // Write the block chain for the document summary information
+ for (int i = summaryInfoBlock + 8; i < summaryInfoBlock + 15; i++)
+ {
+ IntegerHelper.getFourBytes(i + 1, bigBlockDepot, bbdPos);
+ bbdPos +=4 ;
+ checkBbdPos();
+ }
+
+ // Write the end of the block chain for the document summary
+ IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+
+ // Write out the block chain for the copied property sets, if present
+ writeAdditionalPropertySetBlockChains();
+
+ // The Big Block Depot immediately follows the document summary. Denote
+ // these as a special block
+ for (int i = 0; i < numBigBlockDepotBlocks; i++)
+ {
+ IntegerHelper.getFourBytes(-3, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+ }
+
+ // Write the root entry
+ writeBlockChain(rootStartBlock, numRootEntryBlocks);
+
+ // Pad out the remainder of the block
+ if (bbdPos != 0)
+ {
+ for (int i = bbdPos; i < BIG_BLOCK_SIZE; i++)
+ {
+ bigBlockDepot[i] = (byte) 0xff;
+ }
+ out.write(bigBlockDepot);
+ }
+ }
+
+ /**
+ * Calculates the number of big blocks required to store data of the
+ * specified length
+ *
+ * @param length the length of the data
+ * @return the number of big blocks required to store the data
+ */
+ private int getBigBlocksRequired(int length)
+ {
+ int blocks = length / BIG_BLOCK_SIZE;
+
+ return (length % BIG_BLOCK_SIZE > 0 )? blocks + 1 : blocks;
+ }
+
+ /**
+ * Calculates the number of small blocks required to store data of the
+ * specified length
+ *
+ * @param length the length of the data
+ * @return the number of small blocks required to store the data
+ */
+ private int getSmallBlocksRequired(int length)
+ {
+ int blocks = length / SMALL_BLOCK_SIZE;
+
+ return (length % SMALL_BLOCK_SIZE > 0 )? blocks + 1 : blocks;
+ }
+
+ /**
+ * Writes out the property sets
+ *
+ * @exception IOException
+ */
+ private void writePropertySets() throws IOException
+ {
+ byte[] propertySetStorage = new byte[BIG_BLOCK_SIZE * numRootEntryBlocks];
+
+ int pos = 0;
+ int[] mappings = null;
+
+ // Build up the mappings array
+ if (additionalPropertySets != null)
+ {
+ mappings = new int[numPropertySets];
+
+ // Map the standard ones to the first four
+ for (int i = 0 ; i < STANDARD_PROPERTY_SETS.length ; i++)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ readPropertySets.get(STANDARD_PROPERTY_SETS[i]);
+ mappings[rps.number] = i;
+ }
+
+ // Now go through the original ones
+ int newMapping = STANDARD_PROPERTY_SETS.length;
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext(); )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+ mappings[rps.number] = newMapping;
+ newMapping++;
+ }
+ }
+
+ int dir = 0;
+ int previous = 0;
+ int next = 0;
+
+ // Set the root entry property set
+ PropertyStorage ps = new PropertyStorage(ROOT_ENTRY_NAME);
+ ps.setType(5);
+ ps.setStartBlock(-2);
+ ps.setSize(0);
+ ps.setPrevious(-1);
+ ps.setNext(-1);
+ ps.setColour(0);
+
+ dir = 2;
+ if (additionalPropertySets != null)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ readPropertySets.get(ROOT_ENTRY_NAME);
+ dir = mappings[rps.propertyStorage.directory];
+ }
+ ps.setDirectory(dir);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+
+ // Set the workbook property set
+ ps = new PropertyStorage(WORKBOOK_NAME);
+ ps.setType(2);
+ ps.setStartBlock(excelDataStartBlock);
+ // start the excel data after immediately after this block
+ ps.setSize(requiredSize);
+ // alway use a big block stream - none of that messing around
+ // with small blocks
+ ps.setColour(1);
+
+ previous = 3;
+
+ if (additionalPropertySets != null)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ readPropertySets.get(WORKBOOK_NAME);
+ previous = mappings[rps.propertyStorage.previous];
+ }
+
+ ps.setPrevious(previous);
+ ps.setNext(-1);
+ ps.setDirectory(-1);
+ ps.setColour(1);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+ // Set the summary information
+ ps = new PropertyStorage(SUMMARY_INFORMATION_NAME);
+ ps.setType(2);
+ ps.setStartBlock(excelDataStartBlock + excelDataBlocks);
+ ps.setSize(SMALL_BLOCK_THRESHOLD);
+ ps.setColour(1);
+
+ previous = 1;
+ next = 3;
+
+ if (additionalPropertySets != null)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ readPropertySets.get(SUMMARY_INFORMATION_NAME);
+
+ previous = rps.propertyStorage.previous != - 1 ?
+ mappings[rps.propertyStorage.previous] : -1 ;
+ next = rps.propertyStorage.next != - 1 ?
+ mappings[rps.propertyStorage.next] : -1 ;
+ }
+
+ ps.setPrevious(previous);
+ ps.setNext(next);
+ ps.setDirectory(-1);
+ ps.setColour(1);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+ // Set the document summary information
+ ps = new PropertyStorage(DOCUMENT_SUMMARY_INFORMATION_NAME);
+ ps.setType(2);
+ ps.setStartBlock(excelDataStartBlock + excelDataBlocks + 8);
+ ps.setSize(SMALL_BLOCK_THRESHOLD);
+ ps.setPrevious(-1);
+ ps.setNext(-1);
+ ps.setDirectory(-1);
+ ps.setColour(1);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+
+
+ // Write out the additional property sets
+ if (additionalPropertySets == null)
+ {
+ out.write(propertySetStorage);
+ return;
+ }
+
+ int bigBlock = excelDataStartBlock + excelDataBlocks + 16 +
+ 18;
+
+ for (Iterator i = additionalPropertySets.iterator() ; i.hasNext(); )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+
+ ps = new PropertyStorage(rps.propertyStorage.name);
+ ps.setType(rps.propertyStorage.type);
+ ps.setStartBlock(bigBlock);
+ ps.setSize(Math.max(rps.propertyStorage.size, SMALL_BLOCK_THRESHOLD));
+
+ previous = rps.propertyStorage.previous != -1 ?
+ mappings[rps.propertyStorage.previous] : -1;
+ next = rps.propertyStorage.next != -1 ?
+ mappings[rps.propertyStorage.next] : -1;
+ dir = rps.propertyStorage.directory != -1 ?
+ mappings[rps.propertyStorage.directory] : -1;
+
+ ps.setPrevious(previous);
+ ps.setNext(next);
+ ps.setDirectory(dir);
+ ps.setColour(1);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+
+ if (rps.data.length >= SMALL_BLOCK_THRESHOLD)
+ {
+ bigBlock += getBigBlocksRequired(rps.data.length);
+ }
+ else
+ {
+ bigBlock += SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE;
+ }
+ }
+
+ out.write(propertySetStorage);
+ }
+}
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/CompoundFile.java4
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/CompoundFile.java4,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/CompoundFile.java4 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,1025 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.OutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.HashMap;
+
+import common.Assert;
+import common.Logger;
+import jxl.biff.BaseCompoundFile;
+import jxl.biff.IntegerHelper;
+import jxl.read.biff.BiffException;
+
+/**
+ * Writes out a compound file
+ *
+ * Header block is -1
+ * Excel data is e..n (where is the head extension blocks, normally 0 and
+ * n is at least 8)
+ * Summary information (8 blocks)
+ * Document summary (8 blocks)
+ * BBD is block p..q (where p=e+n+16 and q-p+1 is the number of BBD blocks)
+ * Property storage block is q+b...r (normally 1 block) (where b is the number
+ * of BBD blocks)
+ */
+final class CompoundFile extends BaseCompoundFile
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(CompoundFile.class);
+
+ /**
+ * The stream to which the jumbled up data is written to
+ */
+ private OutputStream out;
+ /**
+ * The organized biff records which form the actual excel data
+ */
+ private byte[] excelData;
+
+ /**
+ * The size of the array
+ */
+ private int size;
+
+ /**
+ * The size the excel data should be in order to comply with the
+ * general compound file format
+ */
+ private int requiredSize;
+
+ /**
+ * The number of blocks it takes to store the big block depot
+ */
+ private int numBigBlockDepotBlocks;
+
+ /**
+ * The number of blocks it takes to store the small block depot chain
+ */
+ private int numSmallBlockDepotChainBlocks;
+
+ /**
+ * The number of blocks it takes to store the small block depot
+ */
+ private int numSmallBlockDepotBlocks;
+
+ /**
+ * The number of extension blocks required for the header to describe
+ * the BBD
+ */
+ private int numExtensionBlocks;
+
+ /**
+ * The extension block for the header
+ */
+ private int extensionBlock;
+
+ /**
+ * The number of blocks it takes to store the excel data
+ */
+ private int excelDataBlocks;
+
+ /**
+ * The start block of the root entry
+ */
+ private int rootStartBlock;
+
+ /**
+ * The start block of the excel data
+ */
+ private int excelDataStartBlock;
+
+ /**
+ * The start block of the big block depot
+ */
+ private int bbdStartBlock;
+
+ /**
+ * The number of big blocks required for additional property sets
+ */
+ private int additionalPropertyBlocks;
+
+ /**
+ * The total number of property sets in this compound file
+ */
+ private int numPropertySets;
+
+ /**
+ * The number of blocks required to store the root entry property sets
+ * and small block depot
+ */
+ private int numRootEntryBlocks;
+
+ /**
+ * The list of additional, non standard property sets names
+ */
+ private ArrayList additionalPropertySets;
+
+ /**
+ * A hash map of the original property sets keyed on name
+ */
+ private HashMap readPropertySets;
+
+ /**
+ * The array of standard property set mappings
+ */
+ private int[] standardPropertySetMappings;
+
+ private ReadPropertyStorage rootEntryPropertySet;
+
+ /**
+ * Structure used to store the property set and the data
+ */
+ private static final class ReadPropertyStorage
+ {
+ PropertyStorage propertyStorage;
+ byte[] data;
+ int number;
+
+ ReadPropertyStorage(PropertyStorage ps, byte[] d, int n)
+ {
+ propertyStorage = ps;
+ data = d;
+ number = n;
+ }
+ }
+
+
+ // The following member variables are used across methods when
+ // writing out the big block depot
+ /**
+ * The current position within the bbd. Used when writing out the
+ * BBD
+ */
+ private int bbdPos;
+
+ /**
+ * The current bbd block
+ */
+ private byte[] bigBlockDepot;
+
+
+ /**
+ * Constructor
+ *
+ * @param l the length of the data
+ * @param os the output stream to write to
+ * @param data the excel data
+ * @param rcf the read compound
+ */
+ public CompoundFile(byte[] data, int l, OutputStream os,
+ jxl.read.biff.CompoundFile rcf)
+ throws CopyAdditionalPropertySetsException, IOException
+ {
+ super();
+ size = l;
+ excelData = data;
+
+ readAdditionalPropertySets(rcf);
+
+ numRootEntryBlocks = 1;
+ numPropertySets = 4 +
+ (additionalPropertySets != null ? additionalPropertySets.size() : 0);
+
+ if (additionalPropertySets != null)
+ {
+ /*
+ try
+ {
+ rootEntryPropertySet = new ReadPropertyStorage(rcf.getPropertySet(ROOT_ENTRY_NAME), rcf.getStream(ROOT_ENTRY_NAME), 0);
+ int blocks = rootEntryPropertySet.data.length >= SMALL_BLOCK_THRESHOLD ?
+ getBigBlocksRequired(rootEntryPropertySet.data.length) :
+ SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE;
+ additionalPropertyBlocks += blocks;
+ }
+ catch(BiffException e)
+ {
+ e.printStackTrace();
+ }
+ */
+ numRootEntryBlocks += getBigBlocksRequired
+ (additionalPropertySets.size() * PROPERTY_STORAGE_BLOCK_SIZE);
+ }
+
+ logger.debug("root entry requires " + numRootEntryBlocks + " blocks");
+
+ int blocks = getBigBlocksRequired(l);
+
+ // First pad the data out so that it fits nicely into a whole number
+ // of blocks
+ if (l < SMALL_BLOCK_THRESHOLD)
+ {
+ requiredSize = SMALL_BLOCK_THRESHOLD;
+ }
+ else
+ {
+ requiredSize = blocks * BIG_BLOCK_SIZE;
+ }
+
+ out = os;
+
+ // logger.debug("smallBlockDepot requires " + numSmallBlockDepotBlocks + " big blocks");
+
+ // Do the calculations
+ excelDataBlocks = requiredSize/BIG_BLOCK_SIZE;
+ numBigBlockDepotBlocks = 1;
+
+ int blockChainLength = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4;
+
+ int startTotalBlocks = excelDataBlocks +
+ 8 + // summary block
+ 8 + // document information
+ additionalPropertyBlocks +
+ numRootEntryBlocks;
+
+ int totalBlocks = startTotalBlocks + numBigBlockDepotBlocks;
+
+ // Calculate the number of BBD blocks needed to hold this info
+ numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks /
+ (double) (BIG_BLOCK_SIZE/4));
+
+ // Does this affect the total?
+ totalBlocks = startTotalBlocks + numBigBlockDepotBlocks;
+
+ // And recalculate
+ numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks /
+ (double) (BIG_BLOCK_SIZE/4));
+
+ // Does this affect the total?
+ totalBlocks = startTotalBlocks + numBigBlockDepotBlocks;
+
+ // See if the excel bbd chain can fit into the header block.
+ // Remember to allow for the end of chain indicator
+ if (numBigBlockDepotBlocks > blockChainLength - 1 )
+ {
+ // Sod it - we need an extension block. We have to go through
+ // the whole tiresome calculation again
+ extensionBlock = 0;
+
+ // Compute the number of extension blocks
+ int bbdBlocksLeft = numBigBlockDepotBlocks - blockChainLength + 1;
+
+ numExtensionBlocks = (int) Math.ceil((double) bbdBlocksLeft /
+ (double) (BIG_BLOCK_SIZE/4 - 1));
+
+ // Modify the total number of blocks required and recalculate the
+ // the number of bbd blocks
+ totalBlocks = startTotalBlocks +
+ numExtensionBlocks +
+ numBigBlockDepotBlocks;
+ numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks /
+ (double) (BIG_BLOCK_SIZE/4));
+
+ // The final total
+ totalBlocks = startTotalBlocks +
+ numExtensionBlocks +
+ numBigBlockDepotBlocks;
+ }
+ else
+ {
+ extensionBlock = -2;
+ numExtensionBlocks = 0;
+ }
+
+ // Set the excel data start block to be after the header (and
+ // its extensions)
+ excelDataStartBlock = numExtensionBlocks;
+
+ logger.debug("excelDataStartBlock " + excelDataStartBlock);
+
+ // Set the bbd start block to be after all the excel data
+ bbdStartBlock = excelDataStartBlock +
+ excelDataBlocks +
+ additionalPropertyBlocks +
+ 16;
+
+ logger.debug("bbdStartBlock " + bbdStartBlock);
+
+ // Set the root start block to be after all the big block depot blocks
+ rootStartBlock = bbdStartBlock +
+ numBigBlockDepotBlocks;
+
+
+ if (totalBlocks != rootStartBlock + numRootEntryBlocks)
+ {
+ logger.warn("Root start block and total blocks are inconsistent " +
+ " generated file may be corrupt");
+ logger.warn("RootStartBlock " + rootStartBlock + " totalBlocks " + totalBlocks);
+ }
+ }
+
+ /**
+ * Reads the additional property sets from the read in compound file
+ *
+ * @return the number of blocks needed to store these property sets
+ */
+ private void readAdditionalPropertySets
+ (jxl.read.biff.CompoundFile readCompoundFile)
+ throws CopyAdditionalPropertySetsException, IOException
+ {
+ if (readCompoundFile == null)
+ {
+ return;
+ }
+
+ additionalPropertySets = new ArrayList();
+ readPropertySets = new HashMap();
+
+ String[] psnames = readCompoundFile.getPropertySetNames();
+ int blocksRequired = 0;
+ standardPropertySetMappings = new int[STANDARD_PROPERTY_SETS.length];
+
+ for (int i = 0 ; i < psnames.length ; i++)
+ {
+ // Add it to the hash map for later
+ PropertyStorage ps = readCompoundFile.getPropertySet(psnames[i]);
+
+ // If the name is non standard, then retrieve the property set
+ // information
+ boolean standard = false;
+ for (int j = 0 ; j < STANDARD_PROPERTY_SETS.length && !standard ; j++)
+ {
+ if (psnames[i].equalsIgnoreCase(STANDARD_PROPERTY_SETS[j]))
+ {
+ standard = true;
+ ReadPropertyStorage rps = new ReadPropertyStorage(ps, null, i);
+ readPropertySets.put(psnames[i], rps);
+ }
+ }
+
+ if (!standard)
+ {
+ try
+ {
+ byte[] data = null;
+ if (ps.size > 0 )
+ {
+ data = readCompoundFile.getStream(ps.name);
+ }
+ else
+ {
+ data = new byte[0];
+ }
+ ReadPropertyStorage rps = new ReadPropertyStorage(ps, data, i);
+ readPropertySets.put(psnames[i], rps);
+ additionalPropertySets.add(rps);
+
+ int blocks = data.length >= SMALL_BLOCK_THRESHOLD ?
+ getBigBlocksRequired(data.length) :
+ SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE;
+ blocksRequired += blocks;
+ }
+ catch (BiffException e)
+ {
+ logger.error(e);
+ throw new CopyAdditionalPropertySetsException();
+ }
+ }
+ }
+
+ additionalPropertyBlocks = blocksRequired;
+ }
+
+
+ /**
+ * Writes out the excel file in OLE compound file format
+ *
+ * @exception IOException
+ */
+ public void write() throws IOException
+ {
+ writeHeader();
+ writeExcelData();
+ writeDocumentSummaryData();
+ writeSummaryData();
+ writeAdditionalPropertySets();
+ writeBigBlockDepot();
+ writePropertySets();
+
+ // Don't flush or close the stream - this is handled by the enclosing File
+ // object
+ }
+
+ /**
+ * Writes out any additional property sets
+ */
+ private void writeAdditionalPropertySets() throws IOException
+ {
+ if (additionalPropertySets == null)
+ {
+ return;
+ }
+
+
+ /*
+ logger.debug("Writing property set " + rootEntryPropertySet.propertyStorage.name);
+ int numBlocks2 = rootEntryPropertySet.data.length >= SMALL_BLOCK_THRESHOLD ?
+ getBigBlocksRequired(rootEntryPropertySet.data.length) :
+ SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE;
+ int requiredSize2 = numBlocks2 * BIG_BLOCK_SIZE;
+
+ out.write(rootEntryPropertySet.data, 0, rootEntryPropertySet.data.length);
+
+ byte[] padding2 = new byte[requiredSize2 - rootEntryPropertySet.data.length];
+ out.write(padding2, 0, padding2.length);
+
+ logger.debug("data length " + rootEntryPropertySet.data.length + " Padding " + padding2.length);
+ */
+
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ;)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+ byte[] data = rps.data;
+
+ logger.debug("Writing property set " + rps.propertyStorage.name);
+ int numBlocks = data.length >= SMALL_BLOCK_THRESHOLD ?
+ getBigBlocksRequired(data.length) :
+ SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE;
+ int requiredSize = numBlocks * BIG_BLOCK_SIZE;
+
+ out.write(data, 0, data.length);
+
+ byte[] padding = new byte[requiredSize - data.length];
+ out.write(padding, 0, padding.length);
+ }
+ }
+
+ /**
+ * Writes out the excel data, padding it out with empty bytes as
+ * necessary
+ * Also write out empty
+ *
+ * @exception IOException
+ */
+ private void writeExcelData() throws IOException
+ {
+ logger.debug("num excel data blocks " + excelDataBlocks + " excelData size " + requiredSize);
+ out.write(excelData, 0, size);
+
+ byte[] padding = new byte[requiredSize - size];
+ out.write(padding);
+ }
+
+ /**
+ * Write out the document summary data. This is just blank
+ *
+ * @exception IOException
+ */
+ private void writeDocumentSummaryData() throws IOException
+ {
+ byte[] padding = new byte[SMALL_BLOCK_THRESHOLD];
+
+ // Write out the summary information
+ out.write(padding);
+ }
+
+ /**
+ * Write out the summary data. This is just blank
+ *
+ * @exception IOException
+ */
+ private void writeSummaryData() throws IOException
+ {
+ byte[] padding = new byte[SMALL_BLOCK_THRESHOLD];
+
+ // Write out the summary information
+ out.write(padding);
+ }
+
+ /**
+ * Writes the compound file header
+ *
+ * @exception IOException
+ */
+ private void writeHeader() throws IOException
+ {
+ logger.debug("num extensions blocks for header: " + numExtensionBlocks);
+ // Build up the header array
+ byte[] headerBlock = new byte[BIG_BLOCK_SIZE];
+ byte[] extensionBlockData = new byte[BIG_BLOCK_SIZE * numExtensionBlocks];
+
+ // Copy in the identifier
+ System.arraycopy(IDENTIFIER, 0, headerBlock, 0, IDENTIFIER.length);
+
+ // Copy in some magic values - no idea what they mean
+ headerBlock[0x18] = 0x3e;
+ headerBlock[0x1a] = 0x3;
+ headerBlock[0x1c] = (byte) 0xfe;
+ headerBlock[0x1d] = (byte) 0xff;
+ headerBlock[0x1e] = 0x9;
+ headerBlock[0x20] = 0x6;
+ headerBlock[0x39] = 0x10;
+
+ // Set the number of BBD blocks
+ IntegerHelper.getFourBytes(numBigBlockDepotBlocks,
+ headerBlock,
+ NUM_BIG_BLOCK_DEPOT_BLOCKS_POS);
+
+ // Set the small block depot chain to -2 ie. no small block chain
+ IntegerHelper.getFourBytes(-2,
+ headerBlock,
+ SMALL_BLOCK_DEPOT_BLOCK_POS);
+
+ // Set the extension block
+ IntegerHelper.getFourBytes(extensionBlock,
+ headerBlock,
+ EXTENSION_BLOCK_POS);
+
+ // Set the number of extension blocks to be the number of BBD blocks - 1
+ IntegerHelper.getFourBytes(numExtensionBlocks,
+ headerBlock,
+ NUM_EXTENSION_BLOCK_POS);
+
+ // Set the root start block
+ IntegerHelper.getFourBytes(rootStartBlock,
+ headerBlock,
+ ROOT_START_BLOCK_POS);
+
+ // Set the block numbers for the BBD. Set the BBD running
+ // after the excel data and summary information
+ int pos = BIG_BLOCK_DEPOT_BLOCKS_POS;
+
+ // See how many blocks fit into the header
+ int blocksToWrite = Math.min(numBigBlockDepotBlocks,
+ (BIG_BLOCK_SIZE -
+ BIG_BLOCK_DEPOT_BLOCKS_POS)/4);
+ int extensionBlock = 0;
+ int blocksWritten = 0;
+
+ for (int i = 0 ; i < blocksToWrite; i++)
+ {
+ IntegerHelper.getFourBytes(bbdStartBlock + i,
+ headerBlock,
+ pos);
+ pos += 4;
+ blocksWritten++;
+ }
+
+ // Pad out the rest of the header with blanks
+ for (int i = pos; i < BIG_BLOCK_SIZE; i++)
+ {
+ headerBlock[i] = (byte) 0xff;
+ }
+
+ out.write(headerBlock);
+
+ // Write out the extension blocks
+ pos = 0;
+
+ for (int extBlock = 0; extBlock < numExtensionBlocks; extBlock++)
+ {
+ blocksToWrite = Math.min(numBigBlockDepotBlocks - blocksWritten,
+ BIG_BLOCK_SIZE/4 -1);
+
+ for(int j = 0 ; j < blocksToWrite; j++)
+ {
+ IntegerHelper.getFourBytes(bbdStartBlock + blocksWritten + j,
+ extensionBlockData,
+ pos);
+ pos += 4;
+ }
+
+ blocksWritten += blocksToWrite;
+
+ // Indicate the next block, or the termination of the chain
+ int nextBlock = (blocksWritten == numBigBlockDepotBlocks) ?
+ -2 : extBlock+1 ;
+ IntegerHelper.getFourBytes(nextBlock, extensionBlockData, pos);
+ pos +=4;
+ }
+
+ if (numExtensionBlocks > 0)
+ {
+ // Pad out the rest of the extension block with blanks
+ for (int i = pos; i < extensionBlockData.length; i++)
+ {
+ extensionBlockData[i] = (byte) 0xff;
+ }
+
+ out.write(extensionBlockData);
+ }
+ }
+
+ /**
+ * Checks that the data can fit into the current BBD block. If not,
+ * then it moves on to the next block
+ *
+ * @exception IOException
+ */
+ private void checkBbdPos() throws IOException
+ {
+ if (bbdPos >= BIG_BLOCK_SIZE)
+ {
+ // Write out the extension block. This will simply be the next block
+ out.write(bigBlockDepot);
+
+ // Create a new block
+ bigBlockDepot = new byte[BIG_BLOCK_SIZE];
+ bbdPos = 0;
+ }
+ }
+
+ /**
+ * Writes out the big block chain
+ *
+ * @param startBlock the starting block of the big block chain
+ * @param numBlocks the number of blocks in the chain
+ * @exception IOException
+ */
+ private void writeBlockChain(int startBlock, int numBlocks)
+ throws IOException
+ {
+ int blocksToWrite = numBlocks - 1;
+ int blockNumber = startBlock + 1;
+
+ while (blocksToWrite > 0)
+ {
+ int bbdBlocks = Math.min(blocksToWrite, (BIG_BLOCK_SIZE - bbdPos)/4);
+
+ for (int i = 0 ; i < bbdBlocks; i++)
+ {
+ IntegerHelper.getFourBytes(blockNumber, bigBlockDepot, bbdPos);
+ bbdPos +=4 ;
+ blockNumber++;
+ }
+
+ blocksToWrite -= bbdBlocks;
+ checkBbdPos();
+ }
+
+ // Write the end of the block chain
+ IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+ }
+
+ /**
+ * Writes the block chains for the additional property sets
+ *
+ * @exception IOException
+ */
+ private void writeAdditionalPropertySetBlockChains() throws IOException
+ {
+ if (additionalPropertySets == null)
+ {
+ return;
+ }
+
+ int blockNumber = excelDataStartBlock + excelDataBlocks + 16;
+
+ /*
+ int numBlocks2 = rootEntryPropertySet.data.length >= SMALL_BLOCK_THRESHOLD ?
+ getBigBlocksRequired(rootEntryPropertySet.data.length) :
+ SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE;
+
+ String psname2 = rootEntryPropertySet.propertyStorage.name;
+ logger.debug("writing big block chain for " + psname2 + " block " + blockNumber + " numBlocks " + numBlocks2);
+ writeBlockChain(blockNumber, numBlocks2);
+ blockNumber += numBlocks2;
+ */
+
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ; )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+
+ int numBlocks = rps.data.length >= SMALL_BLOCK_THRESHOLD ?
+ getBigBlocksRequired(rps.data.length) :
+ SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE;
+
+ String psname = rps.propertyStorage.name;
+ logger.debug("writing big block chain for " + psname + " block " + blockNumber + " numBlocks " + numBlocks);
+ writeBlockChain(blockNumber, numBlocks);
+ blockNumber += numBlocks;
+ }
+ }
+
+ /**
+ * Writes out the Big Block Depot
+ *
+ * @exception IOException
+ */
+ private void writeBigBlockDepot() throws IOException
+ {
+ // This is after the excel data, the summary information, the
+ // big block property sets and the small block depot
+ bigBlockDepot = new byte[BIG_BLOCK_SIZE];
+ bbdPos = 0;
+
+ // Write out the extension blocks, indicating them as special blocks
+ for (int i = 0 ; i < numExtensionBlocks; i++)
+ {
+ IntegerHelper.getFourBytes(-3, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+ }
+
+ writeBlockChain(excelDataStartBlock, excelDataBlocks);
+
+ // The excel data has been written. Now write out the rest of it
+
+ // Write the block chain for the summary information
+ int summaryInfoBlock = excelDataStartBlock +
+ excelDataBlocks +
+ additionalPropertyBlocks;
+
+ for (int i = summaryInfoBlock; i < summaryInfoBlock + 7; i++)
+ {
+ IntegerHelper.getFourBytes(i + 1, bigBlockDepot, bbdPos);
+ bbdPos +=4 ;
+ checkBbdPos();
+ }
+
+ // Write the end of the block chain for the summary info block
+ IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+
+ // Write the block chain for the document summary information
+ for (int i = summaryInfoBlock + 8; i < summaryInfoBlock + 15; i++)
+ {
+ IntegerHelper.getFourBytes(i + 1, bigBlockDepot, bbdPos);
+ bbdPos +=4 ;
+ checkBbdPos();
+ }
+
+ // Write the end of the block chain for the document summary
+ IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+
+ // Write out the block chain for the copied property sets, if present
+ writeAdditionalPropertySetBlockChains();
+
+ // The Big Block Depot immediately follows the document summary. Denote
+ // these as a special block
+ for (int i = 0; i < numBigBlockDepotBlocks; i++)
+ {
+ IntegerHelper.getFourBytes(-3, bigBlockDepot, bbdPos);
+ bbdPos += 4;
+ checkBbdPos();
+ }
+
+ // Write the root entry
+ writeBlockChain(rootStartBlock, numRootEntryBlocks);
+
+ // Pad out the remainder of the block
+ if (bbdPos != 0)
+ {
+ for (int i = bbdPos; i < BIG_BLOCK_SIZE; i++)
+ {
+ bigBlockDepot[i] = (byte) 0xff;
+ }
+ out.write(bigBlockDepot);
+ }
+ }
+
+ /**
+ * Calculates the number of big blocks required to store data of the
+ * specified length
+ *
+ * @param length the length of the data
+ * @return the number of big blocks required to store the data
+ */
+ private int getBigBlocksRequired(int length)
+ {
+ int blocks = length / BIG_BLOCK_SIZE;
+
+ return (length % BIG_BLOCK_SIZE > 0 )? blocks + 1 : blocks;
+ }
+
+ /**
+ * Calculates the number of small blocks required to store data of the
+ * specified length
+ *
+ * @param length the length of the data
+ * @return the number of small blocks required to store the data
+ */
+ private int getSmallBlocksRequired(int length)
+ {
+ int blocks = length / SMALL_BLOCK_SIZE;
+
+ return (length % SMALL_BLOCK_SIZE > 0 )? blocks + 1 : blocks;
+ }
+
+ /**
+ * Writes out the property sets
+ *
+ * @exception IOException
+ */
+ private void writePropertySets() throws IOException
+ {
+ byte[] propertySetStorage = new byte[BIG_BLOCK_SIZE * numRootEntryBlocks];
+
+ int pos = 0;
+ int[] mappings = null;
+
+ // Build up the mappings array
+ if (additionalPropertySets != null)
+ {
+ mappings = new int[numPropertySets];
+
+ // Map the standard ones to the first four
+ for (int i = 0 ; i < STANDARD_PROPERTY_SETS.length ; i++)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ readPropertySets.get(STANDARD_PROPERTY_SETS[i]);
+ mappings[rps.number] = i;
+ }
+
+ // Now go through the original ones
+ int newMapping = STANDARD_PROPERTY_SETS.length;
+ for (Iterator i = additionalPropertySets.iterator(); i.hasNext(); )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+ mappings[rps.number] = newMapping;
+ newMapping++;
+ }
+ }
+
+ int dir = 0;
+ int previous = 0;
+ int next = 0;
+
+ // Set the root entry property set
+ PropertyStorage ps = new PropertyStorage(ROOT_ENTRY_NAME);
+ ps.setType(5);
+ ps.setStartBlock(-2);
+ ps.setSize(0);
+ ps.setPrevious(-1);
+ ps.setNext(-1);
+ ps.setColour(0);
+
+ dir = 2;
+ if (additionalPropertySets != null)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ readPropertySets.get(ROOT_ENTRY_NAME);
+ dir = mappings[rps.propertyStorage.directory];
+ }
+ ps.setDirectory(dir);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+
+ // Set the workbook property set
+ ps = new PropertyStorage(WORKBOOK_NAME);
+ ps.setType(2);
+ ps.setStartBlock(excelDataStartBlock);
+ // start the excel data after immediately after this block
+ ps.setSize(requiredSize);
+ // alway use a big block stream - none of that messing around
+ // with small blocks
+ ps.setColour(1);
+
+ previous = 3;
+
+ if (additionalPropertySets != null)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ readPropertySets.get(WORKBOOK_NAME);
+ previous = mappings[rps.propertyStorage.previous];
+ }
+
+ ps.setPrevious(previous);
+ ps.setNext(-1);
+ ps.setDirectory(-1);
+ // ps.setColour(1);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+ // Set the summary information
+ ps = new PropertyStorage(SUMMARY_INFORMATION_NAME);
+ ps.setType(2);
+ ps.setStartBlock(excelDataStartBlock + excelDataBlocks);
+ ps.setSize(SMALL_BLOCK_THRESHOLD);
+ // ps.setColour(1);
+
+ previous = 1;
+ next = 3;
+
+ if (additionalPropertySets != null)
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage)
+ readPropertySets.get(SUMMARY_INFORMATION_NAME);
+
+ previous = rps.propertyStorage.previous != - 1 ?
+ mappings[rps.propertyStorage.previous] : -1 ;
+ next = rps.propertyStorage.next != - 1 ?
+ mappings[rps.propertyStorage.next] : -1 ;
+ }
+
+ ps.setPrevious(previous);
+ ps.setNext(next);
+ ps.setDirectory(-1);
+ // ps.setColour(1);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+ // Set the document summary information
+ ps = new PropertyStorage(DOCUMENT_SUMMARY_INFORMATION_NAME);
+ ps.setType(2);
+ ps.setStartBlock(excelDataStartBlock + excelDataBlocks + 8);
+ ps.setSize(SMALL_BLOCK_THRESHOLD);
+ ps.setPrevious(-1);
+ ps.setNext(-1);
+ ps.setDirectory(-1);
+ // ps.setColour(1);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+
+
+ // Write out the additional property sets
+ if (additionalPropertySets == null)
+ {
+ out.write(propertySetStorage);
+ return;
+ }
+
+ int bigBlock = excelDataStartBlock + excelDataBlocks + 16 +
+ 18;
+
+ for (Iterator i = additionalPropertySets.iterator() ; i.hasNext(); )
+ {
+ ReadPropertyStorage rps = (ReadPropertyStorage) i.next();
+
+ ps = new PropertyStorage(rps.propertyStorage.name);
+ ps.setType(rps.propertyStorage.type);
+ ps.setStartBlock(bigBlock);
+ ps.setSize(Math.max(rps.propertyStorage.size, SMALL_BLOCK_THRESHOLD));
+
+ previous = rps.propertyStorage.previous != -1 ?
+ mappings[rps.propertyStorage.previous] : -1;
+ next = rps.propertyStorage.next != -1 ?
+ mappings[rps.propertyStorage.next] : -1;
+ dir = rps.propertyStorage.directory != -1 ?
+ mappings[rps.propertyStorage.directory] : -1;
+
+ ps.setPrevious(previous);
+ ps.setNext(next);
+ ps.setDirectory(dir);
+ // ps.setColour(1);
+
+ System.arraycopy(ps.data, 0,
+ propertySetStorage, pos,
+ PROPERTY_STORAGE_BLOCK_SIZE);
+ pos += PROPERTY_STORAGE_BLOCK_SIZE;
+
+
+ if (rps.data.length >= SMALL_BLOCK_THRESHOLD)
+ {
+ bigBlock += getBigBlocksRequired(rps.data.length);
+ }
+ else
+ {
+ bigBlock += SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE;
+ }
+ }
+
+ out.write(propertySetStorage);
+ }
+}
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/CopyAdditionalPropertySetsException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/CopyAdditionalPropertySetsException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/CopyAdditionalPropertySetsException.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,35 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+/**
+ * Exception thrown when attempting to copy a workbook which contains
+ * additional property sets
+ */
+public class CopyAdditionalPropertySetsException extends JxlWriteException
+{
+ /**
+ * Constructor
+ */
+ public CopyAdditionalPropertySetsException()
+ {
+ super(copyPropertySets);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/CountryRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/CountryRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/CountryRecord.java 17 Aug 2012 14:51:08 -0000 1.1
@@ -0,0 +1,84 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.CountryCode;
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+
+/**
+ * Record containing the localization information
+ */
+class CountryRecord extends WritableRecordData
+{
+ /**
+ * The user interface language
+ */
+ private int language;
+
+ /**
+ * The regional settings
+ */
+ private int regionalSettings;
+
+ /**
+ * Constructor
+ */
+ public CountryRecord(CountryCode lang, CountryCode r)
+ {
+ super(Type.COUNTRY);
+
+ language = lang.getValue();
+ regionalSettings = r.getValue();
+ }
+
+ public CountryRecord(jxl.read.biff.CountryRecord cr)
+ {
+ super(Type.COUNTRY);
+
+ language = cr.getLanguageCode();
+ regionalSettings = cr.getRegionalSettingsCode();
+ }
+
+ /**
+ * Retrieves the data to be written to the binary file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[4];
+
+ IntegerHelper.getTwoBytes(language, data, 0);
+ IntegerHelper.getTwoBytes(regionalSettings, data, 2);
+
+ return data;
+ }
+}
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/DBCellRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/DBCellRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/DBCellRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,124 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Indexes the first row record of the block and each individual cell.
+ * This is invoked by the sheets write process
+ */
+class DBCellRecord extends WritableRecordData
+{
+ /**
+ * The file position of the first Row record in this block
+ */
+ private int rowPos;
+
+ /**
+ * The position of the start of the next cell after the first row. This
+ * is used as the offset for the cell positions
+ */
+ private int cellOffset;
+
+ /**
+ * The list of all cell positions in this block
+ */
+ private ArrayList cellRowPositions;
+
+ /**
+ * The position of this record in the file. Vital for calculating offsets
+ */
+ private int position;
+
+ /**
+ * Constructor
+ *
+ * @param rp the position of this row
+ */
+ public DBCellRecord(int rp)
+ {
+ super(Type.DBCELL);
+ rowPos = rp;
+ cellRowPositions = new ArrayList(10);
+ }
+
+ /**
+ * Sets the offset of this cell record within the sheet stream
+ *
+ * @param pos the offset
+ */
+ void setCellOffset(int pos)
+ {
+ cellOffset = pos;
+ }
+
+ /**
+ * Adds a cell
+ *
+ * @param pos
+ */
+ void addCellRowPosition(int pos)
+ {
+ cellRowPositions.add(new Integer(pos));
+ }
+
+ /**
+ * Sets the position of this cell within the sheet stream
+ *
+ * @param pos the position
+ */
+ void setPosition(int pos)
+ {
+ position = pos;
+ }
+
+ /**
+ * Gets the binary data for this cell record
+ *
+ * @return the binary data
+ */
+ protected byte[] getData()
+ {
+ byte[] data = new byte[4 + 2 * cellRowPositions.size()];
+
+ // Set the offset to the first row
+ IntegerHelper.getFourBytes(position - rowPos, data, 0);
+
+ // Now add in all the cell offsets
+ int pos = 4;
+ int lastCellPos = cellOffset;
+ Iterator i = cellRowPositions.iterator();
+ while (i.hasNext())
+ {
+ int cellPos = ((Integer) i.next()).intValue();
+ IntegerHelper.getTwoBytes(cellPos - lastCellPos, data, pos);
+ lastCellPos = cellPos;
+ pos += 2;
+ }
+
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/DSFRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/DSFRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/DSFRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,57 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores a flag which indicates whether the file is a double stream
+ * file. For files written by JExcelAPI, this FALSE
+ */
+class DSFRecord extends WritableRecordData
+{
+ /**
+ * The data to be written to the binary file
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ */
+ public DSFRecord()
+ {
+ super(Type.DSF);
+
+ // Hard code the fact that this is most assuredly not a double
+ // stream file
+ data = new byte[] {0,0};
+ }
+
+ /**
+ * The binary data to be written out
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/DataValidation.java2
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/DataValidation.java2,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/DataValidation.java2 17 Aug 2012 14:51:08 -0000 1.1
@@ -0,0 +1,213 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+
+/**
+ * Class which encapsulates a data validation (typically in the form of a
+ * dropdown list box
+ */
+public class DataValidation
+{
+ /**
+ * The logger
+ */
+ private final static Logger logger = Logger.getLogger(DataValidation.class);
+
+ /**
+ * The data validity list
+ */
+ private DataValidityListRecord validityList;
+
+ /**
+ * The data validity record
+ */
+ private ArrayList validitySettings;
+
+ /**
+ * The current position in the validitySettins array
+ */
+ private int pos;
+
+ /**
+ * Handle to the workbook
+ */
+ private WritableWorkbookImpl workbook;
+
+ /**
+ * Handle to the workbook settings
+ */
+ private WorkbookSettings workbookSettings;
+
+ /**
+ * Constructor
+ *
+ * @param dv the data validations from the read only sheet
+ */
+ DataValidation(jxl.read.biff.DataValidation dv,
+ WritableWorkbookImpl w,
+ WorkbookSettings ws)
+ {
+ workbook = w;
+ workbookSettings = ws;
+ validityList = new DataValidityListRecord(dv.getDataValidityList());
+
+ jxl.read.biff.DataValiditySettingsRecord[] settings =
+ dv.getDataValiditySettings();
+
+ validitySettings = new ArrayList(settings.length);
+ for (int i = 0; i < settings.length ; i++)
+ {
+ validitySettings.add(new DataValiditySettingsRecord(settings[i],
+ workbook,
+ workbookSettings));
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param dv the data validations from the writable sheet
+ */
+ DataValidation(DataValidation dv,
+ WritableWorkbookImpl w,
+ WorkbookSettings ws)
+
+ {
+ workbook = w;
+ workbookSettings = ws;
+ validityList = new DataValidityListRecord(dv.validityList);
+
+ validitySettings = new ArrayList(dv.validitySettings.size());
+
+ for (Iterator i = dv.validitySettings.iterator(); i.hasNext(); )
+ {
+ DataValiditySettingsRecord dvsr = (DataValiditySettingsRecord) i.next();
+ validitySettings.add
+ (new DataValiditySettingsRecord(dvsr,
+ workbook,
+ workbookSettings));
+ }
+ }
+
+
+ /**
+ * Writes out the data validation
+ *
+ * @exception IOException
+ * @param outputFile the output file
+ */
+ public void write(File outputFile) throws IOException
+ {
+ if (!validityList.hasDVRecords())
+ {
+ return;
+ }
+
+ outputFile.write(validityList);
+
+ for (Iterator i = validitySettings.iterator(); i.hasNext() ; )
+ {
+ DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next();
+ outputFile.write(dv);
+ }
+ }
+
+ /**
+ * Inserts a row
+ *
+ * @param row the inserted row
+ */
+ public void insertRow(int row)
+ {
+ for (Iterator i = validitySettings.iterator(); i.hasNext() ; )
+ {
+ DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next();
+ dv.insertRow(row);
+ }
+ }
+
+ /**
+ * Inserts a row
+ *
+ * @param row the inserted row
+ */
+ public void removeRow(int row)
+ {
+ for (Iterator i = validitySettings.iterator(); i.hasNext() ; )
+ {
+ DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next();
+
+ if (dv.getFirstRow() == row && dv.getLastRow() == row)
+ {
+ i.remove();
+ validityList.dvRemoved();
+ }
+ else
+ {
+ dv.removeRow(row);
+ }
+ }
+ }
+
+ /**
+ * Inserts a column
+ *
+ * @param col the inserted column
+ */
+ public void insertColumn(int col)
+ {
+ for (Iterator i = validitySettings.iterator(); i.hasNext() ; )
+ {
+ DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next();
+ dv.insertColumn(col);
+ }
+ }
+
+ /**
+ * Removes a column
+ *
+ * @param col the inserted column
+ */
+ public void removeColumn(int col)
+ {
+ for (Iterator i = validitySettings.iterator(); i.hasNext() ; )
+ {
+ DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next();
+
+ if (dv.getFirstColumn() == col && dv.getLastColumn() == col)
+ {
+ i.remove();
+ validityList.dvRemoved();
+ }
+ else
+ {
+ dv.removeColumn(col);
+ }
+ }
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/DataValidityListRecord.java2
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/DataValidityListRecord.java2,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/DataValidityListRecord.java2 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,111 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.DValParser;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+
+/**
+ * Data validity settings
+ */
+class DataValidityListRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * The dval parser
+ */
+ private DValParser dvalParser;
+
+ /**
+ * Constructor
+ *
+ * @param dvlr the record copied from a read only sheet
+ */
+ DataValidityListRecord(jxl.read.biff.DataValidityListRecord dvlr)
+ {
+ super(Type.DVAL);
+
+ data = dvlr.getData();
+ }
+
+ /**
+ * Constructor
+ *
+ * @param dvlr the record copied from a writable sheet
+ */
+ DataValidityListRecord(DataValidityListRecord dvlr)
+ {
+ super(Type.DVAL);
+
+ data = new byte[dvlr.data.length];
+ System.arraycopy(dvlr.data, 0, data, 0, data.length);
+ }
+
+ /**
+ * Retrieves the data for output to binary file
+ *
+ * @return the data to be written
+ */
+ public byte[] getData()
+ {
+ if (dvalParser == null)
+ {
+ return data;
+ }
+
+ return dvalParser.getData();
+ }
+
+ /**
+ * Called when a remove row or column results in one of DV records being
+ * removed
+ */
+ void dvRemoved()
+ {
+ if (dvalParser == null)
+ {
+ dvalParser = new DValParser(data);
+ }
+
+ dvalParser.dvRemoved();
+ }
+
+ /**
+ * Accessor for the number of DV records
+ *
+ * @return the number of DV records for this list
+ */
+ public boolean hasDVRecords()
+ {
+ if (dvalParser == null)
+ {
+ return true;
+ }
+
+ return dvalParser.getNumberOfDVRecords() > 0;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/DataValiditySettingsRecord.java2
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/DataValiditySettingsRecord.java2,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/DataValiditySettingsRecord.java2 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,247 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.DVParser;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+import jxl.biff.formula.FormulaException;
+
+/**
+ * Data validity settings
+ */
+class DataValiditySettingsRecord extends WritableRecordData
+{
+ /**
+ * The logger
+ */
+ private static final Logger logger =
+ Logger.getLogger(DataValiditySettingsRecord.class);
+
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * The reader
+ */
+ private DVParser dvParser;
+
+ /**
+ * Handle to the workbook
+ */
+ private WritableWorkbookImpl workbook;
+
+ /**
+ * Handle to the workbook settings
+ */
+ private WorkbookSettings workbookSettings;
+
+ /**
+ * Constructor
+ *
+ * @param dvsr the record copied from a read only sheet
+ */
+ DataValiditySettingsRecord(jxl.read.biff.DataValiditySettingsRecord dvsr,
+ WritableWorkbookImpl w,
+ WorkbookSettings ws)
+ {
+ super(Type.DV);
+ workbook = w;
+ workbookSettings = ws;
+
+
+ data = dvsr.getData();
+ }
+
+ /**
+ * Constructor
+ *
+ * @param dvsr the record copied from a writable sheet
+ */
+ DataValiditySettingsRecord(DataValiditySettingsRecord dvsr,
+ WritableWorkbookImpl w,
+ WorkbookSettings ws)
+ {
+ super(Type.DV);
+ workbook = w;
+ workbookSettings = ws;
+
+ data = new byte[dvsr.data.length];
+ System.arraycopy(dvsr.data, 0, data, 0, data.length);
+ }
+
+ /**
+ * Initializes the dvParser
+ */
+ private void initialize()
+ {
+ try
+ {
+ if (dvParser == null)
+ {
+ dvParser = new DVParser(data, workbook, workbook, workbookSettings);
+ }
+ }
+ catch (FormulaException e)
+ {
+ logger.warn("Cannot read drop down range " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ /**
+ * Retrieves the data for output to binary file
+ *
+ * @return the data to be written
+ */
+ public byte[] getData()
+ {
+ if (dvParser == null)
+ {
+ return data;
+ }
+
+ return dvParser.getData();
+ }
+
+ /**
+ * Inserts a row
+ *
+ * @param row the row to insert
+ */
+ public void insertRow(int row)
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ dvParser.insertRow(row);
+ }
+
+ /**
+ * Removes a row
+ *
+ * @param row the row to insert
+ */
+ public void removeRow(int row)
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ dvParser.removeRow(row);
+ }
+
+ /**
+ * Inserts a row
+ *
+ * @param col the row to insert
+ */
+ public void insertColumn(int col)
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ dvParser.insertColumn(col);
+ }
+
+ /**
+ * Removes a column
+ *
+ * @param col the row to insert
+ */
+ public void removeColumn(int col)
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ dvParser.removeColumn(col);
+ }
+
+ /**
+ * Accessor for first column
+ *
+ * @return the first column
+ */
+ public int getFirstColumn()
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ return dvParser.getFirstColumn();
+ }
+
+ /**
+ * Accessor for the last column
+ *
+ * @return the last column
+ */
+ public int getLastColumn()
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ return dvParser.getLastColumn();
+ }
+
+ /**
+ * Accessor for first row
+ *
+ * @return the first row
+ */
+ public int getFirstRow()
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ return dvParser.getFirstRow();
+ }
+
+ /**
+ * Accessor for the last row
+ *
+ * @return the last row
+ */
+ public int getLastRow()
+ {
+ if (dvParser == null)
+ {
+ initialize();
+ }
+
+ return dvParser.getLastRow();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/DateFormatRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/DateFormatRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/DateFormatRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,49 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.FormatRecord;
+
+/**
+ * A class which contains a date format
+ */
+public class DateFormatRecord extends FormatRecord
+{
+ /**
+ * Constructor
+ *
+ * @param fmt the date format
+ */
+ protected DateFormatRecord(String fmt)
+ {
+ super();
+
+ // Do the replacements in the format string
+ String fs = fmt;
+
+ fs = replace(fs, "a", "AM/PM");
+ fs = replace(fs, "S", "0");
+
+ setFormatString(fs);
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/DateRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/DateRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/DateRecord.java 17 Aug 2012 14:51:08 -0000 1.1
@@ -0,0 +1,343 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+import common.Logger;
+
+import jxl.CellType;
+import jxl.DateCell;
+import jxl.biff.DoubleHelper;
+import jxl.biff.Type;
+import jxl.format.CellFormat;
+import jxl.write.DateFormats;
+import jxl.write.WritableCellFormat;
+
+/**
+ * A date stored in the database
+ */
+public abstract class DateRecord extends CellValue
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(DateRecord.class);
+
+ /**
+ * The excel value of the date
+ */
+ private double value;
+ /**
+ * The java representation of the date
+ */
+ private Date date;
+
+ /**
+ * Indicates whether this is a full date, or just a time only
+ */
+ private boolean time;
+
+ // The number of days between 01 Jan 1900 and 01 Jan 1970 - this gives
+ // the UTC offset
+ /**
+ */
+ private final static int utcOffsetDays = 25569;
+
+ // The number of milliseconds in a day
+ /**
+ */
+ private final static long msInADay = 24 * 60 * 60 * 1000;
+
+ /**
+ * This is package protected so that the worksheet might detect
+ * whether or not to override it with the column cell format
+ */
+ static final WritableCellFormat defaultDateFormat =
+ new WritableCellFormat(DateFormats.DEFAULT);
+
+ // The number of days between 1 Jan 1900 and 1 March 1900. Excel thinks
+ // the day before this was 29th Feb 1900, but it was 28th Feb 19000.
+ // I guess the programmers thought nobody would notice that they
+ // couldn't be bothered to program this dating anomaly properly
+ /**
+ */
+ private final static int nonLeapDay = 61;
+
+ /**
+ * Class definition for a dummy variable
+ */
+ protected static final class GMTDate
+ {
+ public GMTDate(){}
+ };
+
+ /**
+ * Constructor invoked by the user API
+ *
+ * @param c the column
+ * @param r the row
+ * @param d the date
+ */
+ protected DateRecord(int c, int r, Date d)
+ {
+ this(c, r, d, defaultDateFormat, false);
+ }
+
+ /**
+ * Constructor invoked by the user API
+ *
+ * @param c the column
+ * @param r the row
+ * @param d the date
+ * @param a adjust timezone
+ */
+ protected DateRecord(int c, int r, Date d, GMTDate a)
+ {
+ this(c, r, d, defaultDateFormat, false);
+ }
+
+ /**
+ * Constructor invoked from the user API
+ *
+ * @param c the column
+ * @param r the row
+ * @param st the format for the date
+ * @param d the date
+ */
+ protected DateRecord(int c, int r, Date d, CellFormat st)
+ {
+ super(Type.NUMBER, c, r,st);
+ date = d;
+ calculateValue(true);
+ }
+
+ /**
+ * Constructor invoked from the user API
+ *
+ * @param c the column
+ * @param r the row
+ * @param st the format for the date
+ * @param d the date
+ * @param a adjust for the timezone
+ */
+ protected DateRecord(int c, int r, Date d, CellFormat st, GMTDate a)
+ {
+ super(Type.NUMBER, c, r, st);
+ date = d;
+ calculateValue(false);
+ }
+
+ /**
+ * Constructor invoked from the API
+ *
+ * @param c the column
+ * @param r the row
+ * @param st the date format
+ * @param tim time indicator
+ * @param d the date
+ */
+ protected DateRecord(int c, int r, Date d, CellFormat st, boolean tim)
+ {
+ super(Type.NUMBER, c, r, st);
+ date = d;
+ time = tim;
+ calculateValue(false);
+ }
+
+ /**
+ * Constructor invoked when copying a readable spreadsheet
+ *
+ * @param dc the date to copy
+ */
+ protected DateRecord(DateCell dc)
+ {
+ super(Type.NUMBER, dc);
+ date = dc.getDate();
+ time = dc.isTime();
+ calculateValue(false);
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param c the column
+ * @param r the row
+ * @param dr the record to copy
+ */
+ protected DateRecord(int c, int r, DateRecord dr)
+ {
+ super(Type.NUMBER, c, r, dr);
+ value = dr.value;
+ time = dr.time;
+ date = dr.date;
+ }
+
+ /**
+ * Calculates the 1900 based numerical value based upon the utc value held
+ * in the date object
+ *
+ * @param adjust TRUE if we want to incorporate timezone information
+ * into the raw UTC date eg. when copying from a spreadsheet
+ */
+ private void calculateValue(boolean adjust)
+ {
+ // Offsets for current time zone
+ long zoneOffset = 0;
+ long dstOffset = 0;
+
+ // Get the timezone and dst offsets if we want to take these into
+ // account
+ if (adjust)
+ {
+ // Get the current calender, replete with timezone information
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+
+ zoneOffset = cal.get(Calendar.ZONE_OFFSET);
+ dstOffset = cal.get(Calendar.DST_OFFSET);
+ }
+
+ long utcValue = date.getTime() + zoneOffset + dstOffset;
+
+ // Convert this to the number of days, plus fractions of a day since
+ // 01 Jan 1970
+ double utcDays = (double) utcValue / (double) msInADay;
+
+ // Add in the offset to get the number of days since 01 Jan 1900
+ value = utcDays + utcOffsetDays;
+
+ // Work round a bug in excel. Excel seems to think there is a date
+ // called the 29th Feb, 1900 - but this was not a leap year.
+ // Therefore for values less than 61, we must subtract 1. Only do
+ // this for full dates, not times
+ if (!time && value < nonLeapDay)
+ {
+ value -= 1;
+ }
+
+ // If this refers to a time, then get rid of the integer part
+ if (time)
+ {
+ value = value - (int) value;
+ }
+ }
+
+ /**
+ * Returns the content type of this cell
+ *
+ * @return the content type for this cell
+ */
+ public CellType getType()
+ {
+ return CellType.DATE;
+ }
+
+ /**
+ * Gets the binary data for writing
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] celldata = super.getData();
+ byte[] data = new byte[celldata.length + 8];
+ System.arraycopy(celldata, 0, data, 0, celldata.length);
+ DoubleHelper.getIEEEBytes(value, data, celldata.length);
+
+ return data;
+ }
+
+ /**
+ * Quick and dirty function to return the contents of this cell as a string.
+ * For more complex manipulation of the contents, it is necessary to cast
+ * this interface to correct subinterface
+ *
+ * @return the contents of this cell as a string
+ */
+ public String getContents()
+ {
+ return date.toString();
+ }
+
+ /**
+ * Sets the date in this cell
+ *
+ * @param d the date
+ */
+ protected void setDate(Date d)
+ {
+ date = d;
+ calculateValue(true);
+ }
+
+ /**
+ * Sets the date in this cell, taking the timezone into account
+ *
+ * @param d the date
+ * @param a adjust for timezone
+ */
+ protected void setDate(Date d, GMTDate a)
+ {
+ date = d;
+ calculateValue(false);
+ }
+
+
+ /**
+ * Gets the date contained in this cell
+ *
+ * @return the cell contents
+ */
+ public Date getDate()
+ {
+ return date;
+ }
+
+ /**
+ * Indicates whether the date value contained in this cell refers to a date,
+ * or merely a time. When writing a cell, all dates are fully defined,
+ * even if they refer to a time
+ *
+ * @return FALSE if this is full date, TRUE if a time
+ */
+ public boolean isTime()
+ {
+ return time;
+ }
+
+ /**
+ * Gets the DateFormat used to format the cell. This will normally be
+ * the format specified in the excel spreadsheet, but in the event of any
+ * difficulty parsing this, it will revert to the default date/time format.
+ *
+ * @return the DateFormat object used to format the date in the original
+ * excel cell
+ */
+ public DateFormat getDateFormat()
+ {
+ return null;
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/DefaultColumnWidth.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/DefaultColumnWidth.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/DefaultColumnWidth.java 17 Aug 2012 14:51:08 -0000 1.1
@@ -0,0 +1,62 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * The default column width for a workbook
+ */
+class DefaultColumnWidth extends WritableRecordData
+{
+ /**
+ * The default column width
+ */
+ private int width;
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param w the default column width
+ */
+ public DefaultColumnWidth(int w)
+ {
+ super(Type.DEFCOLWIDTH);
+ width = w;
+ data = new byte[2];
+ IntegerHelper.getTwoBytes(width, data, 0);
+ }
+
+ /**
+ * Gets the binary data for writing to the stream
+ *
+ * @return the binary data
+ */
+ protected byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/DefaultRowHeightRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/DefaultRowHeightRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/DefaultRowHeightRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,77 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * The default row height for cells in the workbook
+ */
+class DefaultRowHeightRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+ /**
+ * The default row height
+ */
+ private int rowHeight;
+
+ /**
+ * Indicates whether or not the default row height has been changed
+ */
+ private boolean changed;
+
+ /**
+ * Constructor
+ *
+ * @param height the default row height
+ * @param ch TRUE if the default value has been changed, false
+ * otherwise
+ */
+ public DefaultRowHeightRecord(int h, boolean ch)
+ {
+ super(Type.DEFAULTROWHEIGHT);
+ data = new byte[4];
+ rowHeight = h;
+ changed = ch;
+ }
+
+ /**
+ * Gets the binary data for writing to the output stream
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ if (changed)
+ {
+ data[0] |= 0x1;
+ }
+
+ IntegerHelper.getTwoBytes(rowHeight, data, 2);
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/DeltaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/DeltaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/DeltaRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,79 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.DoubleHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record which stores the maximum change value from the Options
+ * dialog
+ */
+class DeltaRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+ /**
+ * The number of iterations
+ */
+ private double iterationValue;
+
+ /**
+ * Constructor
+ *
+ * @param itval
+ */
+ public DeltaRecord(double itval)
+ {
+ super(Type.DELTA);
+ iterationValue = itval;
+
+ data = new byte[8];
+ }
+
+
+ /**
+ * Gets the binary data for writing to the output file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ DoubleHelper.getIEEEBytes(iterationValue, data, 0);
+
+ /* long val = Double.doubleToLongBits(iterationValue);
+ data[0] = (byte) (val & 0xff);
+ data[1] = (byte) ((val & 0xff00) >> 8);
+ data[2] = (byte) ((val & 0xff0000) >> 16);
+ data[3] = (byte) ((val & 0xff000000) >> 24);
+ data[4] = (byte) ((val & 0xff00000000L) >> 32);
+ data[5] = (byte) ((val & 0xff0000000000L) >> 40);
+ data[6] = (byte) ((val & 0xff000000000000L) >> 48);
+ data[7] = (byte) ((val & 0xff00000000000000L) >> 56) ;
+ */
+
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/DimensionRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/DimensionRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/DimensionRecord.java 17 Aug 2012 14:51:08 -0000 1.1
@@ -0,0 +1,73 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record which contains the bounds of the sheet
+ */
+class DimensionRecord extends WritableRecordData
+{
+ /**
+ * The number of rows in the sheet
+ */
+ private int numRows;
+ /**
+ * The number of columns in the sheet
+ */
+ private int numCols;
+
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param c the number of columns
+ * @param r the number of rows
+ */
+ public DimensionRecord(int r, int c)
+ {
+ super(Type.DIMENSION);
+ numRows = r;
+ numCols = c;
+
+ data = new byte[14];
+
+ IntegerHelper.getFourBytes(numRows, data, 4);
+ IntegerHelper.getTwoBytes(numCols, data, 10);
+ }
+
+ /**
+ * Gets the binary data to be written to the output file
+ *
+ * @return the binary data
+ */
+ protected byte[] getData()
+ {
+ return data;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/EOFRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/EOFRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/EOFRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,48 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record which marks the end of the current stream
+ */
+class EOFRecord extends WritableRecordData
+{
+ /**
+ * Constructor
+ */
+ public EOFRecord()
+ {
+ super(Type.EOF);
+ }
+
+ /**
+ * Returns the binary data to be written to the output file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return new byte[0];
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ExcelDataOutput.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ExcelDataOutput.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ExcelDataOutput.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,62 @@
+/*********************************************************************
+*
+* Copyright (C) 2007 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * Interface to abstract away an in-memory output or a temporary file
+ * output. Used by the File object
+ */
+interface ExcelDataOutput
+{
+ /**
+ * Appends the bytes to the end of the output
+ *
+ * @param d the data to write to the end of the array
+ */
+ public void write(byte[] bytes) throws IOException;
+
+ /**
+ * Gets the current position within the file
+ *
+ * @return the position within the file
+ */
+ public int getPosition() throws IOException;
+
+ /**
+ * Sets the data at the specified position to the contents of the array
+ *
+ * @param pos the position to alter
+ * @param newdata the data to modify
+ */
+ public void setData(byte[] newdata, int pos) throws IOException;
+
+ /**
+ * Writes the data to the output stream
+ */
+ public void writeData(OutputStream out) throws IOException;
+
+ /**
+ * Called when the final compound file has been written
+ */
+ public void close() throws IOException;
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ExtendedSSTRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ExtendedSSTRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ExtendedSSTRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,115 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Indicates an extension to the Shared String Table. Currently this
+ * contains blank records
+ *
+ * Thanks to Guenther for contributing a proper implementation of the EXTSST
+ * record, replacing my previous dummy version
+ */
+class ExtendedSSTRecord extends WritableRecordData
+{
+ private static final int infoRecordSize = 8;
+ private int numberOfStrings;
+ private int[] absoluteStreamPositions;
+ private int[] relativeStreamPositions;
+ private int currentStringIndex = 0;
+
+ /**
+ * Constructor
+ *
+ * @param numstrings the number of strings per bucket
+ * @param streampos the absolute stream position of the beginning of
+ * the SST record
+ */
+ public ExtendedSSTRecord(int newNumberOfStrings)
+ {
+ super(Type.EXTSST);
+ numberOfStrings = newNumberOfStrings;
+ int numberOfBuckets = getNumberOfBuckets();
+ absoluteStreamPositions = new int[numberOfBuckets];
+ relativeStreamPositions = new int[numberOfBuckets];
+ currentStringIndex = 0;
+ }
+
+ public int getNumberOfBuckets()
+ {
+ int numberOfStringsPerBucket = getNumberOfStringsPerBucket();
+ return numberOfStringsPerBucket != 0 ?
+ (numberOfStrings + numberOfStringsPerBucket - 1) /
+ numberOfStringsPerBucket : 0;
+ }
+
+ public int getNumberOfStringsPerBucket()
+ {
+ // XXX
+ // should come up with a more clever calculation
+ // bucket limit should not be bigger than 1024, otherwise we end
+ // up with too many buckets and would have to write continue records
+ // for the EXTSST record which we want to avoid for now.
+ final int bucketLimit = 128;
+ return (numberOfStrings + bucketLimit - 1) / bucketLimit;
+ }
+
+ public void addString(int absoluteStreamPosition,
+ int relativeStreamPosition)
+ {
+ absoluteStreamPositions[currentStringIndex] =
+ absoluteStreamPosition + relativeStreamPosition;
+ relativeStreamPositions[currentStringIndex] = relativeStreamPosition;
+ currentStringIndex++;
+ }
+
+ /**
+ * Gets the binary data to be written out
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ int numberOfBuckets = getNumberOfBuckets();
+ byte[] data = new byte[2 + (8 * numberOfBuckets)];
+ // number of strings per bucket
+ IntegerHelper.getTwoBytes(getNumberOfStringsPerBucket(), data, 0);
+
+ for (int i = 0; i < numberOfBuckets; i++)
+ {
+ // absolute stream position
+ IntegerHelper.getFourBytes(absoluteStreamPositions[i],
+ data,
+ 2 + (i * infoRecordSize));
+ // relative offset
+ IntegerHelper.getTwoBytes(relativeStreamPositions[i],
+ data,
+ 6 + (i * infoRecordSize));
+ // reserved
+ // IntegerHelper.getTwoBytes(0x0, data, 8 + (i * infoRecordSize));
+ }
+
+ return data;
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ExternalNameRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ExternalNameRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ExternalNameRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,74 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Logger;
+
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * An external sheet record, used to maintain integrity when formulas
+ * are copied from read databases
+ */
+class ExternalNameRecord extends WritableRecordData
+{
+ /**
+ * The logger
+ */
+ Logger logger = Logger.getLogger(ExternalNameRecord.class);
+
+ /**
+ * The name of the addin
+ */
+ private String name;
+
+ /**
+ * Constructor used for writable workbooks
+ */
+ public ExternalNameRecord(String n)
+ {
+ super(Type.EXTERNNAME);
+ name = n;
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[name.length() * 2 + 12];
+
+ data[6] = (byte) name.length();
+ data[7] = 0x1;
+ StringHelper.getUnicodeBytes(name, data, 8);
+
+ int pos = 8 + name.length() * 2;
+ data[pos] = 0x2;
+ data[pos+1] = 0x0;
+ data[pos+2] = 0x1c;
+ data[pos+3] = 0x17;
+
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ExternalSheetRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ExternalSheetRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ExternalSheetRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,252 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * An external sheet record, used to maintain integrity when formulas
+ * are copied from read databases
+ */
+class ExternalSheetRecord extends WritableRecordData
+{
+ /**
+ * The underlying external sheet data
+ */
+ private byte[] data;
+
+ /**
+ * The list of XTI structures
+ */
+ private ArrayList xtis;
+
+ /**
+ * An XTI structure
+ */
+ private static class XTI
+ {
+ int supbookIndex;
+ int firstTab;
+ int lastTab;
+
+ XTI(int s, int f, int l)
+ {
+ supbookIndex = s;
+ firstTab = f;
+ lastTab = l;
+ }
+
+ void sheetInserted(int index)
+ {
+ if (firstTab >= index)
+ {
+ firstTab++;
+ }
+
+ if (lastTab >= index)
+ {
+ lastTab++;
+ }
+ }
+
+ void sheetRemoved(int index)
+ {
+ if (firstTab == index)
+ {
+ firstTab = 0;
+ }
+
+ if (lastTab == index)
+ {
+ lastTab = 0;
+ }
+
+ if (firstTab > index)
+ {
+ firstTab--;
+ }
+
+ if (lastTab > index)
+ {
+ lastTab--;
+ }
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param esf the external sheet record to copy
+ */
+ public ExternalSheetRecord(jxl.read.biff.ExternalSheetRecord esf)
+ {
+ super(Type.EXTERNSHEET);
+
+ xtis = new ArrayList(esf.getNumRecords());
+ XTI xti = null;
+ for (int i = 0 ; i < esf.getNumRecords(); i++)
+ {
+ xti = new XTI(esf.getSupbookIndex(i),
+ esf.getFirstTabIndex(i),
+ esf.getLastTabIndex(i));
+ xtis.add(xti);
+ }
+ }
+
+ /**
+ * Constructor used for writable workbooks
+ */
+ public ExternalSheetRecord()
+ {
+ super(Type.EXTERNSHEET);
+ xtis = new ArrayList();
+ }
+
+ /**
+ * Gets the extern sheet index for the specified parameters, creating
+ * a new xti record if necessary
+ * @param supbookind the internal supbook reference
+ * @param sheetind the sheet index
+ */
+ int getIndex(int supbookind, int sheetind)
+ {
+ Iterator i = xtis.iterator();
+ XTI xti = null;
+ boolean found = false;
+ int pos = 0;
+ while (i.hasNext() && !found)
+ {
+ xti = (XTI) i.next();
+
+ if (xti.supbookIndex == supbookind &&
+ xti.firstTab == sheetind)
+ {
+ found = true;
+ }
+ else
+ {
+ pos++;
+ }
+ }
+
+ if (!found)
+ {
+ xti = new XTI(supbookind, sheetind, sheetind);
+ xtis.add(xti);
+ pos = xtis.size() - 1;
+ }
+
+ return pos;
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[2 + xtis.size() * 6];
+
+ int pos = 0;
+ IntegerHelper.getTwoBytes(xtis.size(), data, 0);
+ pos += 2;
+
+ Iterator i = xtis.iterator();
+ XTI xti = null;
+ while (i.hasNext())
+ {
+ xti = (XTI) i.next();
+ IntegerHelper.getTwoBytes(xti.supbookIndex, data, pos);
+ IntegerHelper.getTwoBytes(xti.firstTab, data, pos+2);
+ IntegerHelper.getTwoBytes(xti.lastTab, data, pos+4);
+ pos +=6 ;
+ }
+
+ return data;
+ }
+
+ /**
+ * Gets the supbook index for the specified external sheet
+ *
+ * @param the index of the supbook record
+ * @return the supbook index
+ */
+ public int getSupbookIndex(int index)
+ {
+ return ((XTI) xtis.get(index)).supbookIndex;
+ }
+
+ /**
+ * Gets the first tab index for the specified external sheet
+ *
+ * @param the index of the supbook record
+ * @return the first tab index
+ */
+ public int getFirstTabIndex(int index)
+ {
+ return ((XTI) xtis.get(index)).firstTab;
+ }
+
+ /**
+ * Gets the last tab index for the specified external sheet
+ *
+ * @param the index of the supbook record
+ * @return the last tab index
+ */
+ public int getLastTabIndex(int index)
+ {
+ return ((XTI) xtis.get(index)).lastTab;
+ }
+
+ /**
+ * Called when a sheet has been inserted via the API
+ * @param the position of the insertion
+ */
+ void sheetInserted(int index)
+ {
+ XTI xti = null;
+ for (Iterator i = xtis.iterator(); i.hasNext() ; )
+ {
+ xti = (XTI) i.next();
+ xti.sheetInserted(index);
+ }
+ }
+
+ /**
+ * Called when a sheet has been removed via the API
+ * @param the position of the insertion
+ */
+ void sheetRemoved(int index)
+ {
+ XTI xti = null;
+ for (Iterator i = xtis.iterator(); i.hasNext() ; )
+ {
+ xti = (XTI) i.next();
+ xti.sheetRemoved(index);
+ }
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/File.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/File.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/File.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,191 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.ByteData;
+
+/**
+ * A file of excel data to be written out. All the excel data is held
+ * in memory, and when the close method is called a CompoundFile object
+ * is used to write the Biff oriented excel data in the CompoundFile
+ * format
+ */
+public final class File
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(File.class);
+
+ /**
+ * The data from the excel 97 file
+ */
+ private ExcelDataOutput data;
+ /**
+ * The current position within the file
+ */
+ private int pos;
+ /**
+ * The output stream
+ */
+ private OutputStream outputStream;
+ /**
+ * The initial file size
+ */
+ private int initialFileSize;
+ /**
+ * The amount to increase the growable array by
+ */
+ private int arrayGrowSize;
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings workbookSettings;
+ /**
+ * The read compound file. This will only be non-null if there are macros
+ * or other property sets of that ilk which that we should be copying
+ */
+ jxl.read.biff.CompoundFile readCompoundFile;
+
+ /**
+ * Constructor
+ *
+ * @param os the output stream
+ * @param ws the configuration settings for this workbook
+ * @param rcf the rea compound file
+ */
+ File(OutputStream os, WorkbookSettings ws, jxl.read.biff.CompoundFile rcf)
+ throws IOException
+ {
+ outputStream = os;
+ workbookSettings = ws;
+ readCompoundFile = rcf;
+ createDataOutput();
+ }
+
+ private void createDataOutput() throws IOException
+ {
+ if (workbookSettings.getUseTemporaryFileDuringWrite())
+ {
+ data = new FileDataOutput
+ (workbookSettings.getTemporaryFileDuringWriteDirectory());
+ }
+ else
+ {
+ initialFileSize = workbookSettings.getInitialFileSize();
+ arrayGrowSize = workbookSettings.getArrayGrowSize();
+
+ data = new MemoryDataOutput(initialFileSize, arrayGrowSize);
+ }
+ }
+
+ /**
+ * Closes the file. In fact, this writes out all the excel data
+ * to disk using a CompoundFile object, and then frees up all the memory
+ * allocated to the workbook
+ *
+ * @exception IOException
+ * @param cs TRUE if this should close the stream, FALSE if the application
+ * closes it
+ */
+ void close(boolean cs) throws IOException, JxlWriteException
+ {
+ CompoundFile cf = new CompoundFile(data,
+ data.getPosition(),
+ outputStream,
+ readCompoundFile);
+ cf.write();
+
+ outputStream.flush();
+ data.close();
+
+ if (cs)
+ {
+ outputStream.close();
+ }
+
+ // Cleanup the memory a bit
+ data = null;
+
+ if (!workbookSettings.getGCDisabled())
+ {
+ System.gc();
+ }
+ }
+
+ /**
+ * Adds the biff record data to the memory allocated for this File
+ *
+ * @exception IOException
+ * @param record the record to add to the excel data
+ */
+ public void write(ByteData record) throws IOException
+ {
+ byte[] bytes = record.getBytes();
+
+ data.write(bytes);
+ }
+
+ /**
+ * Gets the current position within the file
+ *
+ * @return the current position
+ */
+ int getPos() throws IOException
+ {
+ return data.getPosition();
+ }
+
+ /**
+ * Used to manually alter the contents of the written out data. This
+ * is used when cross-referencing cell records
+ *
+ * @param pos the position to alter
+ * @param newdata the data to modify
+ */
+ void setData(byte[] newdata, int pos) throws IOException
+ {
+ data.setData(newdata, pos);
+ }
+
+ /**
+ * Sets a new output file. This allows the same workbook to be
+ * written to various different output files without having to
+ * read in any templates again
+ *
+ * @param os the output stream
+ */
+ public void setOutputFile(OutputStream os) throws IOException
+ {
+ if (data != null)
+ {
+ logger.warn("Rewriting a workbook with non-empty data");
+ }
+
+ outputStream = os;
+ createDataOutput();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/FileDataOutput.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/FileDataOutput.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/FileDataOutput.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,123 @@
+/*********************************************************************
+*
+* Copyright (C) 2007 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.OutputStream;
+import java.io.IOException;
+import java.io.File;
+import java.io.RandomAccessFile;
+
+import common.Logger;
+
+/**
+ * Used to generate the excel biff data using a temporary file. This
+ * class wraps a RandomAccessFile
+ */
+class FileDataOutput implements ExcelDataOutput
+{
+ // The logger
+ private static Logger logger = Logger.getLogger(FileDataOutput.class);
+
+ /**
+ * The temporary file
+ */
+ private File temporaryFile;
+
+ /**
+ * The excel data
+ */
+ private RandomAccessFile data;
+
+ /**
+ * Constructor
+ *
+ * @param tmpdir the temporary directory used to write files. If this is
+ * NULL then the sytem temporary directory will be used
+ */
+ public FileDataOutput(File tmpdir) throws IOException
+ {
+ temporaryFile = File.createTempFile("jxl",".tmp", tmpdir);
+ temporaryFile.deleteOnExit();
+ data = new RandomAccessFile(temporaryFile, "rw");
+ }
+
+ /**
+ * Writes the bytes to the end of the array, growing the array
+ * as needs dictate
+ *
+ * @param d the data to write to the end of the array
+ */
+ public void write(byte[] bytes) throws IOException
+ {
+ data.write(bytes);
+ }
+
+ /**
+ * Gets the current position within the file
+ *
+ * @return the position within the file
+ */
+ public int getPosition() throws IOException
+ {
+ // As all excel data structures are four bytes anyway, it's ok to
+ // truncate the long to an int
+ return (int) data.getFilePointer();
+ }
+
+ /**
+ * Sets the data at the specified position to the contents of the array
+ *
+ * @param pos the position to alter
+ * @param newdata the data to modify
+ */
+ public void setData(byte[] newdata, int pos) throws IOException
+ {
+ long curpos = data.getFilePointer();
+ data.seek(pos);
+ data.write(newdata);
+ data.seek(curpos);
+ }
+
+ /**
+ * Writes the data to the output stream
+ */
+ public void writeData(OutputStream out) throws IOException
+ {
+ byte[] buffer = new byte[1024];
+ int length = 0;
+ data.seek(0);
+ while ((length = data.read(buffer)) != -1)
+ {
+ out.write(buffer, 0, length);
+ }
+ }
+
+ /**
+ * Called when the final compound file has been written
+ */
+ public void close() throws IOException
+ {
+ data.close();
+
+ // Explicitly delete the temporary file, since sometimes it is the case
+ // that a single process may be generating multiple different excel files
+ temporaryFile.delete();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/FooterRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/FooterRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/FooterRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,89 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Places a string at the bottom of each page when the file is printed.
+ * JExcelApi sets this to be blank
+ */
+class FooterRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+ /**
+ * The footer string
+ */
+ private String footer;
+
+ /**
+ * Consructor
+ *
+ * @param s the footer
+ */
+ public FooterRecord(String s)
+ {
+ super(Type.FOOTER);
+
+ footer = s;
+ }
+
+ /**
+ * Consructor invoked when copying a sheets
+ *
+ * @param fr the read footer record
+ */
+ public FooterRecord(FooterRecord fr)
+ {
+ super(Type.FOOTER);
+
+ footer = fr.footer;
+ }
+
+ /**
+ * Gets the binary data to write to the output file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ if (footer == null || footer.length() == 0)
+ {
+ data = new byte[0];
+ return data;
+ }
+
+ data = new byte[footer.length() * 2 + 3];
+ IntegerHelper.getTwoBytes(footer.length(), data, 0);
+ data[2] = (byte) 0x1;
+
+ StringHelper.getUnicodeBytes(footer, data, 3);
+
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/FormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/FormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/FormulaRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,378 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.CellReferenceHelper;
+import jxl.CellType;
+import jxl.Sheet;
+import jxl.WorkbookSettings;
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.formula.ExternalSheet;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+import jxl.format.CellFormat;
+import jxl.write.WritableCell;
+
+/**
+ * A formula record. Parses the string passed in to deduce the set of
+ * formula records
+ */
+public class FormulaRecord extends CellValue implements FormulaData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(FormulaRecord.class);
+
+ /**
+ * The formula to parse
+ */
+ private String formulaToParse;
+
+ /**
+ * The formula parser
+ */
+ private FormulaParser parser;
+
+ /**
+ * The parsed formula string
+ */
+ private String formulaString;
+
+ /**
+ * The parsed formula bytes
+ */
+ private byte[] formulaBytes;
+
+ /**
+ * The location where this formula was copied from. It is used subsequently
+ * to adjust relative cell references
+ */
+ private CellValue copiedFrom;
+
+ /**
+ * Constructor
+ *
+ * @param f the formula to copy
+ */
+ public FormulaRecord(int c, int r, String f)
+ {
+ super(Type.FORMULA2, c, r);
+ formulaToParse = f;
+ copiedFrom = null;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param f the formula to copy
+ */
+ public FormulaRecord(int c, int r, String f, CellFormat st)
+ {
+ super(Type.FORMULA, c, r, st);
+ formulaToParse = f;
+ copiedFrom = null;
+ }
+
+ /**
+ * Copy constructor for writable formulas
+ *
+ * @param c the column
+ * @param r the row
+ * @param fr the record to copy
+ */
+ protected FormulaRecord(int c, int r, FormulaRecord fr)
+ {
+ super(Type.FORMULA, c, r, fr);
+ copiedFrom = fr;
+ formulaBytes = new byte[fr.formulaBytes.length];
+ System.arraycopy(fr.formulaBytes, 0, formulaBytes, 0, formulaBytes.length);
+ }
+
+ /**
+ * Copy constructor for formulas read in - invoked from writable formulas
+ *
+ * @param c the column
+ * @param r the row
+ * @param rfr the formula data to copy
+ */
+ protected FormulaRecord(int c, int r, ReadFormulaRecord rfr)
+ {
+ super(Type.FORMULA, c, r, rfr);
+ try
+ {
+ copiedFrom = rfr;
+ formulaBytes = rfr.getFormulaBytes();
+ }
+ catch (FormulaException e)
+ {
+ // Fail silently
+ logger.error("", e);
+ }
+ }
+
+ /**
+ * Initializes the string and the formula bytes. In order to get
+ * access to the workbook settings, the object is not initialized until
+ * it is added to the sheet
+ *
+ * @param ws the workbook settings
+ * @param es the external sheet
+ * @param nt the name table
+ */
+ private void initialize(WorkbookSettings ws, ExternalSheet es,
+ WorkbookMethods nt)
+ {
+ if (copiedFrom != null)
+ {
+ initializeCopiedFormula(ws, es, nt);
+ return;
+ }
+
+ parser = new FormulaParser(formulaToParse, es, nt, ws);
+
+ try
+ {
+ parser.parse();
+ formulaString = parser.getFormula();
+ formulaBytes = parser.getBytes();
+ }
+ catch (FormulaException e)
+ {
+ logger.warn
+ (e.getMessage() +
+ " when parsing formula " + formulaToParse + " in cell " +
+ getSheet().getName() + "!" +
+ CellReferenceHelper.getCellReference(getColumn(), getRow()));
+
+ try
+ {
+ // try again, with an error formula
+ formulaToParse = "ERROR(1)";
+ parser = new FormulaParser(formulaToParse, es, nt, ws);
+ parser.parse();
+ formulaString = parser.getFormula();
+ formulaBytes = parser.getBytes();
+ }
+ catch (FormulaException e2)
+ {
+ // fail silently
+ logger.error("",e2);
+ }
+ }
+ }
+
+ /**
+ * This formula was copied from a formula already present in the writable
+ * workbook. Requires special handling to sort out the cell references
+
+ * @param ws the workbook settings
+ * @param es the external sheet
+ * @param nt the name table
+ */
+ private void initializeCopiedFormula(WorkbookSettings ws,
+ ExternalSheet es, WorkbookMethods nt)
+ {
+ try
+ {
+ parser = new FormulaParser(formulaBytes, this, es, nt, ws);
+ parser.parse();
+ parser.adjustRelativeCellReferences
+ (getColumn() - copiedFrom.getColumn(),
+ getRow() - copiedFrom.getRow());
+ formulaString = parser.getFormula();
+ formulaBytes = parser.getBytes();
+ }
+ catch (FormulaException e)
+ {
+ try
+ {
+ // try again, with an error formula
+ formulaToParse = "ERROR(1)";
+ parser = new FormulaParser(formulaToParse, es, nt, ws);
+ parser.parse();
+ formulaString = parser.getFormula();
+ formulaBytes = parser.getBytes();
+
+ }
+ catch (FormulaException e2)
+ {
+ // fail silently
+ logger.error("", e2);
+ }
+ }
+ }
+
+ /**
+ * Called when the cell is added to the worksheet. Overrides the
+ * method in the base class in order to get a handle to the
+ * WorkbookSettings so that this formula may be initialized
+ *
+ * @param fr the formatting records
+ * @param ss the shared strings used within the workbook
+ * @param s the sheet this is being added to
+ */
+ void setCellDetails(FormattingRecords fr, SharedStrings ss,
+ WritableSheetImpl s)
+ {
+ super.setCellDetails(fr, ss, s);
+ initialize(s.getWorkbookSettings(), s.getWorkbook(), s.getWorkbook());
+ s.getWorkbook().addRCIRCell(this);
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] celldata = super.getData();
+ byte[] formulaData = getFormulaData();
+ byte[] data = new byte[formulaData.length + celldata.length];
+ System.arraycopy(celldata, 0, data, 0, celldata.length);
+ System.arraycopy(formulaData, 0, data, celldata.length,
+ formulaData.length);
+ return data;
+ }
+
+ /**
+ * Returns the content type of this cell
+ *
+ * @return the content type for this cell
+ */
+ public CellType getType()
+ {
+ return CellType.ERROR;
+ }
+
+ /**
+ * Quick and dirty function to return the contents of this cell as a string.
+ * For more complex manipulation of the contents, it is necessary to cast
+ * this interface to correct subinterface
+ *
+ * @return the contents of this cell as a string
+ */
+ public String getContents()
+ {
+ return formulaString;
+ }
+
+ /**
+ * Gets the raw bytes for the formula. This will include the
+ * parsed tokens array
+ *
+ * @return the raw record data
+ */
+ public byte[] getFormulaData()
+ {
+ byte[] data = new byte[formulaBytes.length + 16];
+ System.arraycopy(formulaBytes, 0, data, 16, formulaBytes.length);
+
+ data[6] = (byte) 0x10;
+ data[7] = (byte) 0x40;
+ data[12] = (byte) 0xe0;
+ data[13] = (byte) 0xfc;
+ // Set the recalculate on load bit
+ data[8] |= 0x02;
+
+ // Set the length of the rpn array
+ IntegerHelper.getTwoBytes(formulaBytes.length, data, 14);
+
+ return data;
+ }
+
+ /**
+ * A dummy implementation to keep the compiler quiet. This object needs
+ * to be instantiated from ReadFormulaRecord
+ *
+ * @param col the column which the new cell will occupy
+ * @param row the row which the new cell will occupy
+ * @return NOTHING
+ */
+ public WritableCell copyTo(int col, int row)
+ {
+ Assert.verify(false);
+ return null;
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Notifies all
+ * RCIR cells of this change. The default implementation here does nothing
+ *
+ * @param s the sheet on which the column was inserted
+ * @param sheetIndex the sheet index on which the column was inserted
+ * @param col the column number which was inserted
+ */
+ void columnInserted(Sheet s, int sheetIndex, int col)
+ {
+ parser.columnInserted(sheetIndex, col, s == getSheet());
+ formulaBytes = parser.getBytes();
+ }
+
+ /**
+ * Called when a column is removed on the specified sheet. Notifies all
+ * RCIR cells of this change. The default implementation here does nothing
+ *
+ * @param s the sheet on which the column was inserted
+ * @param sheetIndex the sheet index on which the column was inserted
+ * @param col the column number which was inserted
+ */
+ void columnRemoved(Sheet s, int sheetIndex, int col)
+ {
+ parser.columnRemoved(sheetIndex, col, s == getSheet());
+ formulaBytes = parser.getBytes();
+ }
+
+ /**
+ * Called when a row is inserted on the specified sheet. Notifies all
+ * RCIR cells of this change. The default implementation here does nothing
+ *
+ * @param s the sheet on which the column was inserted
+ * @param sheetIndex the sheet index on which the column was inserted
+ * @param row the column number which was inserted
+ */
+ void rowInserted(Sheet s, int sheetIndex, int row)
+ {
+ parser.rowInserted(sheetIndex, row, s == getSheet());
+ formulaBytes = parser.getBytes();
+ }
+
+ /**
+ * Called when a row is inserted on the specified sheet. Notifies all
+ * RCIR cells of this change. The default implementation here does nothing
+ *
+ * @param s the sheet on which the row was removed
+ * @param sheetIndex the sheet index on which the column was removed
+ * @param row the column number which was removed
+ */
+ void rowRemoved(Sheet s, int sheetIndex, int row)
+ {
+ parser.rowRemoved(sheetIndex, row, s == getSheet());
+ formulaBytes = parser.getBytes();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/FunctionGroupCountRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/FunctionGroupCountRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/FunctionGroupCountRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,67 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores the number of build in function groups
+ */
+class FunctionGroupCountRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * The number of built in function groups
+ */
+ private int numFunctionGroups;
+
+ /**
+ * Constructor
+ */
+ public FunctionGroupCountRecord()
+ {
+ super(Type.FNGROUPCOUNT);
+
+ numFunctionGroups = 0xe;
+
+ data = new byte[2];
+
+ IntegerHelper.getTwoBytes(numFunctionGroups, data, 0);
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/GridSetRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/GridSetRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/GridSetRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,69 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record which indicates that the user changed the stae of the
+ * GridLines option
+ */
+class GridSetRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+ /**
+ * Gridset flag
+ */
+ private boolean gridSet;
+
+ /**
+ * Constructor
+ *
+ * @param gs grid set flag
+ */
+ public GridSetRecord(boolean gs)
+ {
+ super(Type.GRIDSET);
+ gridSet = gs;
+
+ data = new byte[2];
+
+ if (gridSet)
+ {
+ data[0] = 1;
+ }
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/GuttersRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/GuttersRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/GuttersRecord.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,119 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record which contains the size of the row and column gutters. These are
+ * all set to zero by default
+ */
+class GuttersRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+ /**
+ * The rowGutter
+ */
+ private int rowGutter;
+ /**
+ * The column gutter
+ */
+ private int colGutter;
+ /**
+ * The maximum outline level for the row gutter
+ */
+ private int maxRowOutline;
+ /**
+ * The maximum row outline level for the column gutter
+ */
+ private int maxColumnOutline;
+
+ /**
+ * Constructor
+ */
+ public GuttersRecord()
+ {
+ super(Type.GUTS);
+ }
+
+ /**
+ * Gets the binary data for output
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ data = new byte[8];
+ IntegerHelper.getTwoBytes(rowGutter, data, 0);
+ IntegerHelper.getTwoBytes(colGutter, data, 2);
+ IntegerHelper.getTwoBytes(maxRowOutline, data, 4);
+ IntegerHelper.getTwoBytes(maxColumnOutline, data, 6);
+ return data;
+ }
+
+ /**
+ * Accessor for the maximum row outline
+ *
+ * @return the maximum row outline
+ */
+ public int getMaxRowOutline()
+ {
+ return maxRowOutline;
+ }
+
+ /**
+ * Sets the maximum row outline
+ *
+ * @param value the maximum row outline
+ */
+ public void setMaxRowOutline(int value)
+ {
+ maxRowOutline = value;
+ rowGutter = 1 + 14 * value;
+ }
+
+ /**
+ * Accessor for the maximum column outline
+ *
+ * @return the maximum column outline
+ */
+ public int getMaxColumnOutline()
+ {
+ return maxColumnOutline;
+ }
+
+ /**
+ * Sets the maximum column outline
+ *
+ * @param value the maximum row outline
+ */
+ public void setMaxColumnOutline(int value)
+ {
+ maxColumnOutline = value;
+ colGutter = 1 + 14 * value;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/HeaderRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/HeaderRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/HeaderRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,88 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record which specifies a print header for a work sheet
+ */
+class HeaderRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+ /**
+ * The print header string
+ */
+ private String header;
+
+ /**
+ * Constructor
+ *
+ * @param s the header string
+ */
+ public HeaderRecord(String h)
+ {
+ super(Type.HEADER);
+
+ header = h;
+ }
+
+ /**
+ * Consructor invoked when copying a sheets
+ *
+ * @param hr the read header record
+ */
+ public HeaderRecord(HeaderRecord hr)
+ {
+ super(Type.HEADER);
+
+ header = hr.header;
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ if (header == null || header.length() == 0)
+ {
+ data = new byte[0];
+ return data;
+ }
+
+ data = new byte[header.length() * 2 + 3];
+ IntegerHelper.getTwoBytes(header.length(), data, 0);
+ data[2] = (byte) 0x1;
+
+ StringHelper.getUnicodeBytes(header, data, 3);
+
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/HideobjRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/HideobjRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/HideobjRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,67 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores options selected in the Options dialog box
+ */
+class HideobjRecord extends WritableRecordData
+{
+ /**
+ * Flag to hide everything
+ */
+ private boolean hideAll;
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param hide the hide all flag
+ */
+ public HideobjRecord(boolean hide)
+ {
+ super(Type.HIDEOBJ);
+
+ hideAll = hide;
+ data = new byte[2];
+
+ if (hideAll)
+ {
+ IntegerHelper.getTwoBytes(2, data, 0);
+ }
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/HorizontalCentreRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/HorizontalCentreRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/HorizontalCentreRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,70 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record which indicates the whether the horizontal center option has
+ * been set
+ */
+class HorizontalCentreRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+ /**
+ * The centre flag
+ */
+ private boolean centre;
+
+ /**
+ * Constructor
+ *
+ * @param ce the centre flag
+ */
+ public HorizontalCentreRecord(boolean ce)
+ {
+ super(Type.HCENTER);
+
+ centre = ce;
+
+ data = new byte[2];
+
+ if (centre)
+ {
+ data[0] = 1;
+ }
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/HorizontalPageBreaksRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/HorizontalPageBreaksRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/HorizontalPageBreaksRecord.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,72 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Contains the list of explicit horizontal page breaks on the current sheet
+ */
+class HorizontalPageBreaksRecord extends WritableRecordData
+{
+ /**
+ * The row breaks
+ */
+ private int[] rowBreaks;
+
+ /**
+ * Constructor
+ *
+ * @param break the row breaks
+ */
+ public HorizontalPageBreaksRecord(int[] breaks)
+ {
+ super(Type.HORIZONTALPAGEBREAKS);
+
+ rowBreaks = breaks;
+ }
+
+ /**
+ * Gets the binary data to write to the output file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[rowBreaks.length * 6 + 2];
+
+ // The number of breaks on the list
+ IntegerHelper.getTwoBytes(rowBreaks.length, data, 0);
+ int pos = 2;
+
+ for (int i = 0; i < rowBreaks.length; i++)
+ {
+ IntegerHelper.getTwoBytes(rowBreaks[i], data, pos);
+ IntegerHelper.getTwoBytes(0xff, data, pos+4);
+ pos += 6;
+ }
+
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/HyperlinkRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/HyperlinkRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/HyperlinkRecord.java 17 Aug 2012 14:51:08 -0000 1.1
@@ -0,0 +1,1277 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.File;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.CellType;
+import jxl.Hyperlink;
+import jxl.Range;
+import jxl.WorkbookSettings;
+import jxl.biff.CellReferenceHelper;
+import jxl.biff.IntegerHelper;
+import jxl.biff.SheetRangeImpl;
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+import jxl.write.Label;
+import jxl.write.WritableHyperlink;
+import jxl.write.WritableCell;
+import jxl.write.WritableSheet;
+
+
+/**
+ * A hyperlink
+ */
+public class HyperlinkRecord extends WritableRecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(HyperlinkRecord.class);
+
+ /**
+ * The first row
+ */
+ private int firstRow;
+ /**
+ * The last row
+ */
+ private int lastRow;
+ /**
+ * The first column
+ */
+ private int firstColumn;
+ /**
+ * The last column
+ */
+ private int lastColumn;
+
+ /**
+ * The URL referred to by this hyperlink
+ */
+ private URL url;
+
+ /**
+ * The local file referred to by this hyperlink
+ */
+ private File file;
+
+ /**
+ * The location in this workbook referred to by this hyperlink
+ */
+ private String location;
+
+ /**
+ * The cell contents of the cell which activate this hyperlink
+ */
+ private String contents;
+
+ /**
+ * The type of this hyperlink
+ */
+ private LinkType linkType;
+
+ /**
+ * The data for this hyperlink
+ */
+ private byte[] data;
+
+ /**
+ * The range of this hyperlink. When creating a hyperlink, this will
+ * be null until the hyperlink is added to the sheet
+ */
+ private Range range;
+
+ /**
+ * The sheet containing this hyperlink
+ */
+ private WritableSheet sheet;
+
+ /**
+ * Indicates whether this record has been modified since it was copied
+ */
+ private boolean modified;
+
+ /**
+ * The excel type of hyperlink
+ */
+ private static class LinkType {};
+
+ private static final LinkType urlLink = new LinkType();
+ private static final LinkType fileLink = new LinkType();
+ private static final LinkType uncLink = new LinkType();
+ private static final LinkType workbookLink = new LinkType();
+ private static final LinkType unknown = new LinkType();
+
+ /**
+ * Constructs this object from the readable spreadsheet
+ *
+ * @param hl the hyperlink from the read spreadsheet
+ */
+ protected HyperlinkRecord(Hyperlink h, WritableSheet s)
+ {
+ super(Type.HLINK);
+
+ if (h instanceof jxl.read.biff.HyperlinkRecord)
+ {
+ copyReadHyperlink(h, s);
+ }
+ else
+ {
+ copyWritableHyperlink(h, s);
+ }
+ }
+
+ /**
+ * Copies a hyperlink read in from a read only sheet
+ */
+ private void copyReadHyperlink(Hyperlink h, WritableSheet s)
+ {
+ jxl.read.biff.HyperlinkRecord hl = (jxl.read.biff.HyperlinkRecord) h;
+
+ data = hl.getRecord().getData();
+ sheet = s;
+
+ // Populate this hyperlink with the copied data
+ firstRow = hl.getRow();
+ firstColumn = hl.getColumn();
+ lastRow = hl.getLastRow();
+ lastColumn = hl.getLastColumn();
+ range = new SheetRangeImpl(s,
+ firstColumn, firstRow,
+ lastColumn, lastRow);
+
+ linkType = unknown;
+
+ if (hl.isFile())
+ {
+ linkType = fileLink;
+ file = hl.getFile();
+ }
+ else if (hl.isURL())
+ {
+ linkType = urlLink;
+ url = hl.getURL();
+ }
+ else if (hl.isLocation())
+ {
+ linkType = workbookLink;
+ location = hl.getLocation();
+ }
+
+ modified = false;
+ }
+
+ /**
+ * Copies a hyperlink read in from a writable sheet.
+ * Used when copying writable sheets
+ *
+ * @param hl the hyperlink from the read spreadsheet
+ */
+ private void copyWritableHyperlink(Hyperlink hl, WritableSheet s)
+ {
+ HyperlinkRecord h = (HyperlinkRecord) hl;
+
+ firstRow = h.firstRow;
+ lastRow = h.lastRow;
+ firstColumn = h.firstColumn;
+ lastColumn = h.lastColumn;
+
+ if (h.url != null)
+ {
+ try
+ {
+ url = new URL(h.url.toString());
+ }
+ catch (MalformedURLException e)
+ {
+ // should never get a malformed url as a result url.toString()
+ Assert.verify(false);
+ }
+ }
+
+ if (h.file != null)
+ {
+ file = new File(h.file.getPath());
+ }
+
+ location = h.location;
+ contents = h.contents;
+ linkType = h.linkType;
+ modified = true;
+
+ sheet = s;
+ range = new SheetRangeImpl(s,
+ firstColumn, firstRow,
+ lastColumn, lastRow);
+ }
+
+ /**
+ * Constructs a URL hyperlink to a range of cells
+ *
+ * @param col the column containing this hyperlink
+ * @param row the row containing this hyperlink
+ * @param lastcol the last column which activates this hyperlink
+ * @param lastrow the last row which activates this hyperlink
+ * @param url the hyperlink
+ * @param desc the description
+ */
+ protected HyperlinkRecord(int col, int row,
+ int lastcol, int lastrow,
+ URL url,
+ String desc)
+ {
+ super(Type.HLINK);
+
+ firstColumn = col;
+ firstRow = row;
+
+ lastColumn = Math.max(firstColumn, lastcol);
+ lastRow = Math.max(firstRow, lastrow);
+
+ this.url = url;
+ contents = desc;
+
+ linkType = urlLink;
+
+ modified = true;
+ }
+
+ /**
+ * Constructs a File hyperlink to a range of cells
+ *
+ * @param col the column containing this hyperlink
+ * @param row the row containing this hyperlink
+ * @param lastcol the last column which activates this hyperlink
+ * @param lastrow the last row which activates this hyperlink
+ * @param file the hyperlink
+ * @param desc the description
+ */
+ protected HyperlinkRecord(int col, int row, int lastcol, int lastrow,
+ File file, String desc)
+ {
+ super(Type.HLINK);
+
+ firstColumn = col;
+ firstRow = row;
+
+ lastColumn = Math.max(firstColumn, lastcol);
+ lastRow = Math.max(firstRow, lastrow);
+ contents = desc;
+
+ this.file = file;
+
+ if (file.getPath().startsWith("\\\\"))
+ {
+ linkType = uncLink;
+ }
+ else
+ {
+ linkType = fileLink;
+ }
+
+ modified = true;
+ }
+
+ /**
+ * Constructs a hyperlink to some cells within this workbook
+ *
+ * @param col the column containing this hyperlink
+ * @param row the row containing this hyperlink
+ * @param lastcol the last column which activates this hyperlink
+ * @param lastrow the last row which activates this hyperlink
+ * @param desc the contents of the cell which describe this hyperlink
+ * @param sheet the sheet containing the cells to be linked to
+ * @param destcol the column number of the first destination linked cell
+ * @param destrow the row number of the first destination linked cell
+ * @param lastdestcol the column number of the last destination linked cell
+ * @param lastdestrow the row number of the last destination linked cell
+ */
+ protected HyperlinkRecord(int col, int row,
+ int lastcol, int lastrow,
+ String desc,
+ WritableSheet s,
+ int destcol, int destrow,
+ int lastdestcol, int lastdestrow)
+ {
+ super(Type.HLINK);
+
+ firstColumn = col;
+ firstRow = row;
+
+ lastColumn = Math.max(firstColumn, lastcol);
+ lastRow = Math.max(firstRow, lastrow);
+
+ setLocation(s, destcol, destrow, lastdestcol, lastdestrow);
+ contents = desc;
+
+ linkType = workbookLink;
+
+ modified = true;
+ }
+
+ /**
+ * Determines whether this is a hyperlink to a file
+ *
+ * @return TRUE if this is a hyperlink to a file, FALSE otherwise
+ */
+ public boolean isFile()
+ {
+ return linkType == fileLink;
+ }
+
+ /**
+ * Determines whether this is a hyperlink to a UNC
+ *
+ * @return TRUE if this is a hyperlink to a UNC, FALSE otherwise
+ */
+ public boolean isUNC()
+ {
+ return linkType == uncLink;
+ }
+
+ /**
+ * Determines whether this is a hyperlink to a web resource
+ *
+ * @return TRUE if this is a URL
+ */
+ public boolean isURL()
+ {
+ return linkType == urlLink;
+ }
+
+ /**
+ * Determines whether this is a hyperlink to a location in this workbook
+ *
+ * @return TRUE if this is a link to an internal location
+ */
+ public boolean isLocation()
+ {
+ return linkType == workbookLink;
+ }
+
+ /**
+ * Returns the row number of the top left cell
+ *
+ * @return the row number of this cell
+ */
+ public int getRow()
+ {
+ return firstRow;
+ }
+
+ /**
+ * Returns the column number of the top left cell
+ *
+ * @return the column number of this cell
+ */
+ public int getColumn()
+ {
+ return firstColumn;
+ }
+
+ /**
+ * Returns the row number of the bottom right cell
+ *
+ * @return the row number of this cell
+ */
+ public int getLastRow()
+ {
+ return lastRow;
+ }
+
+ /**
+ * Returns the column number of the bottom right cell
+ *
+ * @return the column number of this cell
+ */
+ public int getLastColumn()
+ {
+ return lastColumn;
+ }
+
+ /**
+ * Gets the URL referenced by this Hyperlink
+ *
+ * @return the URL, or NULL if this hyperlink is not a URL
+ */
+ public URL getURL()
+ {
+ return url;
+ }
+
+ /**
+ * Returns the local file eferenced by this Hyperlink
+ *
+ * @return the file, or NULL if this hyperlink is not a file
+ */
+ public File getFile()
+ {
+ return file;
+ }
+
+ /**
+ * Gets the binary data to be written to the output file
+ *
+ * @return the data to write to file
+ */
+ public byte[] getData()
+ {
+ if (!modified)
+ {
+ return data;
+ }
+
+ // Build up the common data
+ byte[] commonData = new byte[32];
+
+ // Set the range of cells this hyperlink applies to
+ IntegerHelper.getTwoBytes(firstRow, commonData, 0);
+ IntegerHelper.getTwoBytes(lastRow, commonData, 2);
+ IntegerHelper.getTwoBytes(firstColumn, commonData, 4);
+ IntegerHelper.getTwoBytes(lastColumn, commonData, 6);
+
+ // Some inexplicable byte sequence
+ commonData[8] = (byte) 0xd0;
+ commonData[9] = (byte) 0xc9;
+ commonData[10] = (byte) 0xea;
+ commonData[11] = (byte) 0x79;
+ commonData[12] = (byte) 0xf9;
+ commonData[13] = (byte) 0xba;
+ commonData[14] = (byte) 0xce;
+ commonData[15] = (byte) 0x11;
+ commonData[16] = (byte) 0x8c;
+ commonData[17] = (byte) 0x82;
+ commonData[18] = (byte) 0x0;
+ commonData[19] = (byte) 0xaa;
+ commonData[20] = (byte) 0x0;
+ commonData[21] = (byte) 0x4b;
+ commonData[22] = (byte) 0xa9;
+ commonData[23] = (byte) 0x0b;
+ commonData[24] = (byte) 0x2;
+ commonData[25] = (byte) 0x0;
+ commonData[26] = (byte) 0x0;
+ commonData[27] = (byte) 0x0;
+
+ // Set up the option flags to indicate the type of this URL. There
+ // is no description
+ int optionFlags = 0;
+ if (isURL())
+ {
+ optionFlags = 3;
+
+ if (contents != null)
+ {
+ optionFlags |= 0x14;
+ }
+ }
+ else if (isFile())
+ {
+ optionFlags = 1;
+
+ if (contents != null)
+ {
+ optionFlags |= 0x14;
+ }
+ }
+ else if (isLocation())
+ {
+ optionFlags = 8;
+ }
+ else if (isUNC())
+ {
+ optionFlags = 259;
+ }
+
+ IntegerHelper.getFourBytes(optionFlags, commonData, 28);
+
+ if (isURL())
+ {
+ data = getURLData(commonData);
+ }
+ else if (isFile())
+ {
+ data = getFileData(commonData);
+ }
+ else if (isLocation())
+ {
+ data = getLocationData(commonData);
+ }
+ else if (isUNC())
+ {
+ data = getUNCData(commonData);
+ }
+
+ return data;
+ }
+
+ /**
+ * A standard toString method
+ *
+ * @return the contents of this object as a string
+ */
+ public String toString()
+ {
+ if (isFile())
+ {
+ return file.toString();
+ }
+ else if (isURL())
+ {
+ return url.toString();
+ }
+ else if (isUNC())
+ {
+ return file.toString();
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ /**
+ * Gets the range of cells which activate this hyperlink
+ * The get sheet index methods will all return -1, because the
+ * cells will all be present on the same sheet
+ *
+ * @return the range of cells which activate the hyperlink or NULL
+ * if this hyperlink has not been added to the sheet
+ */
+ public Range getRange()
+ {
+ return range;
+ }
+
+ /**
+ * Sets the URL of this hyperlink
+ *
+ * @param url the url
+ */
+ public void setURL(URL url)
+ {
+ URL prevurl = this.url;
+ linkType = urlLink;
+ file = null;
+ location = null;
+ contents = null;
+ this.url = url;
+ modified = true;
+
+ if (sheet == null)
+ {
+ // hyperlink has not been added to the sheet yet, so simply return
+ return;
+ }
+
+ // Change the label on the sheet if it was a string representation of the
+ // URL
+ WritableCell wc = sheet.getWritableCell(firstColumn, firstRow);
+
+ if (wc.getType() == CellType.LABEL)
+ {
+ Label l = (Label) wc;
+ String prevurlString = prevurl.toString();
+ String prevurlString2 = "";
+ if (prevurlString.charAt(prevurlString.length() - 1) == '/' ||
+ prevurlString.charAt(prevurlString.length() - 1) == '\\')
+ {
+ prevurlString2 = prevurlString.substring(0,
+ prevurlString.length() - 1);
+ }
+
+ if (l.getString().equals(prevurlString) ||
+ l.getString().equals(prevurlString2))
+ {
+ l.setString(url.toString());
+ }
+ }
+ }
+
+ /**
+ * Sets the file activated by this hyperlink
+ *
+ * @param file the file
+ */
+ public void setFile(File file)
+ {
+ linkType = fileLink;
+ url = null;
+ location = null;
+ contents = null;
+ this.file = file;
+ modified = true;
+
+ if (sheet == null)
+ {
+ // hyperlink has not been added to the sheet yet, so simply return
+ return;
+ }
+
+ // Change the label on the sheet
+ WritableCell wc = sheet.getWritableCell(firstColumn, firstRow);
+
+ Assert.verify(wc.getType() == CellType.LABEL);
+
+ Label l = (Label) wc;
+ l.setString(file.toString());
+ }
+
+ /**
+ * Sets the location of the cells to be linked to within this workbook
+ *
+ * @param desc the label describing the link
+ * @param sheet the sheet containing the cells to be linked to
+ * @param destcol the column number of the first destination linked cell
+ * @param destrow the row number of the first destination linked cell
+ * @param lastdestcol the column number of the last destination linked cell
+ * @param lastdestrow the row number of the last destination linked cell
+ */
+ protected void setLocation(String desc,
+ WritableSheet sheet,
+ int destcol, int destrow,
+ int lastdestcol, int lastdestrow)
+ {
+ linkType = workbookLink;
+ url = null;
+ file = null;
+ modified = true;
+ contents = desc;
+
+ setLocation(sheet, destcol, destrow, lastdestcol, lastdestrow);
+
+ if (sheet == null)
+ {
+ // hyperlink has not been added to the sheet yet, so simply return
+ return;
+ }
+
+ // Change the label on the sheet
+ WritableCell wc = sheet.getWritableCell(firstColumn, firstRow);
+
+ Assert.verify(wc.getType() == CellType.LABEL);
+
+ Label l = (Label) wc;
+ l.setString(desc);
+ }
+
+ /**
+ * Initializes the location from the data passed in
+ *
+ * @param sheet the sheet containing the cells to be linked to
+ * @param destcol the column number of the first destination linked cell
+ * @param destrow the row number of the first destination linked cell
+ * @param lastdestcol the column number of the last destination linked cell
+ * @param lastdestrow the row number of the last destination linked cell
+ */
+ private void setLocation(WritableSheet sheet,
+ int destcol, int destrow,
+ int lastdestcol, int lastdestrow)
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append('\'');
+
+ if (sheet.getName().indexOf('\'') == -1)
+ {
+ sb.append(sheet.getName());
+ }
+ else
+ {
+ // sb.append(sheet.getName().replaceAll("'", "''"));
+
+ // Can't use replaceAll as it is only 1.4 compatible, so have to
+ // do this the tedious way
+ String sheetName = sheet.getName();
+ int pos = 0 ;
+ int nextPos = sheetName.indexOf('\'', pos);
+
+ while (nextPos != -1 && pos < sheetName.length())
+ {
+ sb.append(sheetName.substring(pos, nextPos));
+ sb.append("''");
+ pos = nextPos + 1;
+ nextPos = sheetName.indexOf('\'', pos);
+ }
+ sb.append(sheetName.substring(pos));
+ }
+
+ sb.append('\'');
+ sb.append('!');
+
+ lastdestcol = Math.max(destcol, lastdestcol);
+ lastdestrow = Math.max(destrow, lastdestrow);
+
+ CellReferenceHelper.getCellReference(destcol, destrow, sb);
+ sb.append(':');
+ CellReferenceHelper.getCellReference(lastdestcol, lastdestrow, sb);
+
+ location = sb.toString();
+ }
+
+ /**
+ * A row has been inserted, so adjust the range objects accordingly
+ *
+ * @param r the row which has been inserted
+ */
+ void insertRow(int r)
+ {
+ // This will not be called unless the hyperlink has been added to the
+ // sheet
+ Assert.verify(sheet != null && range != null);
+
+ if (r > lastRow)
+ {
+ return;
+ }
+
+ if (r <= firstRow)
+ {
+ firstRow++;
+ modified = true;
+ }
+
+ if (r <= lastRow)
+ {
+ lastRow++;
+ modified = true;
+ }
+
+ if (modified)
+ {
+ range = new SheetRangeImpl(sheet,
+ firstColumn, firstRow,
+ lastColumn, lastRow);
+ }
+ }
+
+ /**
+ * A column has been inserted, so adjust the range objects accordingly
+ *
+ * @param c the column which has been inserted
+ */
+ void insertColumn(int c)
+ {
+ // This will not be called unless the hyperlink has been added to the
+ // sheet
+ Assert.verify(sheet != null && range != null);
+
+ if (c > lastColumn)
+ {
+ return;
+ }
+
+ if (c <= firstColumn)
+ {
+ firstColumn++;
+ modified = true;
+ }
+
+ if (c <= lastColumn)
+ {
+ lastColumn++;
+ modified = true;
+ }
+
+ if (modified)
+ {
+ range = new SheetRangeImpl(sheet,
+ firstColumn, firstRow,
+ lastColumn, lastRow);
+ }
+ }
+
+ /**
+ * A row has been removed, so adjust the range objects accordingly
+ *
+ * @param r the row which has been inserted
+ */
+ void removeRow(int r)
+ {
+ // This will not be called unless the hyperlink has been added to the
+ // sheet
+ Assert.verify(sheet != null && range != null);
+
+ if (r > lastRow)
+ {
+ return;
+ }
+
+ if (r < firstRow)
+ {
+ firstRow--;
+ modified = true;
+ }
+
+ if (r < lastRow)
+ {
+ lastRow--;
+ modified = true;
+ }
+
+ if (modified)
+ {
+ Assert.verify(range != null);
+ range = new SheetRangeImpl(sheet,
+ firstColumn, firstRow,
+ lastColumn, lastRow);
+ }
+ }
+
+ /**
+ * A column has been removed, so adjust the range objects accordingly
+ *
+ * @param c the column which has been removed
+ */
+ void removeColumn(int c)
+ {
+ // This will not be called unless the hyperlink has been added to the
+ // sheet
+ Assert.verify(sheet != null && range != null);
+
+ if (c > lastColumn)
+ {
+ return;
+ }
+
+ if (c < firstColumn)
+ {
+ firstColumn--;
+ modified = true;
+ }
+
+ if (c < lastColumn)
+ {
+ lastColumn--;
+ modified = true;
+ }
+
+ if (modified)
+ {
+ Assert.verify(range != null);
+ range = new SheetRangeImpl(sheet,
+ firstColumn, firstRow,
+ lastColumn, lastRow);
+ }
+ }
+
+ /**
+ * Gets the hyperlink stream specific to a URL link
+ *
+ * @param cd the data common for all types of hyperlink
+ * @return the raw data for a URL hyperlink
+ */
+ private byte[] getURLData(byte[] cd)
+ {
+ String urlString = url.toString();
+
+ int dataLength = cd.length + 20 + (urlString.length() + 1)* 2;
+
+ if (contents != null)
+ {
+ dataLength += 4 + (contents.length() + 1) * 2;
+ }
+
+ byte[] d = new byte[dataLength];
+
+ System.arraycopy(cd, 0, d, 0, cd.length);
+
+ int urlPos = cd.length;
+
+ if (contents != null)
+ {
+ IntegerHelper.getFourBytes(contents.length() + 1, d, urlPos);
+ StringHelper.getUnicodeBytes(contents, d, urlPos + 4);
+ urlPos += (contents.length() + 1) * 2 + 4;
+ }
+
+ // Inexplicable byte sequence
+ d[urlPos] = (byte) 0xe0;
+ d[urlPos+1] = (byte) 0xc9;
+ d[urlPos+2] = (byte) 0xea;
+ d[urlPos+3] = (byte) 0x79;
+ d[urlPos+4] = (byte) 0xf9;
+ d[urlPos+5] = (byte) 0xba;
+ d[urlPos+6] = (byte) 0xce;
+ d[urlPos+7] = (byte) 0x11;
+ d[urlPos+8] = (byte) 0x8c;
+ d[urlPos+9] = (byte) 0x82;
+ d[urlPos+10] = (byte) 0x0;
+ d[urlPos+11] = (byte) 0xaa;
+ d[urlPos+12] = (byte) 0x0;
+ d[urlPos+13] = (byte) 0x4b;
+ d[urlPos+14] = (byte) 0xa9;
+ d[urlPos+15] = (byte) 0x0b;
+
+ // Number of characters in the url, including a zero trailing character
+ IntegerHelper.getFourBytes((urlString.length() + 1)*2, d, urlPos+16);
+
+ // Put the url into the data string
+ StringHelper.getUnicodeBytes(urlString, d, urlPos+20);
+
+ return d;
+ }
+
+ /**
+ * Gets the hyperlink stream specific to a URL link
+ *
+ * @param cd the data common for all types of hyperlink
+ * @return the raw data for a URL hyperlink
+ */
+ private byte[] getUNCData(byte[] cd)
+ {
+ String uncString = file.getPath();
+
+ byte[] d = new byte[cd.length + uncString.length() * 2 + 2 + 4];
+ System.arraycopy(cd, 0, d, 0, cd.length);
+
+ int urlPos = cd.length;
+
+ // The length of the unc string, including zero terminator
+ int length = uncString.length() + 1;
+ IntegerHelper.getFourBytes(length, d, urlPos);
+
+ // Place the string into the stream
+ StringHelper.getUnicodeBytes(uncString, d, urlPos + 4);
+
+ return d;
+ }
+
+ /**
+ * Gets the hyperlink stream specific to a local file link
+ *
+ * @param cd the data common for all types of hyperlink
+ * @return the raw data for a URL hyperlink
+ */
+ private byte[] getFileData(byte[] cd)
+ {
+ // Build up the directory hierarchy in reverse order
+ ArrayList path = new ArrayList();
+ ArrayList shortFileName = new ArrayList();
+ path.add(file.getName());
+ shortFileName.add(getShortName(file.getName()));
+
+ File parent = file.getParentFile();
+ while (parent != null)
+ {
+ path.add(parent.getName());
+ shortFileName.add(getShortName(parent.getName()));
+ parent = parent.getParentFile();
+ }
+
+ // Deduce the up directory level count and remove the directory from
+ // the path
+ int upLevelCount = 0;
+ int pos = path.size() - 1;
+ boolean upDir = true;
+
+ while (upDir)
+ {
+ String s = (String) path.get(pos);
+ if (s.equals(".."))
+ {
+ upLevelCount++;
+ path.remove(pos);
+ shortFileName.remove(pos);
+ }
+ else
+ {
+ upDir = false;
+ }
+
+ pos--;
+ }
+
+ StringBuffer filePathSB = new StringBuffer();
+ StringBuffer shortFilePathSB = new StringBuffer();
+
+ if (file.getPath().charAt(1)==':')
+ {
+ char driveLetter = file.getPath().charAt(0);
+ if (driveLetter != 'C' && driveLetter != 'c')
+ {
+ filePathSB.append(driveLetter);
+ filePathSB.append(':');
+ shortFilePathSB.append(driveLetter);
+ shortFilePathSB.append(':');
+ }
+ }
+
+ for (int i = path.size() - 1; i >= 0 ; i--)
+ {
+ filePathSB.append((String)path.get(i));
+ shortFilePathSB.append((String)shortFileName.get(i));
+
+ if (i != 0)
+ {
+ filePathSB.append("\\");
+ shortFilePathSB.append("\\");
+ }
+ }
+
+
+ String filePath = filePathSB.toString();
+ String shortFilePath = shortFilePathSB.toString();
+
+ int dataLength = cd.length +
+ 4 + (shortFilePath.length() + 1) + // short file name
+ 16 + // inexplicable byte sequence
+ 2 + // up directory level count
+ 8 + (filePath.length() + 1) * 2 + // long file name
+ 24; // inexplicable byte sequence
+
+
+ if (contents != null)
+ {
+ dataLength += 4 + (contents.length() + 1) * 2;
+ }
+
+ // Copy across the common data into the new array
+ byte[] d = new byte[dataLength];
+
+ System.arraycopy(cd, 0, d, 0, cd.length);
+
+ int filePos = cd.length;
+
+ // Add in the description text
+ if (contents != null)
+ {
+ IntegerHelper.getFourBytes(contents.length() + 1, d, filePos);
+ StringHelper.getUnicodeBytes(contents, d, filePos + 4);
+ filePos += (contents.length() + 1) * 2 + 4;
+ }
+
+ int curPos = filePos;
+
+ // Inexplicable byte sequence
+ d[curPos] = (byte) 0x03;
+ d[curPos+1] = (byte) 0x03;
+ d[curPos+2] = (byte) 0x0;
+ d[curPos+3] = (byte) 0x0;
+ d[curPos+4] = (byte) 0x0;
+ d[curPos+5] = (byte) 0x0;
+ d[curPos+6] = (byte) 0x0;
+ d[curPos+7] = (byte) 0x0;
+ d[curPos+8] = (byte) 0xc0;
+ d[curPos+9] = (byte) 0x0;
+ d[curPos+10] = (byte) 0x0;
+ d[curPos+11] = (byte) 0x0;
+ d[curPos+12] = (byte) 0x0;
+ d[curPos+13] = (byte) 0x0;
+ d[curPos+14] = (byte) 0x0;
+ d[curPos+15] = (byte) 0x46;
+
+ curPos += 16;
+
+ // The directory up level count
+ IntegerHelper.getTwoBytes(upLevelCount, d, curPos);
+ curPos += 2;
+
+ // The number of bytes in the short file name, including zero terminator
+ IntegerHelper.getFourBytes((shortFilePath.length() + 1), d, curPos);
+
+ // The short file name
+ StringHelper.getBytes(shortFilePath, d, curPos+4);
+
+ curPos += 4 + (shortFilePath.length() + 1);
+
+ // Inexplicable byte sequence
+ d[curPos] = (byte) 0xff;
+ d[curPos+1] = (byte) 0xff;
+ d[curPos+2] = (byte) 0xad;
+ d[curPos+3] = (byte) 0xde;
+ d[curPos+4] = (byte) 0x0;
+ d[curPos+5] = (byte) 0x0;
+ d[curPos+6] = (byte) 0x0;
+ d[curPos+7] = (byte) 0x0;
+ d[curPos+8] = (byte) 0x0;
+ d[curPos+9] = (byte) 0x0;
+ d[curPos+10] = (byte) 0x0;
+ d[curPos+11] = (byte) 0x0;
+ d[curPos+12] = (byte) 0x0;
+ d[curPos+13] = (byte) 0x0;
+ d[curPos+14] = (byte) 0x0;
+ d[curPos+15] = (byte) 0x0;
+ d[curPos+16] = (byte) 0x0;
+ d[curPos+17] = (byte) 0x0;
+ d[curPos+18] = (byte) 0x0;
+ d[curPos+19] = (byte) 0x0;
+ d[curPos+20] = (byte) 0x0;
+ d[curPos+21] = (byte) 0x0;
+ d[curPos+22] = (byte) 0x0;
+ d[curPos+23] = (byte) 0x0;
+
+ curPos += 24;
+
+ // Size of the long file name data in bytes, including inexplicable data
+ // fields
+ int size = 6 + filePath.length() * 2;
+ IntegerHelper.getFourBytes(size, d, curPos);
+ curPos += 4;
+
+ // The number of bytes in the long file name
+ // NOT including zero terminator
+ IntegerHelper.getFourBytes((filePath.length()) * 2, d, curPos);
+ curPos += 4;
+
+ // Inexplicable bytes
+ d[curPos] = (byte) 0x3;
+ d[curPos+1] = (byte) 0x0;
+
+ curPos += 2;
+
+ // The long file name
+ StringHelper.getUnicodeBytes(filePath, d, curPos);
+ curPos += (filePath.length() + 1) * 2;
+
+
+ /*
+ curPos += 24;
+ int nameLength = filePath.length() * 2;
+
+ // Size of the file link
+ IntegerHelper.getFourBytes(nameLength+6, d, curPos);
+
+ // Number of characters
+ IntegerHelper.getFourBytes(nameLength, d, curPos+4);
+
+ // Inexplicable byte sequence
+ d[curPos+8] = 0x03;
+
+ // The long file name
+ StringHelper.getUnicodeBytes(filePath, d, curPos+10);
+ */
+
+ return d;
+ }
+
+ /**
+ * Gets the DOS short file name in 8.3 format of the name passed in
+ *
+ * @param s the name
+ * @return the dos short name
+ */
+ private String getShortName(String s)
+ {
+ int sep = s.indexOf('.');
+
+ String prefix = null;
+ String suffix = null;
+
+ if (sep == -1)
+ {
+ prefix = s;
+ suffix="";
+ }
+ else
+ {
+ prefix = s.substring(0,sep);
+ suffix = s.substring(sep+1);
+ }
+
+ if (prefix.length() > 8)
+ {
+ prefix = prefix.substring(0, 6) + "~" + (prefix.length() - 8);
+ prefix = prefix.substring(0, 8);
+ }
+
+ suffix = suffix.substring(0,Math.min(3, suffix.length()));
+
+ if (suffix.length() > 0)
+ {
+ return prefix + '.' + suffix;
+ }
+ else
+ {
+ return prefix;
+ }
+ }
+
+ /**
+ * Gets the hyperlink stream specific to a location link
+ *
+ * @param cd the data common for all types of hyperlink
+ * @return the raw data for a URL hyperlink
+ */
+ private byte[] getLocationData(byte[] cd)
+ {
+ byte[] d = new byte[cd.length + 4 + (location.length() + 1)* 2];
+ System.arraycopy(cd, 0, d, 0, cd.length);
+
+ int locPos = cd.length;
+
+ // The number of chars in the location string, plus a 0 terminator
+ IntegerHelper.getFourBytes(location.length() + 1, d, locPos);
+
+ // Get the location
+ StringHelper.getUnicodeBytes(location, d, locPos+4);
+
+ return d;
+ }
+
+
+ /**
+ * Initializes the range when this hyperlink is added to the sheet
+ *
+ * @param s the sheet containing this hyperlink
+ */
+ void initialize(WritableSheet s)
+ {
+ sheet = s;
+ range = new SheetRangeImpl(s,
+ firstColumn, firstRow,
+ lastColumn, lastRow);
+ }
+
+ /**
+ * Called by the worksheet. Gets the string contents to put into the cell
+ * containing this hyperlink
+ *
+ * @return the string contents for the hyperlink cell
+ */
+ String getContents()
+ {
+ return contents;
+ }
+
+ /**
+ * Sets the description
+ *
+ * @param desc the description
+ */
+ protected void setContents(String desc)
+ {
+ contents = desc;
+ modified = true;
+ }
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/IndexRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/IndexRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/IndexRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,104 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.IntegerHelper;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Index into the cell rows in an worksheet
+ */
+class IndexRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+ /**
+ * The numbe of rows served by this index record
+ */
+ private int rows;
+ /**
+ * The position of the BOF record in the excel output stream
+ */
+ private int bofPosition;
+ /**
+ * The number of blocks needed to hold all the rows
+ */
+ private int blocks;
+
+ /**
+ * The position of the current 'pointer' within the byte array
+ */
+ private int dataPos;
+
+ /**
+ * Constructor
+ *
+ * @param pos the position of the BOF record
+ * @param bl the number of blocks
+ * @param r the number of rows
+ */
+ public IndexRecord(int pos, int r, int bl)
+ {
+ super(Type.INDEX);
+ bofPosition = pos;
+ rows = r;
+ blocks = bl;
+
+ // Allocate the amount of bytes required to hold all the blocks
+ data = new byte[16 + 4 * blocks];
+ dataPos = 16;
+ }
+
+ /**
+ * Gets the binary data for output. This writes out an empty data block, and
+ * the information is filled in later on when the information becomes
+ * available
+ *
+ * @return the binary data
+ */
+ protected byte[] getData()
+ {
+ IntegerHelper.getFourBytes(rows, data, 8);
+ return data;
+ }
+
+ /**
+ * Adds another index record into the array
+ *
+ * @param pos the position in the output file
+ */
+ void addBlockPosition(int pos)
+ {
+ IntegerHelper.getFourBytes(pos - bofPosition, data, dataPos);
+ dataPos += 4;
+ }
+
+ /**
+ * Sets the position of the data start. This happens to be the position
+ * of the DEFCOLWIDTH record
+ */
+ void setDataStartPosition(int pos)
+ {
+ IntegerHelper.getFourBytes(pos - bofPosition, data, 12);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/InterfaceEndRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/InterfaceEndRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/InterfaceEndRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,48 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Marks the end of the user interface section of the Book stream.
+ * It has no data field
+ */
+class InterfaceEndRecord extends WritableRecordData
+{
+ /**
+ * Consructor
+ */
+ public InterfaceEndRecord()
+ {
+ super(Type.INTERFACEEND);
+ }
+
+ /**
+ * Gets the binary data for output
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return new byte[0];
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/InterfaceHeaderRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/InterfaceHeaderRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/InterfaceHeaderRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,52 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Marks the beginning of the user interface record
+ */
+class InterfaceHeaderRecord extends WritableRecordData
+{
+ /**
+ * Constructor
+ */
+ public InterfaceHeaderRecord()
+ {
+ super(Type.INTERFACEHDR);
+ }
+
+ /**
+ * Gets the binary data
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ // Return the character encoding
+ byte[] data = new byte[]
+ { (byte) 0xb0, (byte) 0x04};
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/IterationRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/IterationRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/IterationRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,69 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores the iteration option from the dialog box
+ */
+class IterationRecord extends WritableRecordData
+{
+ /**
+ * The iterate flag
+ */
+ private boolean iterate;
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param it the iterator flag
+ */
+ public IterationRecord(boolean it)
+ {
+ super(Type.ITERATION);
+
+ iterate = it;
+
+ data = new byte[2];
+
+ if (iterate)
+ {
+ data[0] = 1;
+ }
+ }
+
+ /**
+ * Gets the binary data for output
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/JxlWriteException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/JxlWriteException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/JxlWriteException.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,71 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.write.WriteException;
+
+/**
+ * Exception thrown when reading a biff file
+ */
+public class JxlWriteException extends WriteException
+{
+ private static class WriteMessage
+ {
+ /**
+ */
+ public String message;
+ /**
+ * Constructs this exception with the specified message
+ *
+ * @param m the messageA
+ */
+ WriteMessage(String m) {message = m;}
+ }
+
+ /**
+ */
+ static WriteMessage formatInitialized =
+ new WriteMessage("Attempt to modify a referenced format");
+ /**
+ */
+ static WriteMessage cellReferenced =
+ new WriteMessage("Cell has already been added to a worksheet");
+
+ static WriteMessage maxRowsExceeded =
+ new WriteMessage("The maximum number of rows permitted on a worksheet " +
+ "been exceeded");
+
+ static WriteMessage maxColumnsExceeded =
+ new WriteMessage("The maximum number of columns permitted on a " +
+ "worksheet has been exceeded");
+
+ static WriteMessage copyPropertySets =
+ new WriteMessage("Error encounted when copying additional property sets");
+
+ /**
+ * Constructs this exception with the specified message
+ *
+ * @param m the message
+ */
+ public JxlWriteException(WriteMessage m)
+ {
+ super(m.message);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/LabelRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/LabelRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/LabelRecord.java 17 Aug 2012 14:51:08 -0000 1.1
@@ -0,0 +1,231 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.CellType;
+import jxl.LabelCell;
+import jxl.biff.FormattingRecords;
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.format.CellFormat;
+
+/**
+ * A label record, used for writing out string
+ */
+public abstract class LabelRecord extends CellValue
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(LabelRecord.class);
+
+ /**
+ * The string
+ */
+ private String contents;
+
+ /**
+ * A handle to the shared strings used within this workbook
+ */
+ private SharedStrings sharedStrings;
+
+ /**
+ * The index of the string in the shared string table
+ */
+ private int index;
+
+ /**
+ * Constructor used when creating a label from the user API
+ *
+ * @param c the column
+ * @param cont the contents
+ * @param r the row
+ */
+ protected LabelRecord(int c, int r, String cont)
+ {
+ super(Type.LABELSST, c, r);
+ contents = cont;
+ if (contents == null)
+ {
+ contents="";
+ }
+ }
+
+ /**
+ * Constructor used when creating a label from the API. This is
+ * overloaded to allow formatting information to be passed to the record
+ *
+ * @param c the column
+ * @param cont the contents
+ * @param r the row
+ * @param st the format applied to the cell
+ */
+ protected LabelRecord(int c, int r, String cont, CellFormat st)
+ {
+ super(Type.LABELSST, c, r, st);
+ contents = cont;
+
+ if (contents == null)
+ {
+ contents="";
+ }
+ }
+
+
+ /**
+ * Copy constructor
+ *
+ * @param c the column
+ * @param r the row
+ * @param nr the record to copy
+ */
+ protected LabelRecord(int c, int r, LabelRecord lr)
+ {
+ super(Type.LABELSST, c, r, lr);
+ contents = lr.contents;
+ }
+
+ /**
+ * Constructor used when copying a label from a read only
+ * spreadsheet
+ *
+ * @param lc the label to copy
+ */
+ protected LabelRecord(LabelCell lc)
+ {
+ super(Type.LABELSST, lc);
+ contents = lc.getString();
+ if (contents == null)
+ {
+ contents = "";
+ }
+ }
+
+ /**
+ * Returns the content type of this cell
+ *
+ * @return the content type for this cell
+ */
+ public CellType getType()
+ {
+ return CellType.LABEL;
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] celldata = super.getData();
+ byte[] data = new byte[celldata.length + 4];
+ System.arraycopy(celldata, 0, data, 0, celldata.length);
+ IntegerHelper.getFourBytes(index, data, celldata.length);
+
+ return data;
+ }
+
+ /**
+ * Quick and dirty function to return the contents of this cell as a string.
+ * For more complex manipulation of the contents, it is necessary to cast
+ * this interface to correct subinterface
+ *
+ * @return the contents of this cell as a string
+ */
+ public String getContents()
+ {
+ return contents;
+ }
+
+ /**
+ * Gets the label for this cell. The value returned will be the same
+ * as for the getContents method in the base class
+ *
+ * @return the cell contents
+ */
+ public String getString()
+ {
+ return contents;
+ }
+
+ /**
+ * Sets the string contents of this cell
+ *
+ * @param s the new string contents
+ */
+ protected void setString(String s)
+ {
+ if (s == null)
+ {
+ s = "";
+ }
+
+ contents = s;
+
+ // Don't bother doing anything if this cell has not been referenced
+ // yet - everything will be set up in due course
+ if (!isReferenced())
+ {
+ return;
+ }
+
+ Assert.verify(sharedStrings != null);
+
+ // Initalize the shared string index
+ index = sharedStrings.getIndex(contents);
+
+ // Use the sharedStrings reference instead of this object's own
+ // handle - this means that the bespoke copy becomes eligible for
+ // garbage collection
+ contents = sharedStrings.get(index);
+ }
+
+ /**
+ * Overrides the method in the base class in order to add the string
+ * content to the shared string table, and to store its shared string
+ * index
+ *
+ * @param fr the formatting records
+ * @param ss the shared strings used within the workbook
+ * @param s
+ */
+ void setCellDetails(FormattingRecords fr, SharedStrings ss,
+ WritableSheetImpl s)
+ {
+ super.setCellDetails(fr, ss, s);
+
+ sharedStrings = ss;
+
+ index = sharedStrings.getIndex(contents);
+
+ // Use the sharedStrings reference instead of this object's own
+ // handle - this means that the bespoke copy becomes eligible for
+ // garbage collection
+ contents = sharedStrings.get(index);
+ }
+
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/LeftMarginRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/LeftMarginRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/LeftMarginRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,33 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+
+/**
+ * The settings for the left margin
+ */
+class LeftMarginRecord extends MarginRecord
+{
+ LeftMarginRecord(double v)
+ {
+ super(Type.LEFTMARGIN, v);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/MMSRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/MMSRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/MMSRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,71 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores the number of addmen and delmenu groups in the book stream
+ */
+class MMSRecord extends WritableRecordData
+{
+ /**
+ * The number of menu items added
+ */
+ private byte numMenuItemsAdded;
+ /**
+ * The number of menu items deleted
+ */
+ private byte numMenuItemsDeleted;
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param menuItemsAdded the number of menu items added
+ * @param menuItemsDeleted the number of menu items deleted
+ */
+ public MMSRecord(int menuItemsAdded, int menuItemsDeleted)
+ {
+ super(Type.MMS);
+
+ numMenuItemsAdded = (byte) menuItemsAdded;
+ numMenuItemsDeleted = (byte) menuItemsDeleted;
+
+ data = new byte[2];
+
+ data[0] = numMenuItemsAdded;
+ data[1] = numMenuItemsDeleted;
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/MarginRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/MarginRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/MarginRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,59 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.DoubleHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record which specifies a margin value
+ */
+abstract class MarginRecord extends WritableRecordData
+{
+ /**
+ * The margin
+ */
+ private double margin;
+
+ /**
+ * Constructor
+ */
+ public MarginRecord(Type t, double v)
+ {
+ super(t);
+ margin = v;
+ }
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[8];
+
+ DoubleHelper.getIEEEBytes(margin, data, 0);
+
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/MemoryDataOutput.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/MemoryDataOutput.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/MemoryDataOutput.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,117 @@
+/*********************************************************************
+*
+* Copyright (C) 2007 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.OutputStream;
+import java.io.IOException;
+
+import common.Logger;
+
+/**
+ * Used to generate the excel biff data in memory. This class wraps a byte
+ * array
+ */
+class MemoryDataOutput implements ExcelDataOutput
+{
+ // The logger
+ private static Logger logger = Logger.getLogger(MemoryDataOutput.class);
+
+ /**
+ * The excel data
+ */
+ private byte[] data;
+
+ /**
+ * The grow size for the array
+ */
+ private int growSize;
+
+ /**
+ * The current position within the array
+ */
+ private int pos;
+
+ /**
+ * Constructor
+ */
+ public MemoryDataOutput(int initialSize, int gs)
+ {
+ data = new byte[initialSize];
+ growSize = gs;
+ pos = 0;
+ }
+
+ /**
+ * Writes the bytes to the end of the array, growing the array
+ * as needs dictate
+ *
+ * @param d the data to write to the end of the array
+ */
+ public void write(byte[] bytes)
+ {
+ while (pos + bytes.length > data.length)
+ {
+ // Grow the array
+ byte[] newdata = new byte[data.length + growSize];
+ System.arraycopy(data, 0, newdata, 0, pos);
+ data = newdata;
+ }
+
+ System.arraycopy(bytes, 0, data, pos, bytes.length);
+ pos += bytes.length;
+ }
+
+ /**
+ * Gets the current position within the file
+ *
+ * @return the position within the file
+ */
+ public int getPosition()
+ {
+ return pos;
+ }
+
+ /**
+ * Sets the data at the specified position to the contents of the array
+ *
+ * @param pos the position to alter
+ * @param newdata the data to modify
+ */
+ public void setData(byte[] newdata, int pos)
+ {
+ System.arraycopy(newdata, 0, data, pos, newdata.length);
+ }
+
+ /**
+ * Writes the data to the output stream
+ */
+ public void writeData(OutputStream out) throws IOException
+ {
+ out.write(data, 0, pos);
+ }
+
+ /**
+ * Called when the final compound file has been written. No cleanup is
+ * necessary for in-memory file generation
+ */
+ public void close() throws IOException
+ {
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/MergedCells.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/MergedCells.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/MergedCells.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,326 @@
+/*********************************************************************
+ *
+ * Copyright (C) 2003 Andrew Khan
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.Cell;
+import jxl.CellType;
+import jxl.Range;
+import jxl.WorkbookSettings;
+import jxl.biff.SheetRangeImpl;
+import jxl.write.Blank;
+import jxl.write.WritableSheet;
+import jxl.write.WriteException;
+
+/**
+ * Contains all the merged cells, and the necessary logic for checking
+ * for intersections and for handling very large amounts of merging
+ */
+class MergedCells
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(MergedCells.class);
+
+ /**
+ * The list of merged cells
+ */
+ private ArrayList ranges;
+
+ /**
+ * The sheet containing the cells
+ */
+ private WritableSheet sheet;
+
+ /**
+ * The maximum number of ranges per sheet
+ */
+ private static final int maxRangesPerSheet = 1020;
+
+ /**
+ * Constructor
+ */
+ public MergedCells(WritableSheet ws)
+ {
+ ranges = new ArrayList();
+ sheet = ws;
+ }
+
+ /**
+ * Adds the range to the list of merged cells. Does no checking
+ * at this stage
+ *
+ * @param range the range to add
+ */
+ void add(Range r)
+ {
+ ranges.add(r);
+ }
+
+ /**
+ * Used to adjust the merged cells following a row insertion
+ */
+ void insertRow(int row)
+ {
+ // Adjust any merged cells
+ SheetRangeImpl sr = null;
+ Iterator i = ranges.iterator();
+ while (i.hasNext())
+ {
+ sr = (SheetRangeImpl) i.next();
+ sr.insertRow(row);
+ }
+ }
+
+ /**
+ * Used to adjust the merged cells following a column insertion
+ */
+ void insertColumn(int col)
+ {
+ SheetRangeImpl sr = null;
+ Iterator i = ranges.iterator();
+ while (i.hasNext())
+ {
+ sr = (SheetRangeImpl) i.next();
+ sr.insertColumn(col);
+ }
+ }
+
+ /**
+ * Used to adjust the merged cells following a column removal
+ */
+ void removeColumn(int col)
+ {
+ SheetRangeImpl sr = null;
+ Iterator i = ranges.iterator();
+ while (i.hasNext())
+ {
+ sr = (SheetRangeImpl) i.next();
+ if (sr.getTopLeft().getColumn() == col &&
+ sr.getBottomRight().getColumn() == col)
+ {
+ // The column with the merged cells on has been removed, so get
+ // rid of it from the list
+ i.remove();
+ }
+ else
+ {
+ sr.removeColumn(col);
+ }
+ }
+ }
+
+ /**
+ * Used to adjust the merged cells following a row removal
+ */
+ void removeRow(int row)
+ {
+ SheetRangeImpl sr = null;
+ Iterator i = ranges.iterator();
+ while (i.hasNext())
+ {
+ sr = (SheetRangeImpl) i.next();
+ if (sr.getTopLeft().getRow() == row &&
+ sr.getBottomRight().getRow() == row)
+ {
+ // The row with the merged cells on has been removed, so get
+ // rid of it from the list
+ i.remove();
+ }
+ else
+ {
+ sr.removeRow(row);
+ }
+ }
+ }
+
+ /**
+ * Gets the cells which have been merged on this sheet
+ *
+ * @return an array of range objects
+ */
+ Range[] getMergedCells()
+ {
+ Range[] cells = new Range[ranges.size()];
+
+ for (int i=0; i < cells.length; i++)
+ {
+ cells[i] = (Range) ranges.get(i);
+ }
+
+ return cells;
+ }
+
+ /**
+ * Unmerges the specified cells. The Range passed in should be one that
+ * has been previously returned as a result of the getMergedCells method
+ *
+ * @param r the range of cells to unmerge
+ */
+ void unmergeCells(Range r)
+ {
+ int index = ranges.indexOf(r);
+
+ if (index != -1)
+ {
+ ranges.remove(index);
+ }
+ }
+
+ /**
+ * Called prior to writing out in order to check for intersections
+ */
+ private void checkIntersections()
+ {
+ ArrayList newcells = new ArrayList(ranges.size());
+
+ for (Iterator mci = ranges.iterator(); mci.hasNext() ; )
+ {
+ SheetRangeImpl r = (SheetRangeImpl) mci.next();
+
+ // Check that the range doesn't intersect with any existing range
+ Iterator i = newcells.iterator();
+ SheetRangeImpl range = null;
+ boolean intersects = false;
+ while (i.hasNext() && !intersects)
+ {
+ range = (SheetRangeImpl) i.next();
+
+ if (range.intersects(r))
+ {
+ logger.warn("Could not merge cells " + r +
+ " as they clash with an existing set of merged cells.");
+
+ intersects = true;
+ }
+ }
+
+ if (!intersects)
+ {
+ newcells.add(r);
+ }
+ }
+
+ ranges = newcells;
+ }
+
+ /**
+ * Checks the cell ranges for intersections, or if the merged cells
+ * contains more than one item of data
+ */
+ private void checkRanges()
+ {
+ try
+ {
+ SheetRangeImpl range = null;
+
+ // Check all the ranges to make sure they only contain one entry
+ for (int i = 0; i < ranges.size(); i++)
+ {
+ range = (SheetRangeImpl) ranges.get(i);
+
+ // Get the cell in the top left
+ Cell tl = range.getTopLeft();
+ Cell br = range.getBottomRight();
+ boolean found = false;
+
+ for (int c = tl.getColumn(); c <= br.getColumn(); c++)
+ {
+ for (int r = tl.getRow(); r <= br.getRow(); r++)
+ {
+ Cell cell = sheet.getCell(c, r);
+ if (cell.getType() != CellType.EMPTY)
+ {
+ if (!found)
+ {
+ found = true;
+ }
+ else
+ {
+ logger.warn("Range " + range +
+ " contains more than one data cell. " +
+ "Setting the other cells to blank.");
+ Blank b = new Blank(c, r);
+ sheet.addCell(b);
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (WriteException e)
+ {
+ // This should already have been checked - bomb out
+ Assert.verify(false);
+ }
+ }
+
+ void write(File outputFile) throws IOException
+ {
+ if (ranges.size() == 0)
+ {
+ return;
+ }
+
+ WorkbookSettings ws =
+ ( (WritableSheetImpl) sheet).getWorkbookSettings();
+
+ if (!ws.getMergedCellCheckingDisabled())
+ {
+ checkIntersections();
+ checkRanges();
+ }
+
+ // If they will all fit into one record, then create a single
+ // record, write them and get out
+ if (ranges.size() < maxRangesPerSheet)
+ {
+ MergedCellsRecord mcr = new MergedCellsRecord(ranges);
+ outputFile.write(mcr);
+ return;
+ }
+
+ int numRecordsRequired = ranges.size() / maxRangesPerSheet + 1;
+ int pos = 0;
+
+ for (int i = 0 ; i < numRecordsRequired ; i++)
+ {
+ int numranges = Math.min(maxRangesPerSheet, ranges.size() - pos);
+
+ ArrayList cells = new ArrayList(numranges);
+ for (int j = 0 ; j < numranges ; j++)
+ {
+ cells.add(ranges.get(pos+j));
+ }
+
+ MergedCellsRecord mcr = new MergedCellsRecord(cells);
+ outputFile.write(mcr);
+
+ pos += numranges;
+ }
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/MergedCellsRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/MergedCellsRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/MergedCellsRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,93 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.util.ArrayList;
+
+import jxl.Cell;
+import jxl.Range;
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * A number record. This is stored as 8 bytes, as opposed to the
+ * 4 byte RK record
+ */
+public class MergedCellsRecord extends WritableRecordData
+{
+ /**
+ * The ranges of all the cells which are merged on this sheet
+ */
+ private ArrayList ranges;
+
+ /**
+ * Constructs a merged cell record
+ *
+ * @param ws the sheet containing the merged cells
+ */
+ protected MergedCellsRecord(ArrayList mc)
+ {
+ super(Type.MERGEDCELLS);
+
+ ranges = mc;
+ }
+
+ /**
+ * Gets the raw data for output to file
+ *
+ * @return the data to write to file
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[ranges.size() * 8 + 2];
+
+ // Set the number of ranges
+ IntegerHelper.getTwoBytes(ranges.size(), data, 0);
+
+ int pos = 2;
+ Range range = null;
+ for (int i = 0; i < ranges.size() ; i++)
+ {
+ range = (Range) ranges.get(i);
+
+ // Set the various cell records
+ Cell tl = range.getTopLeft();
+ Cell br = range.getBottomRight();
+
+ IntegerHelper.getTwoBytes(tl.getRow(), data, pos);
+ IntegerHelper.getTwoBytes(br.getRow(), data, pos+2);
+ IntegerHelper.getTwoBytes(tl.getColumn(), data, pos+4);
+ IntegerHelper.getTwoBytes(br.getColumn(), data, pos+6);
+
+ pos += 8;
+ }
+
+ return data;
+ }
+
+}
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/MulRKRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/MulRKRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/MulRKRecord.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,120 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.util.List;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+import jxl.write.Number;
+
+/**
+ * Contains an array of RK numbers
+ */
+class MulRKRecord extends WritableRecordData
+{
+ /**
+ * The row containing these numbers
+ */
+ private int row;
+ /**
+ * The first column these rk number occur on
+ */
+ private int colFirst;
+ /**
+ * The last column these rk number occur on
+ */
+ private int colLast;
+ /**
+ * The array of rk numbers
+ */
+ private int[] rknumbers;
+ /**
+ * The array of xf indices
+ */
+ private int[] xfIndices;
+
+ /**
+ * Constructs the rk numbers from the integer cells
+ *
+ * @param numbers A list of jxl.write.Number objects
+ */
+ public MulRKRecord(List numbers)
+ {
+ super(Type.MULRK);
+ row = ((Number)numbers.get(0)).getRow();
+ colFirst = ((Number)numbers.get(0)).getColumn();
+ colLast = colFirst + numbers.size() - 1;
+
+ rknumbers = new int[numbers.size()];
+ xfIndices = new int[numbers.size()];
+
+ for (int i = 0; i < numbers.size(); i++)
+ {
+ rknumbers[i] = (int) ((Number)numbers.get(i)).getValue();
+ xfIndices[i] = ( (CellValue) numbers.get(i)).getXFIndex();
+ }
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[rknumbers.length * 6 + 6];
+
+ // Set up the row and the first column
+ IntegerHelper.getTwoBytes(row, data, 0);
+ IntegerHelper.getTwoBytes(colFirst, data, 2);
+
+ // Add all the rk numbers
+ int pos = 4;
+ int rkValue = 0;
+ byte[] rkBytes = new byte[4];
+ for (int i = 0; i < rknumbers.length; i++)
+ {
+ IntegerHelper.getTwoBytes(xfIndices[i], data, pos);
+
+ // To represent an int as an Excel RK value, we have to
+ // undergo some outrageous jiggery pokery, as follows:
+
+ // Gets the bit representation of the number
+ rkValue = rknumbers[i] << 2;
+
+ // Set the integer bit
+ rkValue |= 0x2;
+ IntegerHelper.getFourBytes(rkValue, data, pos+2);
+
+ pos+=6;
+ }
+
+ // Write the number of rk numbers in this record
+ IntegerHelper.getTwoBytes(colLast, data, pos);
+
+ return data;
+ }
+}
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/NameRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/NameRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/NameRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,655 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Logger;
+
+import jxl.biff.BuiltInName;
+import jxl.biff.IntegerHelper;
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * A name record. Simply takes the binary data from the name
+ * record read in
+ */
+class NameRecord extends WritableRecordData
+{
+ // The logger
+ private static Logger logger = Logger.getLogger(NameRecord.class);
+ /**
+ * The binary data for output to file
+ */
+ private byte[] data;
+
+ /**
+ * The name
+ */
+ private String name;
+
+ /**
+ * The built in name
+ */
+ private BuiltInName builtInName;
+
+ /**
+ * The index into the name table
+ */
+ private int index;
+
+ /**
+ * The 0-based index sheet reference for a record name
+ * 0 is for a global reference
+ */
+ private int sheetRef = 0;
+
+ /**
+ * Modified flag
+ */
+ private boolean modified;
+
+ /**
+ * A nested class to hold range information
+ */
+ static class NameRange
+ {
+ private int columnFirst;
+ private int rowFirst;
+ private int columnLast;
+ private int rowLast;
+ private int externalSheet;
+
+ NameRange(jxl.read.biff.NameRecord.NameRange nr)
+ {
+ columnFirst = nr.getFirstColumn();
+ rowFirst = nr.getFirstRow();
+ columnLast = nr.getLastColumn();
+ rowLast = nr.getLastRow();
+ externalSheet = nr.getExternalSheet();
+ }
+
+ /**
+ * Create a new range for the name record.
+ */
+ NameRange(int extSheet,
+ int theStartRow,
+ int theEndRow,
+ int theStartCol,
+ int theEndCol)
+ {
+ columnFirst = theStartCol;
+ rowFirst = theStartRow;
+ columnLast = theEndCol;
+ rowLast = theEndRow;
+ externalSheet = extSheet;
+ }
+
+ int getFirstColumn() {return columnFirst;}
+ int getFirstRow() {return rowFirst;}
+ int getLastColumn() {return columnLast;}
+ int getLastRow() {return rowLast;}
+ int getExternalSheet() { return externalSheet;}
+
+ void incrementFirstRow() { rowFirst++ ; }
+ void incrementLastRow() { rowLast++ ; }
+ void decrementFirstRow() { rowFirst-- ; }
+ void decrementLastRow() { rowLast-- ; }
+ void incrementFirstColumn() { columnFirst++ ; }
+ void incrementLastColumn() { columnLast++ ; }
+ void decrementFirstColumn() { columnFirst-- ; }
+ void decrementLastColumn() { columnLast-- ; }
+
+ byte[] getData()
+ {
+ byte[] d = new byte[10];
+
+ // Sheet index
+ IntegerHelper.getTwoBytes(externalSheet, d, 0);
+
+ // Starting row
+ IntegerHelper.getTwoBytes(rowFirst, d, 2);
+
+ // End row
+ IntegerHelper.getTwoBytes(rowLast, d, 4);
+
+ // Start column
+ IntegerHelper.getTwoBytes(columnFirst & 0xff, d, 6);
+
+ // End columns
+ IntegerHelper.getTwoBytes(columnLast & 0xff, d, 8);
+
+ return d;
+ }
+ }
+
+ /**
+ * The ranges covered by this name
+ */
+ private NameRange[] ranges;
+
+ // Constants which refer to the parse tokens after the string
+ private static final int cellReference = 0x3a;
+ private static final int areaReference = 0x3b;
+ private static final int subExpression = 0x29;
+ private static final int union = 0x10;
+
+ // An empty range
+ private static final NameRange EMPTY_RANGE = new NameRange(0,0,0,0,0);
+
+ /**
+ * Constructor - used when copying sheets
+ *
+ * @param index the index into the name table
+ */
+ public NameRecord(jxl.read.biff.NameRecord sr, int ind)
+ {
+ super(Type.NAME);
+
+ data = sr.getData();
+ name = sr.getName();
+ sheetRef = sr.getSheetRef();
+ index = ind;
+ modified = false;
+
+ // Copy the ranges
+ jxl.read.biff.NameRecord.NameRange[] r = sr.getRanges();
+ ranges = new NameRange[r.length];
+ for (int i = 0 ; i < ranges.length ; i++)
+ {
+ ranges[i] = new NameRange(r[i]);
+ }
+ }
+
+ /**
+ * Create a new name record with the given information.
+ *
+ * @param theName Name to be created.
+ * @param theIndex Index of this name.
+ * @param extSheet External sheet index this name refers to.
+ * @param theStartRow First row this name refers to.
+ * @param theEndRow Last row this name refers to.
+ * @param theStartCol First column this name refers to.
+ * @param theEndCol Last column this name refers to.
+ * @param global TRUE if this is a global name
+ */
+ NameRecord(String theName,
+ int theIndex,
+ int extSheet,
+ int theStartRow,
+ int theEndRow,
+ int theStartCol,
+ int theEndCol,
+ boolean global)
+ {
+ super(Type.NAME);
+
+ name = theName;
+ index = theIndex;
+ sheetRef = global ? 0 : index+1; // 0 indicates a global name, otherwise
+ // the 1-based index of the sheet
+
+ ranges = new NameRange[1];
+ ranges[0] = new NameRange(extSheet,
+ theStartRow,
+ theEndRow,
+ theStartCol,
+ theEndCol);
+ modified = true;
+ }
+
+ /**
+ * Create a new name record with the given information.
+ *
+ * @param theName Name to be created.
+ * @param theIndex Index of this name.
+ * @param extSheet External sheet index this name refers to.
+ * @param theStartRow First row this name refers to.
+ * @param theEndRow Last row this name refers to.
+ * @param theStartCol First column this name refers to.
+ * @param theEndCol Last column this name refers to.
+ * @param global TRUE if this is a global name
+ */
+ NameRecord(BuiltInName theName,
+ int theIndex,
+ int extSheet,
+ int theStartRow,
+ int theEndRow,
+ int theStartCol,
+ int theEndCol,
+ boolean global)
+ {
+ super(Type.NAME);
+
+ builtInName = theName;
+ index = theIndex;
+ sheetRef = global ? 0 : index + 1; // 0 indicates a global name, otherwise
+ // the 1-based index of the sheet
+
+ ranges = new NameRange[1];
+ ranges[0] = new NameRange(extSheet,
+ theStartRow,
+ theEndRow,
+ theStartCol,
+ theEndCol);
+ }
+
+ /**
+ * Create a new name record with the given information for 2-range entities.
+ *
+ * @param theName Name to be created.
+ * @param theIndex Index of this name.
+ * @param extSheet External sheet index this name refers to.
+ * @param theStartRow First row this name refers to.
+ * @param theEndRow Last row this name refers to.
+ * @param theStartCol First column this name refers to.
+ * @param theEndCol Last column this name refers to.
+ * @param theStartRow2 First row this name refers to (2nd instance).
+ * @param theEndRow2 Last row this name refers to (2nd instance).
+ * @param theStartCol2 First column this name refers to (2nd instance).
+ * @param theEndCol2 Last column this name refers to (2nd instance).
+ * @param global TRUE if this is a global name
+ */
+ NameRecord(BuiltInName theName,
+ int theIndex,
+ int extSheet,
+ int theStartRow,
+ int theEndRow,
+ int theStartCol,
+ int theEndCol,
+ int theStartRow2,
+ int theEndRow2,
+ int theStartCol2,
+ int theEndCol2,
+ boolean global)
+ {
+ super(Type.NAME);
+
+ builtInName = theName;
+ index = theIndex;
+ sheetRef = global ? 0 : index + 1; // 0 indicates a global name, otherwise
+ // the 1-based index of the sheet
+
+ ranges = new NameRange[2];
+ ranges[0] = new NameRange(extSheet,
+ theStartRow,
+ theEndRow,
+ theStartCol,
+ theEndCol);
+ ranges[1] = new NameRange(extSheet,
+ theStartRow2,
+ theEndRow2,
+ theStartCol2,
+ theEndCol2);
+ }
+
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ if (data != null && !modified)
+ {
+ // this is a copy
+ return data;
+ }
+
+ final int NAME_HEADER_LENGTH = 15;
+ final byte AREA_RANGE_LENGTH = 11;
+ final byte AREA_REFERENCE = 0x3b;
+
+ int detailLength;
+
+ if (ranges.length > 1)
+ {
+ detailLength = (ranges.length * AREA_RANGE_LENGTH) + 4;
+ }
+ else
+ {
+ detailLength = AREA_RANGE_LENGTH;
+ }
+
+ int length = NAME_HEADER_LENGTH + detailLength;
+ length += builtInName != null ? 1 : name.length();
+ data = new byte[length];
+
+ // Options
+ int options = 0;
+
+ if (builtInName != null)
+ {
+ options |= 0x20;
+ }
+ IntegerHelper.getTwoBytes(options, data, 0);
+
+ // Keyboard shortcut
+ data[2] = 0;
+
+ // Length of the name in chars
+ if (builtInName != null)
+ {
+ data[3] = (byte) 0x1;
+ }
+ else
+ {
+ data[3] = (byte) name.length();
+ }
+
+ // Size of the definitions
+ IntegerHelper.getTwoBytes(detailLength, data, 4);
+
+ // Sheet index
+ IntegerHelper.getTwoBytes(sheetRef, data, 6);
+ IntegerHelper.getTwoBytes(sheetRef, data, 8);
+
+ // Byte 10-13 are optional lengths [0,0,0,0]
+ // Byte 14 is length of name which is not used.
+
+ // The name
+ if (builtInName != null)
+ {
+ data[15] = (byte) builtInName.getValue();
+ }
+ else
+ {
+ StringHelper.getBytes(name, data, 15);
+ }
+
+ // The actual range definition.
+ int pos = builtInName != null ? 16 : name.length() + 15;
+
+ // If there are multiple ranges for the name, we must specify a
+ // subExpression type rather than areaReference and then put out
+ // multiple areaReference entries with an end byte.
+ if (ranges.length > 1)
+ {
+ data[pos++] = subExpression;
+ // Length of remaining bytes excluding itself
+ IntegerHelper.getTwoBytes(detailLength - 3, data, pos);
+ pos += 2;
+ byte[] rd;
+ for (int i = 0 ; i < ranges.length ; i++)
+ {
+ data[pos++] = areaReference;
+ rd = ranges[i].getData();
+ System.arraycopy(rd, 0, data, pos, rd.length);
+ pos += rd.length;
+ }
+ data[pos] = 0x10;
+ }
+ else
+ {
+ // Range format - area
+ data[pos] = areaReference;
+
+ // The range data
+ byte[] rd = ranges[0].getData();
+ System.arraycopy(rd, 0, data, pos+1, rd.length);
+ }
+
+ return data;
+ }
+
+ /**
+ * Accessor for the name
+ *
+ * @return the name
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Accessor for the index of this name in the name table
+ *
+ * @return the index of this name in the name table
+ */
+ public int getIndex()
+ {
+ return index;
+ }
+
+ /**
+ * The 0-based index sheet reference for a record name
+ * 0 is for a global reference
+ *
+ * @return the sheet reference for name formula
+ */
+ public int getSheetRef()
+ {
+ return sheetRef;
+ }
+
+ /**
+ * Set the index sheet reference for a record name
+ * 0 is for a global reference
+ *
+ */
+ public void setSheetRef(int i)
+ {
+ sheetRef = i;
+ IntegerHelper.getTwoBytes(sheetRef, data, 8);
+ }
+
+ /**
+ * Gets the array of ranges for this name
+ * @return the ranges
+ */
+ public NameRange[] getRanges()
+ {
+ return ranges;
+ }
+
+ /**
+ * Called when a row is inserted on the
+ *
+ * @param sheetIndex the sheet index on which the column was inserted
+ * @param row the column number which was inserted
+ */
+ void rowInserted(int sheetIndex, int row)
+ {
+ for (int i = 0 ; i < ranges.length ; i++)
+ {
+ if (sheetIndex != ranges[i].getExternalSheet())
+ {
+ continue; // shame on me - this is no better than a goto
+ }
+
+ if (row <= ranges[i].getFirstRow())
+ {
+ ranges[i].incrementFirstRow();
+ modified = true;
+ }
+
+ if (row <= ranges[i].getLastRow())
+ {
+ ranges[i].incrementLastRow();
+ modified = true;
+ }
+ }
+ }
+
+ /**
+ * Called when a row is removed on the worksheet
+ *
+ * @param sheetIndex the sheet index on which the column was inserted
+ * @param row the column number which was inserted
+ * @reeturn TRUE if the name is to be removed entirely, FALSE otherwise
+ */
+ boolean rowRemoved(int sheetIndex, int row)
+ {
+ for (int i = 0 ; i < ranges.length ; i++)
+ {
+ if (sheetIndex != ranges[i].getExternalSheet())
+ {
+ continue; // shame on me - this is no better than a goto
+ }
+
+ if (row == ranges[i].getFirstRow() && row == ranges[i].getLastRow())
+ {
+ // remove the range
+ ranges[i] = EMPTY_RANGE;
+ }
+
+ if (row < ranges[i].getFirstRow() && row > 0)
+ {
+ ranges[i].decrementFirstRow();
+ modified = true;
+ }
+
+ if (row <= ranges[i].getLastRow())
+ {
+ ranges[i].decrementLastRow();
+ modified = true;
+ }
+ }
+
+ // If all ranges are empty, then remove the name
+ int emptyRanges = 0;
+ for (int i = 0 ; i < ranges.length; i++)
+ {
+ if (ranges[i] == EMPTY_RANGE)
+ {
+ emptyRanges++;
+ }
+ }
+
+ if (emptyRanges == ranges.length)
+ {
+ return true;
+ }
+
+ // otherwise just remove the empty ones
+ NameRange[] newRanges = new NameRange[ranges.length - emptyRanges];
+ for (int i = 0 ; i < ranges.length ; i++)
+ {
+ if (ranges[i] != EMPTY_RANGE)
+ {
+ newRanges[i] = ranges[i];
+ }
+ }
+
+ ranges = newRanges;
+
+ return false;
+ }
+
+ /**
+ * Called when a row is removed on the worksheet
+ *
+ * @param sheetIndex the sheet index on which the column was inserted
+ * @param row the column number which was inserted
+ * @reeturn TRUE if the name is to be removed entirely, FALSE otherwise
+ */
+ boolean columnRemoved(int sheetIndex, int col)
+ {
+ for (int i = 0 ; i < ranges.length ; i++)
+ {
+ if (sheetIndex != ranges[i].getExternalSheet())
+ {
+ continue; // shame on me - this is no better than a goto
+ }
+
+ if (col == ranges[i].getFirstColumn() && col ==
+ ranges[i].getLastColumn())
+ {
+ // remove the range
+ ranges[i] = EMPTY_RANGE;
+ }
+
+ if (col < ranges[i].getFirstColumn() && col > 0)
+ {
+ ranges[i].decrementFirstColumn();
+ modified = true;
+ }
+
+ if (col <= ranges[i].getLastColumn())
+ {
+ ranges[i].decrementLastColumn();
+ modified = true;
+ }
+ }
+
+ // If all ranges are empty, then remove the name
+ int emptyRanges = 0;
+ for (int i = 0 ; i < ranges.length; i++)
+ {
+ if (ranges[i] == EMPTY_RANGE)
+ {
+ emptyRanges++;
+ }
+ }
+
+ if (emptyRanges == ranges.length)
+ {
+ return true;
+ }
+
+ // otherwise just remove the empty ones
+ NameRange[] newRanges = new NameRange[ranges.length - emptyRanges];
+ for (int i = 0 ; i < ranges.length ; i++)
+ {
+ if (ranges[i] != EMPTY_RANGE)
+ {
+ newRanges[i] = ranges[i];
+ }
+ }
+
+ ranges = newRanges;
+
+ return false;
+ }
+
+
+ /**
+ * Called when a row is inserted on the
+ *
+ * @param sheetIndex the sheet index on which the column was inserted
+ * @param col the column number which was inserted
+ */
+ void columnInserted(int sheetIndex, int col)
+ {
+ for (int i = 0 ; i < ranges.length ; i++)
+ {
+ if (sheetIndex != ranges[i].getExternalSheet())
+ {
+ continue; // shame on me - this is no better than a goto
+ }
+
+ if (col <= ranges[i].getFirstColumn())
+ {
+ ranges[i].incrementFirstColumn();
+ modified = true;
+ }
+
+ if (col <= ranges[i].getLastColumn())
+ {
+ ranges[i].incrementLastColumn();
+ modified = true;
+ }
+ }
+ }
+
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/NineteenFourRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/NineteenFourRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/NineteenFourRecord.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,68 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * A record which indicates whether or the 1904 date system is
+ * in use
+ */
+class NineteenFourRecord extends WritableRecordData
+{
+ /**
+ * Flag which indicates whether the 1904 date system is being used
+ */
+ private boolean nineteenFourDate;
+
+ /**
+ * The binary data for output to file
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param oldDate flag indicating whether the 1904 date system is in use
+ */
+ public NineteenFourRecord(boolean oldDate)
+ {
+ super(Type.NINETEENFOUR);
+
+ nineteenFourDate = oldDate;
+ data = new byte[2];
+
+ if (nineteenFourDate)
+ {
+ IntegerHelper.getTwoBytes(1, data, 0);
+ }
+ }
+
+ /**
+ * The binary data for output to file
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/NumberFormatRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/NumberFormatRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/NumberFormatRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,137 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Logger;
+
+import jxl.biff.FormatRecord;
+
+/**
+ * A class which contains a number format
+ */
+public class NumberFormatRecord extends FormatRecord
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(NumberFormatRecord.class);
+
+ // Dummy class to specify non validation
+ protected static class NonValidatingFormat{public NonValidatingFormat(){}};
+
+
+ /**
+ * Constructor. Replaces some of the characters in the java number
+ * format string with the appropriate excel format characters
+ *
+ * @param fmt the number format
+ */
+ protected NumberFormatRecord(String fmt)
+ {
+ super();
+
+ // Do the replacements in the format string
+ String fs = fmt;
+
+ fs = replace(fs, "E0", "E+0");
+
+ fs = trimInvalidChars(fs);
+
+ setFormatString(fs);
+ }
+
+ /**
+ * Constructor. Replaces some of the characters in the java number
+ * format string with the appropriate excel format characters
+ *
+ * @param fmt the number format
+ */
+ protected NumberFormatRecord(String fmt, NonValidatingFormat dummy)
+ {
+ super();
+
+ // Do the replacements in the format string
+ String fs = fmt;
+
+ fs = replace(fs, "E0", "E+0");
+
+ setFormatString(fs);
+ }
+
+ /**
+ * Remove all but the first characters preceding the # or the 0.
+ * Remove all characters after the # or the 0, unless it is a )
+ *
+ * @param fs the candidate number format
+ * @return the string with spurious characters removed
+ */
+ private String trimInvalidChars(String fs)
+ {
+ int firstHash = fs.indexOf('#');
+ int firstZero = fs.indexOf('0');
+ int firstValidChar = 0;
+
+ if (firstHash == -1 && firstZero == -1)
+ {
+ // The string is complete nonsense. Return a default string
+ return "#.###";
+ }
+
+ if (firstHash != 0 && firstZero != 0 &&
+ firstHash != 1 && firstZero != 1)
+ {
+ // The string is dodgy. Find the first valid char
+ firstHash = firstHash == -1?firstHash = Integer.MAX_VALUE:firstHash;
+ firstZero = firstZero == -1?firstZero = Integer.MAX_VALUE:firstZero;
+ firstValidChar = Math.min(firstHash, firstZero);
+
+ StringBuffer tmp = new StringBuffer();
+ tmp.append(fs.charAt(0));
+ tmp.append(fs.substring(firstValidChar));
+ fs = tmp.toString();
+ }
+
+ // Now strip of everything at the end that isn't a # or 0
+ int lastHash = fs.lastIndexOf('#');
+ int lastZero = fs.lastIndexOf('0');
+
+ if (lastHash == fs.length() ||
+ lastZero == fs.length())
+ {
+ return fs;
+ }
+
+ // Find the last valid character
+ int lastValidChar = Math.max(lastHash, lastZero);
+
+ // Check for the existence of a ) or %
+ while ((fs.length() > lastValidChar + 1) &&
+ (fs.charAt(lastValidChar+1) == ')' ||
+ (fs.charAt(lastValidChar+1) == '%')))
+ {
+ lastValidChar++;
+ }
+
+ return fs.substring(0, lastValidChar+1);
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/NumberRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/NumberRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/NumberRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,183 @@
+/*********************************************************************
+*
+* Copyright (C) 2001 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+import jxl.CellType;
+import jxl.NumberCell;
+import jxl.biff.DoubleHelper;
+import jxl.biff.Type;
+import jxl.biff.XFRecord;
+import jxl.format.CellFormat;
+
+/**
+ * The record which contains numerical values. All values are stored
+ * as 64bit IEEE floating point values
+ */
+public abstract class NumberRecord extends CellValue
+{
+ /**
+ * The number
+ */
+ private double value;
+
+ /**
+ * The java equivalent of the excel format
+ */
+ private NumberFormat format;
+
+ /**
+ * The formatter to convert the value into a string
+ */
+ private static DecimalFormat defaultFormat = new DecimalFormat("#.###");
+
+ /**
+ * Constructor invoked by the user API
+ *
+ * @param c the column
+ * @param r the row
+ * @param val the value
+ */
+ protected NumberRecord(int c, int r, double val)
+ {
+ super(Type.NUMBER, c, r);
+ value = val;
+ }
+
+ /**
+ * Overloaded constructor invoked from the API, which takes a cell
+ * format
+ *
+ * @param c the column
+ * @param r the row
+ * @param val the value
+ * @param st the cell format
+ */
+ protected NumberRecord(int c, int r, double val, CellFormat st)
+ {
+ super(Type.NUMBER, c, r, st);
+ value = val;
+ }
+
+ /**
+ * Constructor used when copying a workbook
+ *
+ * @param nc the number to copy
+ */
+ protected NumberRecord(NumberCell nc)
+ {
+ super(Type.NUMBER, nc);
+ value = nc.getValue();
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param c the column
+ * @param r the row
+ * @param nr the record to copy
+ */
+ protected NumberRecord(int c, int r, NumberRecord nr)
+ {
+ super(Type.NUMBER, c, r, nr);
+ value = nr.value;
+ }
+
+ /**
+ * Returns the content type of this cell
+ *
+ * @return the content type for this cell
+ */
+ public CellType getType()
+ {
+ return CellType.NUMBER;
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] celldata = super.getData();
+ byte[] data = new byte[celldata.length + 8];
+ System.arraycopy(celldata, 0, data, 0, celldata.length);
+ DoubleHelper.getIEEEBytes(value, data, celldata.length);
+
+ return data;
+ }
+
+ /**
+ * Quick and dirty function to return the contents of this cell as a string.
+ * For more complex manipulation of the contents, it is necessary to cast
+ * this interface to correct subinterface
+ *
+ * @return the contents of this cell as a string
+ */
+ public String getContents()
+ {
+ if (format == null)
+ {
+ format = ( (XFRecord) getCellFormat()).getNumberFormat();
+ if (format == null)
+ {
+ format = defaultFormat;
+ }
+ }
+ return format.format(value);
+ }
+
+ /**
+ * Gets the double contents for this cell.
+ *
+ * @return the cell contents
+ */
+ public double getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Sets the value of the contents for this cell
+ *
+ * @param val the new value
+ */
+ public void setValue(double val)
+ {
+ value = val;
+ }
+
+ /**
+ * Gets the NumberFormat used to format this cell. This is the java
+ * equivalent of the Excel format
+ *
+ * @return the NumberFormat used to format the cell
+ */
+ public NumberFormat getNumberFormat()
+ {
+ return null;
+ }
+}
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ObjProjRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ObjProjRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ObjProjRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,62 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record containing the obj proj record
+ */
+class ObjProjRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ */
+ public ObjProjRecord()
+ {
+ super(Type.OBJPROJ);
+
+ data = new byte[4];
+ }
+
+ /**
+ * Retrieves the data to be written to the binary file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ObjectProtectRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ObjectProtectRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ObjectProtectRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,68 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * The protection state for a sheet or workbook
+ */
+class ObjectProtectRecord extends WritableRecordData
+{
+ /**
+ * The protection state
+ */
+ private boolean protection;
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param prot the protection state
+ */
+ public ObjectProtectRecord(boolean prot)
+ {
+ super(Type.OBJPROTECT);
+
+ protection = prot;
+
+ data = new byte[2];
+
+ if (protection)
+ {
+ IntegerHelper.getTwoBytes(1, data, 0);
+ }
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/PLSRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/PLSRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/PLSRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,71 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record which specifies a print header for a work sheet
+ */
+class PLSRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Consructor invoked when copying a spreadsheet
+ *
+ * @param hr the read header record
+ */
+ public PLSRecord(jxl.read.biff.PLSRecord hr)
+ {
+ super(Type.PLS);
+
+ data = hr.getData();
+ }
+
+ /**
+ * Consructor invoked when copying a sheets
+ *
+ * @param hr the read header record
+ */
+ public PLSRecord(PLSRecord hr)
+ {
+ super(Type.PLS);
+
+ data = new byte[hr.data.length];
+ System.arraycopy(hr.data, 0, data, 0, data.length);
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/PaletteRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/PaletteRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/PaletteRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,56 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores the colour palette
+ */
+class PaletteRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param p the palette record
+ */
+ public PaletteRecord(jxl.read.biff.PaletteRecord p)
+ {
+ super(Type.PALETTE);
+
+ data = p.getData();
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/PaneRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/PaneRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/PaneRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,109 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Contains the window attributes for a worksheet
+ */
+class PaneRecord extends WritableRecordData
+{
+ /**
+ * The number of rows visible in the top left pane
+ */
+ private int rowsVisible;
+ /**
+ * The number of columns visible in the top left pane
+ */
+ private int columnsVisible;
+
+ /**
+ * The pane codes
+ */
+ private final static int topLeftPane = 0x3;
+ private final static int bottomLeftPane = 0x2;
+ private final static int topRightPane = 0x1;
+ private final static int bottomRightPane = 0x0;
+
+ /**
+ * Code
+
+ /**
+ * Constructor
+ */
+ public PaneRecord(int cols, int rows)
+ {
+ super(Type.PANE);
+
+ rowsVisible = rows;
+ columnsVisible = cols;
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[10];
+
+ // The x position
+ IntegerHelper.getTwoBytes(columnsVisible, data, 0);
+
+ // The y position
+ IntegerHelper.getTwoBytes(rowsVisible, data, 2);
+
+ // The top row visible in the bottom pane
+ if (rowsVisible > 0)
+ {
+ IntegerHelper.getTwoBytes(rowsVisible, data, 4);
+ }
+
+ // The left most column visible in the right pane
+ if (columnsVisible > 0)
+ {
+ IntegerHelper.getTwoBytes(columnsVisible, data, 6);
+ }
+
+ // The active pane
+ int activePane = topLeftPane;
+
+ if (rowsVisible > 0 && columnsVisible == 0)
+ {
+ activePane = bottomLeftPane;
+ }
+ else if (rowsVisible == 0 && columnsVisible > 0)
+ {
+ activePane = topRightPane;
+ }
+ else if (rowsVisible > 0 && columnsVisible > 0)
+ {
+ activePane = bottomRightPane;
+ }
+ // always present
+ IntegerHelper.getTwoBytes(activePane, data, 8);
+
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/PasswordRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/PasswordRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/PasswordRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,122 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * A password record. Thanks to Michael Matthews for sending me the
+ * code to actually store the password for the sheet
+ */
+class PasswordRecord extends WritableRecordData
+{
+ /**
+ * The password
+ */
+ private String password;
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param pw the password
+ */
+ public PasswordRecord(String pw)
+ {
+ super(Type.PASSWORD);
+
+ password = pw;
+
+ if (pw == null)
+ {
+ data = new byte[2];
+ IntegerHelper.getTwoBytes(0, data, 0);
+ }
+ else
+ {
+ byte [] passwordBytes = pw.getBytes();
+ int passwordHash = 0;
+ for (int a = 0; a < passwordBytes.length; a++)
+ {
+ int shifted = rotLeft15Bit(passwordBytes[a], a + 1);
+ passwordHash ^= shifted;
+ }
+ passwordHash ^= passwordBytes.length;
+ passwordHash ^= 0xCE4B;
+
+ data = new byte[2];
+ IntegerHelper.getTwoBytes(passwordHash, data, 0);
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param ph the password hash code
+ */
+ public PasswordRecord(int ph)
+ {
+ super(Type.PASSWORD);
+
+ data = new byte[2];
+ IntegerHelper.getTwoBytes(ph, data, 0);
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+
+ /**
+ * Rotate the value by 15 bits. Thanks to Michael for this
+ *
+ * @param val
+ * @param rotate
+ * @return int
+ */
+ private int rotLeft15Bit(int val, int rotate)
+ {
+ val = val &0x7FFF;
+
+ for(; rotate > 0; rotate--)
+ {
+ if((val & 0x4000) != 0)
+ {
+ val = ((val << 1) & 0x7FFF) + 1;
+ }
+ else
+ {
+ val = (val << 1) & 0x7FFF;
+ }
+ }
+
+ return val;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/PrecisionRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/PrecisionRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/PrecisionRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,67 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores the Precision As Displayed option from the dialog box
+ */
+class PrecisionRecord extends WritableRecordData
+{
+ /**
+ * The precision as displayed flag
+ */
+ private boolean asDisplayed;
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param disp the precision as displayed flag
+ */
+ public PrecisionRecord(boolean disp)
+ {
+ super(Type.PRECISION);
+
+ asDisplayed = disp;
+ data = new byte[2];
+
+ if (!asDisplayed)
+ {
+ IntegerHelper.getTwoBytes(1, data, 0);
+ }
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/PrintGridLinesRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/PrintGridLinesRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/PrintGridLinesRecord.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,68 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * The grid lines option from the Page Setup dialog box
+ */
+class PrintGridLinesRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+ /**
+ * The print grid lines option
+ */
+ private boolean printGridLines;
+
+ /**
+ * Constructor
+ *
+ * @param pgl the grid lines option
+ */
+ public PrintGridLinesRecord(boolean pgl)
+ {
+ super(Type.PRINTGRIDLINES);
+ printGridLines = pgl;
+
+ data = new byte[2];
+
+ if (printGridLines)
+ {
+ data[0] = 1;
+ }
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/PrintHeadersRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/PrintHeadersRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/PrintHeadersRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,68 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * The headings options from the Page Setup dialog box
+ */
+class PrintHeadersRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+ /**
+ * Flag to print headers
+ */
+ private boolean printHeaders;
+
+ /**
+ * Constructor
+ *
+ * @param ph print headers flag
+ */
+ public PrintHeadersRecord(boolean ph)
+ {
+ super(Type.PRINTHEADERS);
+ printHeaders = ph;
+
+ data = new byte[2];
+
+ if (printHeaders)
+ {
+ data[0] = 1;
+ }
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/Prot4RevPassRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/Prot4RevPassRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/Prot4RevPassRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,55 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores the shared workbook protection flag
+ */
+class Prot4RevPassRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ */
+ public Prot4RevPassRecord()
+ {
+ super(Type.PROT4REVPASS);
+
+ // Hard code in an unprotected workbook
+ data = new byte[2];
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/Prot4RevRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/Prot4RevRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/Prot4RevRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,69 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * The shared workbook protection flag
+ */
+class Prot4RevRecord extends WritableRecordData
+{
+ /**
+ * The protection flag
+ */
+ private boolean protection;
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param prot protection flag
+ */
+ public Prot4RevRecord(boolean prot)
+ {
+ super(Type.PROT4REV);
+
+ protection = prot;
+
+ // Hard code in an unprotected workbook
+ data = new byte[2];
+
+ if (protection)
+ {
+ IntegerHelper.getTwoBytes(1, data, 0);
+ }
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ProtectRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ProtectRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ProtectRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,68 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * The protection state for a sheet or workbook
+ */
+class ProtectRecord extends WritableRecordData
+{
+ /**
+ * The protection state
+ */
+ private boolean protection;
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param prot the protection state
+ */
+ public ProtectRecord(boolean prot)
+ {
+ super(Type.PROTECT);
+
+ protection = prot;
+
+ data = new byte[2];
+
+ if (protection)
+ {
+ IntegerHelper.getTwoBytes(1, data, 0);
+ }
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ReadBooleanFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ReadBooleanFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ReadBooleanFormulaRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,50 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.BooleanFormulaCell;
+import jxl.biff.FormulaData;
+
+/**
+ * Class for read number formula records
+ */
+class ReadBooleanFormulaRecord extends ReadFormulaRecord
+ implements BooleanFormulaCell
+{
+ /**
+ * Constructor
+ *
+ * @param f
+ */
+ public ReadBooleanFormulaRecord(FormulaData f)
+ {
+ super(f);
+ }
+
+ /**
+ * Gets the boolean contents for this cell.
+ *
+ * @return the cell contents
+ */
+ public boolean getValue()
+ {
+ return ( (BooleanFormulaCell) getReadFormula()).getValue();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ReadDateFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ReadDateFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ReadDateFormulaRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,76 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.text.DateFormat;
+import java.util.Date;
+
+import jxl.DateFormulaCell;
+import jxl.biff.FormulaData;
+
+/**
+ * Class for read number formula records
+ */
+class ReadDateFormulaRecord extends ReadFormulaRecord
+ implements DateFormulaCell
+{
+ /**
+ * Constructor
+ *
+ * @param f
+ */
+ public ReadDateFormulaRecord(FormulaData f)
+ {
+ super(f);
+ }
+
+ /**
+ * Gets the Date contents for this cell.
+ *
+ * @return the cell contents
+ */
+ public Date getDate()
+ {
+ return ( (DateFormulaCell) getReadFormula()).getDate();
+ }
+
+ /**
+ * Indicates whether the date value contained in this cell refers to a date,
+ * or merely a time
+ *
+ * @return TRUE if the value refers to a time
+ */
+ public boolean isTime()
+ {
+ return ( (DateFormulaCell) getReadFormula()).isTime();
+ }
+
+
+ /**
+ * Gets the DateFormat used to format this cell. This is the java
+ * equivalent of the Excel format
+ *
+ * @return the DateFormat used to format the cell
+ */
+ public DateFormat getDateFormat()
+ {
+ return ( (DateFormulaCell) getReadFormula()).getDateFormat();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ReadErrorFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ReadErrorFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ReadErrorFormulaRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,133 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Logger;
+
+import jxl.ErrorFormulaCell;
+import jxl.biff.FormulaData;
+import jxl.biff.IntegerHelper;
+import jxl.biff.formula.FormulaErrorCode;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+
+
+/**
+ * Class for read number formula records
+ */
+class ReadErrorFormulaRecord extends ReadFormulaRecord
+ implements ErrorFormulaCell
+{
+ // The logger
+ private static Logger logger = Logger.getLogger(ReadErrorFormulaRecord.class);
+
+ /**
+ * Constructor
+ *
+ * @param f
+ */
+ public ReadErrorFormulaRecord(FormulaData f)
+ {
+ super(f);
+ }
+
+ /**
+ * Gets the error code for this cell.
+ *
+ * @return the cell contents
+ */
+ public int getErrorCode()
+ {
+ return ( (ErrorFormulaCell) getReadFormula()).getErrorCode();
+ }
+
+ /**
+ * Error formula specific exception handling. Can't really create
+ * a formula (as it will look for a cell of that name, so just
+ * create a STRING record containing the contents
+ *
+ * @return the bodged data
+ */
+ protected byte[] handleFormulaException()
+ {
+ byte[] expressiondata = null;
+ byte[] celldata = super.getCellData();
+
+ int errorCode = getErrorCode();
+ String formulaString = null;
+
+ if (errorCode == FormulaErrorCode.DIV0.getCode())
+ {
+ formulaString = "1/0";
+ }
+ else if (errorCode == FormulaErrorCode.VALUE.getCode())
+ {
+ formulaString = "\"\"/0";
+ }
+ else if (errorCode == FormulaErrorCode.REF.getCode())
+ {
+ formulaString = "\"#REF!\"";
+ }
+ else
+ {
+ formulaString = "\"ERROR\"";
+ }
+
+ // Generate an appropriate dummy formula
+ WritableWorkbookImpl w = getSheet().getWorkbook();
+ FormulaParser parser = new FormulaParser(formulaString, w, w,
+ w.getSettings());
+
+ // Get the bytes for the dummy formula
+ try
+ {
+ parser.parse();
+ }
+ catch(FormulaException e2)
+ {
+ logger.warn(e2.getMessage());
+ }
+ byte[] formulaBytes = parser.getBytes();
+ expressiondata = new byte[formulaBytes.length + 16];
+ IntegerHelper.getTwoBytes(formulaBytes.length, expressiondata, 14);
+ System.arraycopy(formulaBytes, 0, expressiondata, 16,
+ formulaBytes.length);
+
+ // Set the recalculate on load bit
+ expressiondata[8] |= 0x02;
+
+ byte[] data = new byte[celldata.length +
+ expressiondata.length];
+ System.arraycopy(celldata, 0, data, 0, celldata.length);
+ System.arraycopy(expressiondata, 0, data,
+ celldata.length, expressiondata.length);
+
+ // Set the type bits to indicate an error
+ data[6] = 2;
+ data[12] = -1;
+ data[13] = -1;
+
+ // Set the error code
+ data[8] = (byte) errorCode;
+
+ return data;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ReadFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ReadFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ReadFormulaRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,448 @@
+/*************************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.CellReferenceHelper;
+import jxl.CellType;
+import jxl.FormulaCell;
+import jxl.Sheet;
+import jxl.WorkbookSettings;
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.formula.ExternalSheet;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+import jxl.write.WritableCell;
+
+/**
+ * A formula record. This is invoked when copying a formula from a
+ * read only spreadsheet
+ * This method implements the FormulaData interface to allow the copying
+ * of writable sheets
+ */
+class ReadFormulaRecord extends CellValue implements FormulaData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(ReadFormulaRecord.class);
+
+ /**
+ * The underlying formula from the read sheet
+ */
+ private FormulaData formula;
+
+ /**
+ * The formula parser
+ */
+ private FormulaParser parser;
+
+ /**
+ * Constructor
+ *
+ * @param f the formula to copy
+ */
+ protected ReadFormulaRecord(FormulaData f)
+ {
+ super(Type.FORMULA, f);
+ formula = f;
+ }
+
+ protected final byte[] getCellData()
+ {
+ return super.getData();
+ }
+
+ /**
+ * An exception has occurred, so produce some appropriate dummy
+ * cell contents. This may be overridden by subclasses
+ * if they require specific handling
+ *
+ * @return the bodged data
+ */
+ protected byte[] handleFormulaException()
+ {
+ byte[] expressiondata = null;
+ byte[] celldata = super.getData();
+
+ // Generate an appropriate dummy formula
+ WritableWorkbookImpl w = getSheet().getWorkbook();
+ parser = new FormulaParser(getContents(), w, w,
+ w.getSettings());
+
+ // Get the bytes for the dummy formula
+ try
+ {
+ parser.parse();
+ }
+ catch(FormulaException e2)
+ {
+ logger.warn(e2.getMessage());
+ parser = new FormulaParser("\"ERROR\"", w, w, w.getSettings());
+ try {parser.parse();}
+ catch(FormulaException e3) {Assert.verify(false);}
+ }
+ byte[] formulaBytes = parser.getBytes();
+ expressiondata = new byte[formulaBytes.length + 16];
+ IntegerHelper.getTwoBytes(formulaBytes.length, expressiondata, 14);
+ System.arraycopy(formulaBytes, 0, expressiondata, 16,
+ formulaBytes.length);
+
+ // Set the recalculate on load bit
+ expressiondata[8] |= 0x02;
+
+ byte[] data = new byte[celldata.length +
+ expressiondata.length];
+ System.arraycopy(celldata, 0, data, 0, celldata.length);
+ System.arraycopy(expressiondata, 0, data,
+ celldata.length, expressiondata.length);
+ return data;
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ // Take the superclass cell data to take into account cell
+ // rationalization
+ byte[] celldata = super.getData();
+ byte[] expressiondata = null;
+
+ try
+ {
+ if (parser == null)
+ {
+ expressiondata = formula.getFormulaData();
+ }
+ else
+ {
+ byte[] formulaBytes = parser.getBytes();
+ expressiondata = new byte[formulaBytes.length + 16];
+ IntegerHelper.getTwoBytes(formulaBytes.length, expressiondata, 14);
+ System.arraycopy(formulaBytes, 0, expressiondata, 16,
+ formulaBytes.length);
+ }
+
+ // Set the recalculate on load bit
+ expressiondata[8] |= 0x02;
+
+ byte[] data = new byte[celldata.length +
+ expressiondata.length];
+ System.arraycopy(celldata, 0, data, 0, celldata.length);
+ System.arraycopy(expressiondata, 0, data,
+ celldata.length, expressiondata.length);
+ return data;
+ }
+ catch (FormulaException e)
+ {
+ // Something has gone wrong trying to read the formula data eg. it
+ // might be unsupported biff7 data
+ logger.warn
+ (CellReferenceHelper.getCellReference(getColumn(), getRow()) +
+ " " + e.getMessage());
+ return handleFormulaException();
+ }
+ }
+
+ /**
+ * Returns the content type of this cell
+ *
+ * @return the content type for this cell
+ */
+ public CellType getType()
+ {
+ return formula.getType();
+ }
+
+ /**
+ * Quick and dirty function to return the contents of this cell as a string.
+ *
+ * @return the contents of this cell as a string
+ */
+ public String getContents()
+ {
+ return formula.getContents();
+ }
+
+ /**
+ * Gets the raw bytes for the formula. This will include the
+ * parsed tokens array. Used when copying spreadsheets
+ *
+ * @return the raw record data
+ */
+ public byte[] getFormulaData() throws FormulaException
+ {
+ byte[] d = formula.getFormulaData();
+ byte[] data = new byte[d.length];
+
+ System.arraycopy(d, 0, data, 0, d.length);
+
+ // Set the recalculate on load bit
+ data[8] |= 0x02;
+
+ return data;
+ }
+
+ /**
+ * Gets the formula bytes
+ *
+ * @return the formula bytes
+ */
+ public byte[] getFormulaBytes() throws FormulaException
+ {
+ // If the formula has been parsed, then get the parsed bytes
+ if (parser != null)
+ {
+ return parser.getBytes();
+ }
+
+ // otherwise get the bytes from the original formula
+ byte[] readFormulaData = getFormulaData();
+ byte[] formulaBytes = new byte[readFormulaData.length - 16];
+ System.arraycopy(readFormulaData, 16, formulaBytes, 0,
+ formulaBytes.length);
+ return formulaBytes;
+ }
+
+ /**
+ * Implementation of the deep copy function
+ *
+ * @param col the column which the new cell will occupy
+ * @param row the row which the new cell will occupy
+ * @return a copy of this cell, which can then be added to the sheet
+ */
+ public WritableCell copyTo(int col, int row)
+ {
+ return new FormulaRecord(col, row, this);
+ }
+
+ /**
+ * Overrides the method in the base class to add this to the Workbook's
+ * list of maintained formulas
+ *
+ * @param fr the formatting records
+ * @param ss the shared strings used within the workbook
+ * @param s the sheet this is being added to
+ */
+ void setCellDetails(FormattingRecords fr, SharedStrings ss,
+ WritableSheetImpl s)
+ {
+ super.setCellDetails(fr, ss, s);
+ s.getWorkbook().addRCIRCell(this);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Notifies all
+ * RCIR cells of this change. The default implementation here does nothing
+ *
+ * @param s the sheet on which the column was inserted
+ * @param sheetIndex the sheet index on which the column was inserted
+ * @param col the column number which was inserted
+ */
+ void columnInserted(Sheet s, int sheetIndex, int col)
+ {
+ try
+ {
+ if (parser == null)
+ {
+ byte[] formulaData = formula.getFormulaData();
+ byte[] formulaBytes = new byte[formulaData.length - 16];
+ System.arraycopy(formulaData, 16,
+ formulaBytes, 0, formulaBytes.length);
+ parser = new FormulaParser(formulaBytes,
+ this,
+ getSheet().getWorkbook(),
+ getSheet().getWorkbook(),
+ getSheet().getWorkbookSettings());
+ parser.parse();
+ }
+
+ parser.columnInserted(sheetIndex, col, s == getSheet());
+ }
+ catch (FormulaException e)
+ {
+ logger.warn("cannot insert column within formula: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Called when a column is removed on the specified sheet. Notifies all
+ * RCIR cells of this change. The default implementation here does nothing
+ *
+ * @param s the sheet on which the column was inserted
+ * @param sheetIndex the sheet index on which the column was inserted
+ * @param col the column number which was inserted
+ */
+ void columnRemoved(Sheet s, int sheetIndex, int col)
+ {
+ try
+ {
+ if (parser == null)
+ {
+ byte[] formulaData = formula.getFormulaData();
+ byte[] formulaBytes = new byte[formulaData.length - 16];
+ System.arraycopy(formulaData, 16,
+ formulaBytes, 0, formulaBytes.length);
+ parser = new FormulaParser(formulaBytes,
+ this,
+ getSheet().getWorkbook(),
+ getSheet().getWorkbook(),
+ getSheet().getWorkbookSettings());
+ parser.parse();
+ }
+
+ parser.columnRemoved(sheetIndex, col, s == getSheet());
+ }
+ catch (FormulaException e)
+ {
+ logger.warn("cannot remove column within formula: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Called when a row is inserted on the specified sheet. Notifies all
+ * RCIR cells of this change. The default implementation here does nothing
+ *
+ * @param s the sheet on which the column was inserted
+ * @param sheetIndex the sheet index on which the column was inserted
+ * @param row the column number which was inserted
+ */
+ void rowInserted(Sheet s, int sheetIndex, int row)
+ {
+ try
+ {
+ if (parser == null)
+ {
+ byte[] formulaData = formula.getFormulaData();
+ byte[] formulaBytes = new byte[formulaData.length - 16];
+ System.arraycopy(formulaData, 16,
+ formulaBytes, 0, formulaBytes.length);
+ parser = new FormulaParser(formulaBytes,
+ this,
+ getSheet().getWorkbook(),
+ getSheet().getWorkbook(),
+ getSheet().getWorkbookSettings());
+ parser.parse();
+ }
+
+ parser.rowInserted(sheetIndex, row, s == getSheet());
+ }
+ catch (FormulaException e)
+ {
+ logger.warn("cannot insert row within formula: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Called when a row is inserted on the specified sheet. Notifies all
+ * RCIR cells of this change. The default implementation here does nothing
+ *
+ * @param s the sheet on which the row was removed
+ * @param sheetIndex the sheet index on which the column was removed
+ * @param row the column number which was removed
+ */
+ void rowRemoved(Sheet s, int sheetIndex, int row)
+ {
+ try
+ {
+ if (parser == null)
+ {
+ byte[] formulaData = formula.getFormulaData();
+ byte[] formulaBytes = new byte[formulaData.length - 16];
+ System.arraycopy(formulaData, 16,
+ formulaBytes, 0, formulaBytes.length);
+ parser = new FormulaParser(formulaBytes,
+ this,
+ getSheet().getWorkbook(),
+ getSheet().getWorkbook(),
+ getSheet().getWorkbookSettings());
+ parser.parse();
+ }
+
+ parser.rowRemoved(sheetIndex, row, s == getSheet());
+ }
+ catch (FormulaException e)
+ {
+ logger.warn("cannot remove row within formula: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Accessor for the read formula
+ *
+ * @return the read formula
+ */
+ protected FormulaData getReadFormula()
+ {
+ return formula;
+ }
+
+ /**
+ * Accessor for the read formula
+ *
+ * @return the read formula
+ */
+ public String getFormula() throws FormulaException
+ {
+ return ( (FormulaCell) formula).getFormula();
+ }
+
+ /**
+ * If this formula was on an imported sheet, check that
+ * cell references to another sheet are warned appropriately
+ *
+ * @return TRUE if this formula was able to be imported, FALSE otherwise
+ */
+ public boolean handleImportedCellReferences(ExternalSheet es,
+ WorkbookMethods mt,
+ WorkbookSettings ws)
+ {
+ try
+ {
+ if (parser == null)
+ {
+ byte[] formulaData = formula.getFormulaData();
+ byte[] formulaBytes = new byte[formulaData.length - 16];
+ System.arraycopy(formulaData, 16,
+ formulaBytes, 0, formulaBytes.length);
+ parser = new FormulaParser(formulaBytes,
+ this,
+ es, mt, ws);
+ parser.parse();
+ }
+
+ return parser.handleImportedCellReferences();
+ }
+ catch (FormulaException e)
+ {
+ logger.warn("cannot import formula: " + e.getMessage());
+ return false;
+ }
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ReadNumberFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ReadNumberFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ReadNumberFormulaRecord.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,120 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.text.NumberFormat;
+
+import common.Logger;
+
+import jxl.NumberFormulaCell;
+import jxl.biff.DoubleHelper;
+import jxl.biff.FormulaData;
+import jxl.biff.IntegerHelper;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+
+/**
+ * Class for read number formula records
+ */
+class ReadNumberFormulaRecord extends ReadFormulaRecord
+ implements NumberFormulaCell
+{
+ // The logger
+ private static Logger logger = Logger.getLogger(ReadNumberFormulaRecord.class);
+
+ /**
+ * Constructor
+ *
+ * @param f
+ */
+ public ReadNumberFormulaRecord(FormulaData f)
+ {
+ super(f);
+ }
+
+ /**
+ * Gets the double contents for this cell.
+ *
+ * @return the cell contents
+ */
+ public double getValue()
+ {
+ return ( (NumberFormulaCell) getReadFormula()).getValue();
+ }
+
+ /**
+ * Gets the NumberFormat used to format this cell. This is the java
+ * equivalent of the Excel format
+ *
+ * @return the NumberFormat used to format the cell
+ */
+ public NumberFormat getNumberFormat()
+ {
+ return ( (NumberFormulaCell) getReadFormula()).getNumberFormat();
+ }
+
+ /**
+ * Error formula specific exception handling. Can't really create
+ * a formula (as it will look for a cell of that name, so just
+ * create a STRING record containing the contents
+ *
+ * @return the bodged data
+ */
+ protected byte[] handleFormulaException()
+ {
+ byte[] expressiondata = null;
+ byte[] celldata = super.getCellData();
+
+ // Generate an appropriate dummy formula
+ WritableWorkbookImpl w = getSheet().getWorkbook();
+ FormulaParser parser = new FormulaParser(Double.toString(getValue()), w, w,
+ w.getSettings());
+
+ // Get the bytes for the dummy formula
+ try
+ {
+ parser.parse();
+ }
+ catch(FormulaException e2)
+ {
+ logger.warn(e2.getMessage());
+ }
+ byte[] formulaBytes = parser.getBytes();
+ expressiondata = new byte[formulaBytes.length + 16];
+ IntegerHelper.getTwoBytes(formulaBytes.length, expressiondata, 14);
+ System.arraycopy(formulaBytes, 0, expressiondata, 16,
+ formulaBytes.length);
+
+ // Set the recalculate on load bit
+ expressiondata[8] |= 0x02;
+
+ byte[] data = new byte[celldata.length +
+ expressiondata.length];
+ System.arraycopy(celldata, 0, data, 0, celldata.length);
+ System.arraycopy(expressiondata, 0, data,
+ celldata.length, expressiondata.length);
+
+ // Store the value in the formula
+ DoubleHelper.getIEEEBytes(getValue(), data, 6);
+
+ return data;
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ReadStringFormulaRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ReadStringFormulaRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ReadStringFormulaRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,111 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.StringFormulaCell;
+import jxl.biff.FormulaData;
+import jxl.biff.IntegerHelper;
+import jxl.biff.formula.FormulaException;
+import jxl.biff.formula.FormulaParser;
+
+/**
+ * Class for read number formula records
+ */
+class ReadStringFormulaRecord extends ReadFormulaRecord
+ implements StringFormulaCell
+{
+ // the logger
+ private static Logger logger = Logger.getLogger(ReadFormulaRecord.class);
+
+ /**
+ * Constructor
+ *
+ * @param f
+ */
+ public ReadStringFormulaRecord(FormulaData f)
+ {
+ super(f);
+ }
+
+ /**
+ * Gets the string contents for this cell.
+ *
+ * @return the cell contents
+ */
+ public String getString()
+ {
+ return ( (StringFormulaCell) getReadFormula()).getString();
+ }
+
+ /**
+ * String formula specific exception handling. Can't really create
+ * a formula (as it will look for a cell of that name, so just
+ * create a STRING record containing the contents
+ *
+ * @return the bodged data
+ */
+ protected byte[] handleFormulaException()
+ {
+ byte[] expressiondata = null;
+ byte[] celldata = super.getCellData();
+
+ // Generate an appropriate dummy formula
+ WritableWorkbookImpl w = getSheet().getWorkbook();
+ FormulaParser parser = new FormulaParser("\"" + getContents() +"\"", w, w,
+ w.getSettings());
+
+ // Get the bytes for the dummy formula
+ try
+ {
+ parser.parse();
+ }
+ catch(FormulaException e2)
+ {
+ logger.warn(e2.getMessage());
+ parser = new FormulaParser("\"ERROR\"", w, w, w.getSettings());
+ try {parser.parse();}
+ catch(FormulaException e3) {Assert.verify(false);}
+ }
+ byte[] formulaBytes = parser.getBytes();
+ expressiondata = new byte[formulaBytes.length + 16];
+ IntegerHelper.getTwoBytes(formulaBytes.length, expressiondata, 14);
+ System.arraycopy(formulaBytes, 0, expressiondata, 16,
+ formulaBytes.length);
+
+ // Set the recalculate on load bit
+ expressiondata[8] |= 0x02;
+
+ byte[] data = new byte[celldata.length +
+ expressiondata.length];
+ System.arraycopy(celldata, 0, data, 0, celldata.length);
+ System.arraycopy(expressiondata, 0, data,
+ celldata.length, expressiondata.length);
+
+ // Set the type bits to indicate a string formula
+ data[6] = 0;
+ data[12] = -1;
+ data[13] = -1;
+
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/RefModeRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/RefModeRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/RefModeRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,54 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores the reference style option from the options dialog box
+ */
+class RefModeRecord extends WritableRecordData
+{
+ /**
+ * Constructor
+ */
+ public RefModeRecord()
+ {
+ super(Type.REFMODE);
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[2];
+
+ // Hard code in the style A1 for now
+ data[0] = 0x1;
+
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/RefreshAllRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/RefreshAllRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/RefreshAllRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,70 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record which indicates whether or not data ranges and pivot tables
+ * should be refreshed when the workbook is loaded
+ */
+class RefreshAllRecord extends WritableRecordData
+{
+ /**
+ * The refresh all flag
+ */
+ private boolean refreshall;
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param refresh refresh all flag
+ */
+ public RefreshAllRecord(boolean refresh)
+ {
+ super(Type.REFRESHALL);
+
+ refreshall = refresh;
+
+ // Hard code in an unprotected workbook
+ data = new byte[2];
+
+ if (refreshall)
+ {
+ IntegerHelper.getTwoBytes(1, data, 0);
+ }
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/RightMarginRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/RightMarginRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/RightMarginRecord.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,33 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+
+/**
+ * The settings for the left margin
+ */
+class RightMarginRecord extends MarginRecord
+{
+ RightMarginRecord(double v)
+ {
+ super(Type.RIGHTMARGIN, v);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/RowRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/RowRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/RowRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,738 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import common.Logger;
+
+import jxl.CellType;
+import jxl.SheetSettings;
+import jxl.WorkbookSettings;
+import jxl.biff.CellReferenceHelper;
+import jxl.biff.IndexMapping;
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+import jxl.biff.XFRecord;
+import jxl.write.Number;
+import jxl.write.WritableSheet;
+
+/**
+ * Contains all the cells for a given row in a sheet
+ */
+class RowRecord extends WritableRecordData
+{
+ /**
+ * The logger
+ */
+ private static final Logger logger = Logger.getLogger(RowRecord.class);
+
+ /**
+ * The binary data
+ */
+ private byte[] data;
+ /**
+ * The cells which comprise this row
+ */
+ private CellValue[] cells;
+ /**
+ * The height of this row in 1/20ths of a point
+ */
+ private int rowHeight;
+ /**
+ * Flag to indicate whether this row is outline collapsed or not
+ */
+ private boolean collapsed;
+ /**
+ * The number of this row within the worksheet
+ */
+ private int rowNumber;
+ /**
+ * The number of columns in this row. This is the largest column value + 1
+ */
+ private int numColumns;
+ /**
+ * The xfIndex for this row
+ */
+ private int xfIndex;
+ /**
+ * The style for this row
+ */
+ private XFRecord style;
+ /**
+ * Flag indicating that this row record has an default format
+ */
+ private boolean defaultFormat;
+ /**
+ * Flag indicating whether this row matches the default font height
+ */
+ private boolean matchesDefFontHeight;
+ /**
+ * The amount to grow the cells array by
+ */
+ private static final int growSize = 10;
+
+ /**
+ * The maximum integer value that can be squeezed into 30 bits
+ */
+ private static final int maxRKValue = 0x1fffffff;
+
+ /**
+ * The minimum integer value that can be squeezed into 30 bits
+ */
+ private static final int minRKValue = -0x20000000;
+
+ /**
+ * Indicates that the row is default height
+ */
+ private static int defaultHeightIndicator = 0xff;
+
+ /**
+ * The maximum number of columns
+ */
+ private static int maxColumns = 256;
+
+ /**
+ * The outline level of the row
+ */
+ private int outlineLevel;
+
+ /**
+ * Is this the icon indicator row of a group?
+ */
+ private boolean groupStart;
+
+ /**
+ * A handle back to the sheet
+ */
+ private WritableSheet sheet;
+
+ /**
+ * Constructs an empty row which has the specified row number
+ *
+ * @param rn the row number of this row
+ */
+ public RowRecord(int rn, WritableSheet ws)
+ {
+ super(Type.ROW);
+ rowNumber = rn;
+ cells = new CellValue[0];
+ numColumns = 0;
+ rowHeight = defaultHeightIndicator;
+ collapsed = false;
+ matchesDefFontHeight = true;
+ sheet = ws;
+ }
+
+ /**
+ * Sets the height of this row
+ *
+ * @param h the row height
+ */
+ public void setRowHeight(int h)
+ {
+ if (h == 0)
+ {
+ setCollapsed(true);
+ matchesDefFontHeight = false;
+ }
+ else
+ {
+ rowHeight = h;
+ matchesDefFontHeight = false;
+ }
+ }
+
+ /**
+ * Sets the row details based upon the readable row record passed in
+ * Called when copying spreadsheets
+ *
+ * @param height the height of the row record in 1/20ths of a point
+ * @param mdfh matches the default font height
+ * @param col the collapsed status of the row
+ * @param ol the outline level
+ * @param gs the group start
+ * @param xf the xfrecord for the row (NULL if no default is set)
+ */
+ void setRowDetails(int height,
+ boolean mdfh,
+ boolean col,
+ int ol,
+ boolean gs,
+ XFRecord xfr)
+ {
+ rowHeight = height;
+ collapsed = col;
+ matchesDefFontHeight = mdfh;
+ outlineLevel = ol;
+ groupStart = gs;
+
+ if (xfr != null)
+ {
+ defaultFormat = true;
+ style = xfr;
+ xfIndex = style.getXFIndex();
+ }
+ }
+
+ /**
+ * Sets the collapsed status of this row
+ *
+ * @param c the collapsed flag
+ */
+ public void setCollapsed(boolean c)
+ {
+ collapsed = c;
+ }
+
+ /**
+ * Gets the row number of this row
+ *
+ * @return the row number
+ */
+ public int getRowNumber()
+ {
+ return rowNumber;
+ }
+
+ /**
+ * Adds a cell to this row, growing the array of cells as required
+ *
+ * @param cv the cell to add
+ */
+ public void addCell(CellValue cv)
+ {
+ int col = cv.getColumn();
+
+ if (col >= maxColumns)
+ {
+ logger.warn("Could not add cell at " +
+ CellReferenceHelper.getCellReference(cv.getRow(),
+ cv.getColumn()) +
+ " because it exceeds the maximum column limit");
+ return;
+ }
+
+ // Grow the array if needs be
+ // Thanks to Brendan for spotting the flaw in merely adding on the
+ // grow size
+ if (col >= cells.length)
+ {
+ CellValue[] oldCells = cells;
+ cells = new CellValue[Math.max(oldCells.length + growSize, col+1)];
+ System.arraycopy(oldCells, 0, cells, 0, oldCells.length);
+ oldCells = null;
+ }
+
+ if (cells[col] != null)
+ {
+ cells[col].removeCellFeatures();
+ }
+
+ cells[col] = cv;
+
+ numColumns = Math.max(col+1, numColumns);
+ }
+
+ /**
+ * Removes a cell from this row
+ *
+ * @param col the column at which to remove the cell
+ */
+ public void removeCell(int col)
+ {
+ // Grow the array if needs be
+ if (col >= numColumns)
+ {
+ return;
+ }
+
+ cells[col] = null;
+ }
+
+ /**
+ * Writes out the row information data (but not the individual cells)
+ *
+ * @exception IOException
+ * @param outputFile the output file
+ */
+ public void write(File outputFile) throws IOException
+ {
+ outputFile.write(this);
+ }
+
+ /**
+ * Writes out all the cells in this row. If more than three integer
+ * values occur consecutively, then a MulRK record is used to group the
+ * numbers
+ *
+ * @exception IOException
+ * @param outputFile the output file
+ */
+ public void writeCells(File outputFile)
+ throws IOException
+ {
+ // This is the list for integer values
+ ArrayList integerValues = new ArrayList();
+ boolean integerValue = false;
+
+ // Write out all the records
+ for (int i = 0; i < numColumns; i++)
+ {
+ integerValue = false;
+ if (cells[i] != null)
+ {
+ // See if this cell is a 30-bit integer value (without additional
+ // cell features)
+ if (cells[i].getType() == CellType.NUMBER)
+ {
+ Number nc = (Number) cells[i];
+ if (nc.getValue() == (int) nc.getValue() &&
+ nc.getValue() < maxRKValue &&
+ nc.getValue() > minRKValue &&
+ nc.getCellFeatures() == null)
+ {
+ integerValue = true;
+ }
+ }
+
+ if (integerValue)
+ {
+ // This cell is an integer, add it to the list
+ integerValues.add(cells[i]);
+ }
+ else
+ {
+ // This cell is not an integer. Write out whatever integers we
+ // have, and then write out this cell
+ writeIntegerValues(integerValues, outputFile);
+ outputFile.write(cells[i]);
+
+ // If the cell is a string formula, write out the string record
+ // immediately afterwards
+ if (cells[i].getType() == CellType.STRING_FORMULA)
+ {
+ StringRecord sr = new StringRecord(cells[i].getContents());
+ outputFile.write(sr);
+ }
+ }
+ }
+ else
+ {
+ // Cell does not exist. Write out the list of integers that
+ // we have
+ writeIntegerValues(integerValues, outputFile);
+ }
+ }
+
+ // All done. Write out any remaining integer values
+ writeIntegerValues(integerValues, outputFile);
+ }
+
+ /**
+ * Writes out the list of integer values. If there are more than three,
+ * a MulRK record is used, otherwise a sequence of Numbers is used
+ *
+ * @exception IOException
+ * @param outputFile the output file
+ * @param integerValues the array of integer values
+ */
+ private void writeIntegerValues(ArrayList integerValues, File outputFile)
+ throws IOException
+ {
+ if (integerValues.size() == 0)
+ {
+ return;
+ }
+
+ if (integerValues.size() >= 3 )
+ {
+ // Write out as a MulRK record
+ MulRKRecord mulrk = new MulRKRecord(integerValues);
+ outputFile.write(mulrk);
+ }
+ else
+ {
+ // Write out as number records
+ Iterator i = integerValues.iterator();
+ while (i.hasNext())
+ {
+ outputFile.write((CellValue) i.next());
+ }
+ }
+
+ // Clear out the list of integerValues
+ integerValues.clear();
+ }
+
+ /**
+ * Gets the row data to output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ // Write out the row record
+ byte[] data = new byte[16];
+
+ // If the default row height has been changed in the sheet settings,
+ // then we need to set the rowHeight on this row explicitly, as
+ // specifying the "match default" flag doesn't work
+ int rh = rowHeight;
+ if (sheet.getSettings().getDefaultRowHeight() !=
+ SheetSettings.DEFAULT_DEFAULT_ROW_HEIGHT)
+ {
+ // the default row height has been changed. If this row does not
+ // have a specific row height set on it, then set it to the default
+ if (rh == defaultHeightIndicator)
+ {
+ rh = sheet.getSettings().getDefaultRowHeight();
+ }
+ }
+
+ IntegerHelper.getTwoBytes(rowNumber, data, 0);
+ IntegerHelper.getTwoBytes(numColumns, data, 4);
+ IntegerHelper.getTwoBytes(rh, data, 6);
+
+ int options = 0x100 + outlineLevel;
+
+ if (groupStart)
+ {
+ options |= 0x10;
+ }
+
+ if (collapsed)
+ {
+ options |= 0x20;
+ }
+
+ if (!matchesDefFontHeight)
+ {
+ options |= 0x40;
+ }
+
+ if (defaultFormat)
+ {
+ options |= 0x80;
+ options |= (xfIndex << 16);
+ }
+
+ IntegerHelper.getFourBytes(options, data, 12);
+
+ return data;
+ }
+
+ /**
+ * Gets the maximum column value which occurs in this row
+ *
+ * @return the maximum column value
+ */
+ public int getMaxColumn()
+ {
+ return numColumns;
+ }
+
+ /**
+ * Gets the cell which occurs at the specified column value
+ *
+ * @param col the colun for which to return the cell
+ * @return the cell value at the specified position, or null if the column
+ * is invalid
+ */
+ public CellValue getCell(int col)
+ {
+ return (col >= 0 && col < numColumns) ? cells[col] : null;
+ }
+
+ /**
+ * Increments the row of this cell by one. Invoked by the sheet when
+ * inserting rows
+ */
+ void incrementRow()
+ {
+ rowNumber++;
+
+ for (int i = 0; i < cells.length; i++)
+ {
+ if (cells[i] != null)
+ {
+ cells[i].incrementRow();
+ }
+ }
+ }
+
+ /**
+ * Decrements the row of this cell by one. Invoked by the sheet when
+ * removing rows
+ */
+ void decrementRow()
+ {
+ rowNumber--;
+ for (int i = 0; i < cells.length; i++)
+ {
+ if (cells[i] != null)
+ {
+ cells[i].decrementRow();
+ }
+ }
+ }
+
+ /**
+ * Inserts a new column at the position specified
+ *
+ * @param col the column to insert
+ */
+ void insertColumn(int col)
+ {
+ // Don't bother doing anything unless there are cells after the
+ // column to be inserted
+ if (col >= numColumns)
+ {
+ return;
+ }
+
+ if (numColumns >= maxColumns)
+ {
+ logger.warn("Could not insert column because maximum column limit has "+
+ "been reached");
+ return;
+ }
+
+ // Create a new array to hold the new column. Grow it if need be
+ CellValue[] oldCells = cells;
+
+ if (numColumns >= cells.length - 1)
+ {
+ cells = new CellValue[oldCells.length + growSize];
+ }
+ else
+ {
+ cells = new CellValue[oldCells.length];
+ }
+
+ // Copy in everything up to the new column
+ System.arraycopy(oldCells, 0, cells, 0, col);
+
+ // Copy in the remaining cells
+ System.arraycopy(oldCells, col, cells, col+1, numColumns - col);
+
+ // Increment all the internal column numbers by one
+ for (int i = col+1; i <= numColumns; i++)
+ {
+ if (cells[i] != null)
+ {
+ cells[i].incrementColumn();
+ }
+ }
+
+ // Adjust the maximum column record
+ numColumns++;
+ }
+
+ /**
+ * Remove the new column at the position specified
+ *
+ * @param col the column to remove
+ */
+ void removeColumn(int col)
+ {
+ // Don't bother doing anything unless there are cells after the
+ // column to be inserted
+ if (col >= numColumns)
+ {
+ return;
+ }
+
+ // Create a new array to hold the new columns
+ CellValue[] oldCells = cells;
+
+ cells = new CellValue[oldCells.length];
+
+ // Copy in everything up to the column
+ System.arraycopy(oldCells, 0, cells, 0, col);
+
+ // Copy in the remaining cells after the column
+ System.arraycopy(oldCells, col + 1, cells, col, numColumns - (col+1));
+
+ // Decrement all the internal column numbers by one
+ for (int i = col; i < numColumns; i++)
+ {
+ if (cells[i] != null)
+ {
+ cells[i].decrementColumn();
+ }
+ }
+
+ // Adjust the maximum column record
+ numColumns--;
+ }
+
+ /**
+ * Interrogates whether this row is of default height
+ *
+ * @return TRUE if this is set to the default height, FALSE otherwise
+ */
+ public boolean isDefaultHeight()
+ {
+ return rowHeight == defaultHeightIndicator;
+ }
+
+ /**
+ * Gets the height of the row
+ *
+ * @return the row height
+ */
+ public int getRowHeight()
+ {
+ return rowHeight;
+ }
+
+ /**
+ * Queries whether the row is collapsed
+ *
+ * @return the collapsed indicator
+ */
+ public boolean isCollapsed()
+ {
+ return collapsed;
+ }
+
+ /**
+ * Rationalizes the sheets xf index mapping
+ * @param xfmapping the index mapping
+ */
+ void rationalize(IndexMapping xfmapping)
+ {
+ if (defaultFormat)
+ {
+ xfIndex = xfmapping.getNewIndex(xfIndex);
+ }
+ }
+
+ /**
+ * Accessor for the style. The returned value is only non-null if the
+ * default style is overridden
+ *
+ * @return the style
+ */
+ XFRecord getStyle()
+ {
+ return style;
+ }
+
+ /**
+ * Accessor for the default format flag
+ *
+ * @return TRUE if this row has its own default format
+ */
+ boolean hasDefaultFormat()
+ {
+ return defaultFormat;
+ }
+
+ /**
+ * Accessor for the matches default font height flag
+ *
+ * @return TRUE if this row matches the default font height
+ */
+ boolean matchesDefaultFontHeight()
+ {
+ return matchesDefFontHeight;
+ }
+
+ /**
+ * Accessor for the column's outline level
+ *
+ * @return the column's outline level
+ */
+ public int getOutlineLevel()
+ {
+ return outlineLevel;
+ }
+
+ /**
+ * Accessor for row's groupStart state
+ *
+ * @return the row's groupStart state
+ */
+ public boolean getGroupStart()
+ {
+ return groupStart;
+ }
+
+ /**
+ * Increments the row's outline level. This is how groups are made as well
+ */
+ public void incrementOutlineLevel()
+ {
+ outlineLevel++;
+ }
+
+ /**
+ * Decrements the row's outline level. This removes it from a grouping
+ * level. If
+ * all outline levels are gone the uncollapse the row.
+ */
+ public void decrementOutlineLevel()
+ {
+ if (0 < outlineLevel)
+ {
+ outlineLevel--;
+ }
+
+ if (0==outlineLevel)
+ {
+ collapsed = false;
+ }
+ }
+
+ /**
+ * Sets the row's outline level
+ *
+ * @param level the row's outline level
+ */
+ public void setOutlineLevel(int level)
+ {
+ outlineLevel = level;
+ }
+
+ /**
+ * Sets the row's group start state
+ *
+ * @param value the group start state
+ */
+ public void setGroupStart(boolean value)
+ {
+ groupStart = value;
+ }
+}
+
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/RowsExceededException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/RowsExceededException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/RowsExceededException.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,35 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+/**
+ * Exception thrown when attempting to add a row to a spreadsheet which
+ * has already reached the maximum amount
+ */
+public class RowsExceededException extends JxlWriteException
+{
+ /**
+ * Constructor
+ */
+ public RowsExceededException()
+ {
+ super(maxRowsExceeded);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/SCLRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/SCLRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/SCLRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,64 @@
+/*********************************************************************
+ *
+ * Copyright (C) 2003 Andrew Khan, Adam Caldwell
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record which specifies a margin value
+ */
+class SCLRecord extends WritableRecordData
+{
+ /**
+ * The zoom factor
+ */
+ private int zoomFactor;
+
+ /**
+ * Constructor
+ *
+ * @param zf the zoom factor as a percentage
+ */
+ public SCLRecord(int zf)
+ {
+ super(Type.SCL);
+
+ zoomFactor = zf;
+ }
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[4];
+
+ int numerator = zoomFactor;
+ int denominator = 100;
+
+ IntegerHelper.getTwoBytes(numerator,data,0);
+ IntegerHelper.getTwoBytes(denominator,data,2);
+
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/SSTContinueRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/SSTContinueRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/SSTContinueRecord.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,225 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * A continuation of a shared string table record.
+ */
+class SSTContinueRecord extends WritableRecordData
+{
+ /**
+ * The first string is a special case
+ */
+ private String firstString;
+ /**
+ * Indicates whether or not we need to include the length information
+ * for the first string
+ */
+ private boolean includeLength;
+ /**
+ * The length of the first string
+ */
+ private int firstStringLength;
+ /**
+ * The list of strings
+ */
+ private ArrayList strings;
+ /**
+ * The list of string lengths
+ */
+ private ArrayList stringLengths;
+ /**
+ * The binary data
+ */
+ private byte[] data;
+ /**
+ * The count of bytes needed so far to contain this record
+ */
+ private int byteCount;
+
+ /**
+ * The maximum amount of bytes available for the SST record
+ */
+ private static int maxBytes = 8228 - // max length
+ 4; // standard biff record stuff
+
+ /**
+ * Constructor
+ *
+ * @param numRefs the number of string references in the workbook
+ * @param s the number of strings
+ */
+ public SSTContinueRecord()
+ {
+ super(Type.CONTINUE);
+
+ byteCount = 0;
+ strings = new ArrayList(50);
+ stringLengths = new ArrayList(50);
+ }
+
+ /**
+ * Adds the first string to this SST record
+ *
+ * @param s the string to add
+ * @param b include the length information for the first string
+ * @return the number of characters not added
+ */
+ public int setFirstString(String s, boolean b)
+ {
+ includeLength = b;
+ firstStringLength = s.length();
+
+ int bytes = 0;
+
+ if (!includeLength)
+ {
+ bytes = s.length() * 2 + 1;
+ }
+ else
+ {
+ bytes = s.length() * 2 + 3;
+ }
+
+ if (bytes <= maxBytes)
+ {
+ firstString = s;
+ byteCount += bytes;
+ return 0;
+ }
+
+ // Calculate the number of characters we can add
+ // The bytes variable will always be an odd number
+ int charsAvailable = includeLength ? (maxBytes - 4) / 2 :
+ (maxBytes - 2) / 2;
+
+ // Add what part of the string we can
+ firstString = s.substring(0, charsAvailable);
+ byteCount = maxBytes - 1;
+
+ return s.length() - charsAvailable;
+ }
+
+ /**
+ * Gets the current offset into this record, excluding the header fields
+ *
+ * @return the number of bytes after the header field
+ */
+ public int getOffset()
+ {
+ return byteCount;
+ }
+
+ /**
+ * Adds a string to this record. It returns the number of string
+ * characters not added, due to space constraints. In the event
+ * of this being non-zero, a continue record will be needed
+ *
+ * @param s the string to add
+ * @return the number of characters not added
+ */
+ public int add(String s)
+ {
+ int bytes = s.length() * 2 + 3;
+
+ // Must be able to add at least the first character of the string
+ // onto the SST
+ if (byteCount >= maxBytes - 5)
+ {
+ return s.length();
+ }
+
+ stringLengths.add(new Integer(s.length()));
+
+ if (bytes + byteCount < maxBytes)
+ {
+ // add the string and return
+ strings.add(s);
+ byteCount += bytes;
+ return 0;
+ }
+
+ // Calculate the number of characters we can add
+ int bytesLeft = maxBytes - 3 - byteCount;
+ int charsAvailable = bytesLeft % 2 == 0 ? bytesLeft / 2 :
+ (bytesLeft - 1) / 2;
+
+ // Add what part of the string we can
+ strings.add(s.substring(0, charsAvailable));
+ byteCount += charsAvailable * 2 + 3;
+
+ return s.length() - charsAvailable;
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ data = new byte[byteCount];
+
+ int pos = 0;
+
+ // Write out the first string
+ if (includeLength)
+ {
+ IntegerHelper.getTwoBytes(firstStringLength, data, 0);
+ data[2] = 0x01;
+ pos = 3;
+ }
+ else
+ {
+ // Just include the unicode indicator
+ data[0] = 0x01;
+ pos = 1;
+ }
+
+ StringHelper.getUnicodeBytes(firstString, data, pos);
+ pos += firstString.length() * 2;
+
+ // Now write out the remainder of the strings
+ Iterator i = strings.iterator();
+ String s = null;
+ int length = 0;
+ int count = 0;
+ while (i.hasNext())
+ {
+ s = (String) i.next();
+ length = ( (Integer) stringLengths.get(count)).intValue();
+ IntegerHelper.getTwoBytes(length, data, pos);
+ data[pos+2] = 0x01;
+ StringHelper.getUnicodeBytes(s, data, pos+3);
+ pos += s.length() * 2 + 3;
+ count++;
+ }
+
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/SSTRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/SSTRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/SSTRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,166 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * A shared string table record.
+ */
+class SSTRecord extends WritableRecordData
+{
+ /**
+ * The number of string references in the workbook
+ */
+ private int numReferences;
+ /**
+ * The number of strings in this table
+ */
+ private int numStrings;
+ /**
+ * The list of strings
+ */
+ private ArrayList strings;
+ /**
+ * The list of string lengths
+ */
+ private ArrayList stringLengths;
+ /**
+ * The binary data
+ */
+ private byte[] data;
+ /**
+ * The count of bytes needed so far to contain this record
+ */
+ private int byteCount;
+
+ /**
+ * The maximum amount of bytes available for the SST record
+ */
+ private static int maxBytes = 8228 - // max length
+ 8 - // bytes for string count fields
+ 4; // standard biff record header
+
+ /**
+ * Constructor
+ *
+ * @param numRefs the number of string references in the workbook
+ * @param s the number of strings
+ */
+ public SSTRecord(int numRefs, int s)
+ {
+ super(Type.SST);
+
+ numReferences = numRefs;
+ numStrings = s;
+ byteCount = 0;
+ strings = new ArrayList(50);
+ stringLengths = new ArrayList(50);
+ }
+
+ /**
+ * Adds a string to this SST record. It returns the number of string
+ * characters not added, due to space constraints. In the event
+ * of this being non-zero, a continue record will be needed
+ *
+ * @param s the string to add
+ * @return the number of characters not added
+ */
+ public int add(String s)
+ {
+ int bytes = s.length() * 2 + 3;
+
+ // Must be able to add at least the first character of the string
+ // onto the SST
+ if (byteCount >= maxBytes - 5)
+ {
+ return s.length() > 0 ? s.length() : -1; // need to return some non-zero
+ // value in order to force the creation of a continue record
+ }
+
+ stringLengths.add(new Integer(s.length()));
+
+ if (bytes + byteCount < maxBytes)
+ {
+ // add the string and return
+ strings.add(s);
+ byteCount += bytes;
+ return 0;
+ }
+
+ // Calculate the number of characters we can add
+ int bytesLeft = maxBytes - 3 - byteCount;
+ int charsAvailable = bytesLeft % 2 == 0 ? bytesLeft / 2 :
+ (bytesLeft - 1) / 2;
+
+ // Add what strings we can
+ strings.add(s.substring(0, charsAvailable));
+ byteCount += charsAvailable * 2 + 3;
+
+ return s.length() - charsAvailable;
+ }
+
+ /**
+ * Gets the current offset into this record, excluding the header fields
+ *
+ * @return the number of bytes after the header field
+ */
+ public int getOffset()
+ {
+ return byteCount + 8;
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ data = new byte[byteCount+8];
+ IntegerHelper.getFourBytes(numReferences, data, 0);
+ IntegerHelper.getFourBytes(numStrings, data, 4);
+
+ int pos = 8;
+ int count = 0;
+
+ Iterator i = strings.iterator();
+ String s = null;
+ int length = 0;
+ while (i.hasNext())
+ {
+ s = (String) i.next();
+ length = ( (Integer) stringLengths.get(count)).intValue();
+ IntegerHelper.getTwoBytes(length, data, pos);
+ data[pos+2] = 0x01;
+ StringHelper.getUnicodeBytes(s, data, pos+3);
+ pos += s.length() * 2 + 3;
+ count++;
+ }
+
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/SaveRecalcRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/SaveRecalcRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/SaveRecalcRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,68 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores the recalculate before save flag as set in the options dialog box
+ */
+class SaveRecalcRecord extends WritableRecordData
+{
+ /**
+ * The binary data for output to file
+ */
+ private byte[] data;
+ /**
+ * The recalculate before save flag
+ */
+ private boolean recalc;
+
+ /**
+ * Constructor
+ *
+ * @param r recalculate flag
+ */
+ public SaveRecalcRecord(boolean r)
+ {
+ super(Type.SAVERECALC);
+ recalc = r;
+
+ data = new byte[2];
+
+ if (recalc)
+ {
+ data[0] = 1;
+ }
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/ScenarioProtectRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/ScenarioProtectRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/ScenarioProtectRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,68 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * The protection state for a sheet or workbook
+ */
+class ScenarioProtectRecord extends WritableRecordData
+{
+ /**
+ * The protection state
+ */
+ private boolean protection;
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param prot the protection state
+ */
+ public ScenarioProtectRecord(boolean prot)
+ {
+ super(Type.SCENPROTECT);
+
+ protection = prot;
+
+ data = new byte[2];
+
+ if (protection)
+ {
+ IntegerHelper.getTwoBytes(1, data, 0);
+ }
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/SelectionRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/SelectionRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/SelectionRecord.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,95 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores the current selection
+ */
+class SelectionRecord extends WritableRecordData
+{
+ /**
+ * The pane type
+ */
+ private PaneType pane;
+
+ /**
+ * The top left column in this pane
+ */
+ private int column;
+
+ /**
+ * The top left row in this pane
+ */
+ private int row;
+
+ // Enumeration for the pane type
+ private static class PaneType
+ {
+ int val;
+
+ PaneType(int v)
+ {val = v;}
+ }
+
+ // The pane types
+ public final static PaneType lowerRight = new PaneType(0);
+ public final static PaneType upperRight = new PaneType(1);
+ public final static PaneType lowerLeft = new PaneType(2);
+ public final static PaneType upperLeft = new PaneType(3);
+
+ /**
+ * Constructor
+ */
+ public SelectionRecord(PaneType pt, int col, int r)
+ {
+ super(Type.SELECTION);
+ column = col;
+ row = r;
+ pane = pt;
+ }
+
+ /**
+ * Gets the binary data
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ // hard code the data in for now
+ byte[] data = new byte[15];
+
+ data[0] = (byte) pane.val;
+ IntegerHelper.getTwoBytes(row, data, 1);
+ IntegerHelper.getTwoBytes(column, data, 3);
+
+ data[7] = (byte) 0x01;
+
+ IntegerHelper.getTwoBytes(row, data, 9);
+ IntegerHelper.getTwoBytes(row, data, 11);
+ data[13] = (byte) column;
+ data[14] = (byte) column;
+
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/SetupRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/SetupRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/SetupRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,247 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Logger;
+
+import jxl.SheetSettings;
+import jxl.biff.DoubleHelper;
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+import jxl.format.PageOrder;
+import jxl.format.PageOrientation;
+import jxl.format.PaperSize;
+
+/**
+ * Stores the options and measurements from the Page Setup dialog box
+ */
+class SetupRecord extends WritableRecordData
+{
+ /**
+ * The logger
+ */
+ Logger logger = Logger.getLogger(SetupRecord.class);
+
+ /**
+ * The binary data for output to file
+ */
+ private byte[] data;
+
+ /**
+ * The header margin
+ */
+ private double headerMargin;
+
+ /**
+ * The footer margin
+ */
+ private double footerMargin;
+
+ /**
+ * The page orientation
+ */
+ private PageOrientation orientation;
+
+ /**
+ * The page order
+ */
+ private PageOrder order;
+
+ /**
+ * The paper size
+ */
+ private int paperSize;
+
+ /**
+ * The scale factor
+ */
+ private int scaleFactor;
+
+ /**
+ * The page start
+ */
+ private int pageStart;
+
+ /**
+ * The fit width
+ */
+ private int fitWidth;
+
+ /**
+ * The fit height
+ */
+ private int fitHeight;
+
+ /**
+ * The horizontal print resolution
+ */
+ private int horizontalPrintResolution;
+
+ /**
+ * The vertical print resolution
+ */
+ private int verticalPrintResolution;
+
+ /**
+ * The number of copies
+ */
+ private int copies;
+
+ /**
+ * Indicates whether the setup data should be initiliazed in the setup
+ * box
+ */
+ private boolean initialized;
+
+ /**
+ * Constructor, taking the sheet settings. This object just
+ * takes the various fields from the bean in which it is interested
+ *
+ * @param the sheet settings
+ */
+ public SetupRecord(SheetSettings s)
+ {
+ super(Type.SETUP);
+
+ orientation = s.getOrientation();
+ order = s.getPageOrder();
+ headerMargin = s.getHeaderMargin();
+ footerMargin = s.getFooterMargin();
+ paperSize = s.getPaperSize().getValue();
+ horizontalPrintResolution = s.getHorizontalPrintResolution();
+ verticalPrintResolution = s.getVerticalPrintResolution();
+ fitWidth = s.getFitWidth();
+ fitHeight = s.getFitHeight();
+ pageStart = s.getPageStart();
+ scaleFactor = s.getScaleFactor();
+ copies = s.getCopies();
+ initialized = true;
+ }
+
+ /**
+ * Sets the orientation
+ *
+ * @param o the orientation
+ */
+ public void setOrientation(PageOrientation o)
+ {
+ orientation = o;
+ }
+
+ /**
+ * Sets the page order
+ *
+ * @param o
+ */
+ public void setOrder(PageOrder o)
+ {
+ order = o;
+ }
+
+ /**
+ * Sets the header and footer margins
+ *
+ * @param hm the header margin
+ * @param fm the footer margin
+ */
+ public void setMargins(double hm, double fm)
+ {
+ headerMargin = hm;
+ footerMargin = fm;
+ }
+
+ /**
+ * Sets the paper size
+ *
+ * @param ps the paper size
+ */
+ public void setPaperSize(PaperSize ps)
+ {
+ paperSize = ps.getValue();
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ data = new byte[34];
+
+ // Paper size
+ IntegerHelper.getTwoBytes(paperSize, data, 0);
+
+ // Scale factor
+ IntegerHelper.getTwoBytes(scaleFactor, data, 2);
+
+ // Page start
+ IntegerHelper.getTwoBytes(pageStart, data, 4);
+
+ // Fit width
+ IntegerHelper.getTwoBytes(fitWidth, data, 6);
+
+ // Fit height
+ IntegerHelper.getTwoBytes(fitHeight, data, 8);
+
+ // grbit
+ int options = 0;
+ if (order == PageOrder.RIGHT_THEN_DOWN)
+ {
+ options |= 0x01;
+ }
+
+ if (orientation == PageOrientation.PORTRAIT)
+ {
+ options |= 0x02;
+ }
+
+ if (pageStart != 0)
+ {
+ options |= 0x80;
+ }
+
+ if (!initialized)
+ {
+ options |= 0x04;
+ }
+
+ IntegerHelper.getTwoBytes(options, data, 10);
+
+ // print resolution
+ IntegerHelper.getTwoBytes(horizontalPrintResolution, data, 12);
+
+ // vertical print resolution
+ IntegerHelper.getTwoBytes(verticalPrintResolution, data, 14);
+
+ // header margin
+ DoubleHelper.getIEEEBytes(headerMargin, data, 16);
+
+ // footer margin
+ DoubleHelper.getIEEEBytes(footerMargin, data, 24);
+
+ // Number of copies
+ IntegerHelper.getTwoBytes(copies, data, 32);
+
+ return data;
+ }
+}
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/SharedStrings.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/SharedStrings.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/SharedStrings.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,187 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * The list of available shared strings. This class contains
+ * the labels used for the entire spreadsheet
+ */
+class SharedStrings
+{
+ /**
+ * All the strings in the spreadsheet, keyed on the string itself
+ */
+ private HashMap strings;
+
+ /**
+ * Contains the same strings, held in a list
+ */
+ private ArrayList stringList;
+
+ /**
+ * The total occurrence of strings in the workbook
+ */
+ private int totalOccurrences;
+
+ /**
+ * Constructor
+ */
+ public SharedStrings()
+ {
+ strings = new HashMap(100);
+ stringList = new ArrayList(100);
+ totalOccurrences = 0;
+ }
+
+ /**
+ * Gets the index for the string passed in. If the string is already
+ * present, then returns the index of that string, otherwise
+ * creates a new key-index mapping
+ *
+ * @param s the string whose index we want
+ * @return the index of the string
+ */
+ public int getIndex(String s)
+ {
+ Integer i = (Integer) strings.get(s);
+
+ if (i == null)
+ {
+ i = new Integer(strings.size());
+ strings.put(s, i);
+ stringList.add(s);
+ }
+
+ totalOccurrences++;
+
+ return i.intValue();
+ }
+
+ /**
+ * Gets the string at the specified index
+ *
+ * @param i the index of the string
+ * @return the string at the specified index
+ */
+ public String get(int i)
+ {
+ return (String) stringList.get(i);
+ }
+
+ /**
+ * Writes out the shared string table
+ *
+ * @param outputFile the binary output file
+ * @exception IOException
+ */
+ public void write(File outputFile) throws IOException
+ {
+ // Thanks to Guenther for contributing the ExtSST implementation portion
+ // of this method
+ int charsLeft = 0;
+ String curString = null;
+ SSTRecord sst = new SSTRecord(totalOccurrences, stringList.size());
+ ExtendedSSTRecord extsst = new ExtendedSSTRecord(stringList.size());
+ int bucketSize = extsst.getNumberOfStringsPerBucket();
+
+ Iterator i = stringList.iterator();
+ int stringIndex = 0;
+ while (i.hasNext() && charsLeft == 0)
+ {
+ curString = (String) i.next();
+ // offset + header bytes
+ int relativePosition = sst.getOffset() + 4;
+ charsLeft = sst.add(curString);
+ if ((stringIndex % bucketSize) == 0) {
+ extsst.addString(outputFile.getPos(), relativePosition);
+ }
+ stringIndex++;
+ }
+ outputFile.write(sst);
+
+ if (charsLeft != 0 || i.hasNext())
+ {
+ // Add the remainder of the string to the continue record
+ SSTContinueRecord cont = createContinueRecord(curString,
+ charsLeft,
+ outputFile);
+
+ // Carry on looping through the array until all the strings are done
+ while (i.hasNext())
+ {
+ curString = (String) i.next();
+ int relativePosition = cont.getOffset() + 4;
+ charsLeft = cont.add(curString);
+ if ((stringIndex % bucketSize) == 0) {
+ extsst.addString(outputFile.getPos(), relativePosition);
+ }
+ stringIndex++;
+
+ if (charsLeft != 0)
+ {
+ outputFile.write(cont);
+ cont = createContinueRecord(curString, charsLeft, outputFile);
+ }
+ }
+
+ outputFile.write(cont);
+ }
+
+ outputFile.write(extsst);
+ }
+
+ /**
+ * Creates and returns a continue record using the left over bits and
+ * pieces
+ */
+ private SSTContinueRecord createContinueRecord
+ (String curString, int charsLeft, File outputFile) throws IOException
+ {
+ // Set up the remainder of the string in the continue record
+ SSTContinueRecord cont = null;
+ while (charsLeft != 0)
+ {
+ cont = new SSTContinueRecord();
+
+ if (charsLeft == curString.length() || curString.length() == 0)
+ {
+ charsLeft = cont.setFirstString(curString, true);
+ }
+ else
+ {
+ charsLeft = cont.setFirstString
+ (curString.substring(curString.length() - charsLeft), false);
+ }
+
+ if (charsLeft != 0)
+ {
+ outputFile.write(cont);
+ cont = new SSTContinueRecord();
+ }
+ }
+
+ return cont;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/SheetCopier.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/SheetCopier.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/SheetCopier.java 17 Aug 2012 14:51:13 -0000 1.1
@@ -0,0 +1,1088 @@
+/*********************************************************************
+*
+* Copyright (C) 2006 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.TreeSet;
+import java.util.Iterator;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.BooleanCell;
+import jxl.Cell;
+import jxl.CellType;
+import jxl.CellView;
+import jxl.DateCell;
+import jxl.HeaderFooter;
+import jxl.Hyperlink;
+import jxl.Image;
+import jxl.LabelCell;
+import jxl.NumberCell;
+import jxl.Range;
+import jxl.Sheet;
+import jxl.SheetSettings;
+import jxl.WorkbookSettings;
+import jxl.biff.AutoFilter;
+import jxl.biff.CellReferenceHelper;
+import jxl.biff.ConditionalFormat;
+import jxl.biff.DataValidation;
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.IndexMapping;
+import jxl.biff.NumFormatRecordsException;
+import jxl.biff.SheetRangeImpl;
+import jxl.biff.XFRecord;
+import jxl.biff.drawing.Chart;
+import jxl.biff.drawing.ComboBox;
+import jxl.biff.drawing.Drawing;
+import jxl.biff.drawing.DrawingGroupObject;
+import jxl.format.CellFormat;
+import jxl.biff.formula.FormulaException;
+import jxl.read.biff.SheetImpl;
+import jxl.read.biff.NameRecord;
+import jxl.read.biff.WorkbookParser;
+import jxl.write.Blank;
+import jxl.write.Boolean;
+import jxl.write.DateTime;
+import jxl.write.Formula;
+import jxl.write.Label;
+import jxl.write.Number;
+import jxl.write.WritableCell;
+import jxl.write.WritableCellFormat;
+import jxl.write.WritableFont;
+import jxl.write.WritableHyperlink;
+import jxl.write.WritableImage;
+import jxl.write.WritableSheet;
+import jxl.write.WritableWorkbook;
+import jxl.write.WriteException;
+
+/**
+ * A transient utility object used to copy sheets. This
+ * functionality has been farmed out to a different class
+ * in order to reduce the bloat of the WritableSheetImpl
+ */
+class SheetCopier
+{
+ private static Logger logger = Logger.getLogger(SheetCopier.class);
+
+ private SheetImpl fromSheet;
+ private WritableSheetImpl toSheet;
+ private WorkbookSettings workbookSettings;
+
+ // Objects used by the sheet
+ private TreeSet columnFormats;
+ private FormattingRecords formatRecords;
+ private ArrayList hyperlinks;
+ private MergedCells mergedCells;
+ private ArrayList rowBreaks;
+ private ArrayList columnBreaks;
+ private SheetWriter sheetWriter;
+ private ArrayList drawings;
+ private ArrayList images;
+ private ArrayList conditionalFormats;
+ private AutoFilter autoFilter;
+ private DataValidation dataValidation;
+ private ComboBox comboBox;
+ private PLSRecord plsRecord;
+ private boolean chartOnly;
+ private ButtonPropertySetRecord buttonPropertySet;
+ private int numRows;
+ private int maxRowOutlineLevel;
+ private int maxColumnOutlineLevel;
+
+ // Objects used to maintain state during the copy process
+ private HashMap xfRecords;
+ private HashMap fonts;
+ private HashMap formats;
+
+ public SheetCopier(Sheet f, WritableSheet t)
+ {
+ fromSheet = (SheetImpl) f;
+ toSheet = (WritableSheetImpl) t;
+ workbookSettings = toSheet.getWorkbook().getSettings();
+ chartOnly = false;
+ }
+
+ void setColumnFormats(TreeSet cf)
+ {
+ columnFormats = cf;
+ }
+
+ void setFormatRecords(FormattingRecords fr)
+ {
+ formatRecords = fr;
+ }
+
+ void setHyperlinks(ArrayList h)
+ {
+ hyperlinks = h;
+ }
+
+ void setMergedCells(MergedCells mc)
+ {
+ mergedCells = mc;
+ }
+
+ void setRowBreaks(ArrayList rb)
+ {
+ rowBreaks = rb;
+ }
+
+ void setColumnBreaks(ArrayList cb)
+ {
+ columnBreaks = cb;
+ }
+
+ void setSheetWriter(SheetWriter sw)
+ {
+ sheetWriter = sw;
+ }
+
+ void setDrawings(ArrayList d)
+ {
+ drawings = d;
+ }
+
+ void setImages(ArrayList i)
+ {
+ images = i;
+ }
+
+ void setConditionalFormats(ArrayList cf)
+ {
+ conditionalFormats = cf;
+ }
+
+ AutoFilter getAutoFilter()
+ {
+ return autoFilter;
+ }
+
+ DataValidation getDataValidation()
+ {
+ return dataValidation;
+ }
+
+ ComboBox getComboBox()
+ {
+ return comboBox;
+ }
+
+ PLSRecord getPLSRecord()
+ {
+ return plsRecord;
+ }
+
+ boolean isChartOnly()
+ {
+ return chartOnly;
+ }
+
+ ButtonPropertySetRecord getButtonPropertySet()
+ {
+ return buttonPropertySet;
+ }
+
+ /**
+ * Copies a sheet from a read-only version to the writable version.
+ * Performs shallow copies
+ */
+ public void copySheet()
+ {
+ shallowCopyCells();
+
+ // Copy the column info records
+ jxl.read.biff.ColumnInfoRecord[] readCirs = fromSheet.getColumnInfos();
+
+ for (int i = 0 ; i < readCirs.length; i++)
+ {
+ jxl.read.biff.ColumnInfoRecord rcir = readCirs[i];
+ for (int j = rcir.getStartColumn(); j <= rcir.getEndColumn() ; j++)
+ {
+ ColumnInfoRecord cir = new ColumnInfoRecord(rcir, j,
+ formatRecords);
+ cir.setHidden(rcir.getHidden());
+ columnFormats.add(cir);
+ }
+ }
+
+ // Copy the hyperlinks
+ Hyperlink[] hls = fromSheet.getHyperlinks();
+ for (int i = 0 ; i < hls.length; i++)
+ {
+ WritableHyperlink hr = new WritableHyperlink
+ (hls[i], toSheet);
+ hyperlinks.add(hr);
+ }
+
+ // Copy the merged cells
+ Range[] merged = fromSheet.getMergedCells();
+
+ for (int i = 0; i < merged.length; i++)
+ {
+ mergedCells.add(new SheetRangeImpl((SheetRangeImpl)merged[i], toSheet));
+ }
+
+ // Copy the row properties
+ try
+ {
+ jxl.read.biff.RowRecord[] rowprops = fromSheet.getRowProperties();
+
+ for (int i = 0; i < rowprops.length; i++)
+ {
+ RowRecord rr = toSheet.getRowRecord(rowprops[i].getRowNumber());
+ XFRecord format = rowprops[i].hasDefaultFormat() ?
+ formatRecords.getXFRecord(rowprops[i].getXFIndex()) : null;
+ rr.setRowDetails(rowprops[i].getRowHeight(),
+ rowprops[i].matchesDefaultFontHeight(),
+ rowprops[i].isCollapsed(),
+ rowprops[i].getOutlineLevel(),
+ rowprops[i].getGroupStart(),
+ format);
+ numRows = Math.max(numRows, rowprops[i].getRowNumber() + 1);
+ }
+ }
+ catch (RowsExceededException e)
+ {
+ // Handle the rows exceeded exception - this cannot occur since
+ // the sheet we are copying from will have a valid number of rows
+ Assert.verify(false);
+ }
+
+ // Copy the headers and footers
+ // sheetWriter.setHeader(new HeaderRecord(si.getHeader()));
+ // sheetWriter.setFooter(new FooterRecord(si.getFooter()));
+
+ // Copy the page breaks
+ int[] rowbreaks = fromSheet.getRowPageBreaks();
+
+ if (rowbreaks != null)
+ {
+ for (int i = 0; i < rowbreaks.length; i++)
+ {
+ rowBreaks.add(new Integer(rowbreaks[i]));
+ }
+ }
+
+ int[] columnbreaks = fromSheet.getColumnPageBreaks();
+
+ if (columnbreaks != null)
+ {
+ for (int i = 0; i < columnbreaks.length; i++)
+ {
+ columnBreaks.add(new Integer(columnbreaks[i]));
+ }
+ }
+
+ // Copy the charts
+ sheetWriter.setCharts(fromSheet.getCharts());
+
+ // Copy the drawings
+ DrawingGroupObject[] dr = fromSheet.getDrawings();
+ for (int i = 0 ; i < dr.length ; i++)
+ {
+ if (dr[i] instanceof jxl.biff.drawing.Drawing)
+ {
+ WritableImage wi = new WritableImage
+ (dr[i], toSheet.getWorkbook().getDrawingGroup());
+ drawings.add(wi);
+ images.add(wi);
+ }
+ else if (dr[i] instanceof jxl.biff.drawing.Comment)
+ {
+ jxl.biff.drawing.Comment c =
+ new jxl.biff.drawing.Comment(dr[i],
+ toSheet.getWorkbook().getDrawingGroup(),
+ workbookSettings);
+ drawings.add(c);
+
+ // Set up the reference on the cell value
+ CellValue cv = (CellValue) toSheet.getWritableCell(c.getColumn(),
+ c.getRow());
+ Assert.verify(cv.getCellFeatures() != null);
+ cv.getWritableCellFeatures().setCommentDrawing(c);
+ }
+ else if (dr[i] instanceof jxl.biff.drawing.Button)
+ {
+ jxl.biff.drawing.Button b =
+ new jxl.biff.drawing.Button
+ (dr[i],
+ toSheet.getWorkbook().getDrawingGroup(),
+ workbookSettings);
+ drawings.add(b);
+ }
+ else if (dr[i] instanceof jxl.biff.drawing.ComboBox)
+ {
+ jxl.biff.drawing.ComboBox cb =
+ new jxl.biff.drawing.ComboBox
+ (dr[i],
+ toSheet.getWorkbook().getDrawingGroup(),
+ workbookSettings);
+ drawings.add(cb);
+ }
+ }
+
+ // Copy the data validations
+ DataValidation rdv = fromSheet.getDataValidation();
+ if (rdv != null)
+ {
+ dataValidation = new DataValidation(rdv,
+ toSheet.getWorkbook(),
+ toSheet.getWorkbook(),
+ workbookSettings);
+ int objid = dataValidation.getComboBoxObjectId();
+ if (objid != 0)
+ {
+ comboBox = (ComboBox) drawings.get(objid);
+ }
+ }
+
+ // Copy the conditional formats
+ ConditionalFormat[] cf = fromSheet.getConditionalFormats();
+ if (cf.length > 0)
+ {
+ for (int i = 0; i < cf.length ; i++)
+ {
+ conditionalFormats.add(cf[i]);
+ }
+ }
+
+ // Get the autofilter
+ autoFilter = fromSheet.getAutoFilter();
+
+ // Copy the workspace options
+ sheetWriter.setWorkspaceOptions(fromSheet.getWorkspaceOptions());
+
+ // Set a flag to indicate if it contains a chart only
+ if (fromSheet.getSheetBof().isChart())
+ {
+ chartOnly = true;
+ sheetWriter.setChartOnly();
+ }
+
+ // Copy the environment specific print record
+ if (fromSheet.getPLS() != null)
+ {
+ if (fromSheet.getWorkbookBof().isBiff7())
+ {
+ logger.warn("Cannot copy Biff7 print settings record - ignoring");
+ }
+ else
+ {
+ plsRecord = new PLSRecord(fromSheet.getPLS());
+ }
+ }
+
+ // Copy the button property set
+ if (fromSheet.getButtonPropertySet() != null)
+ {
+ buttonPropertySet = new ButtonPropertySetRecord
+ (fromSheet.getButtonPropertySet());
+ }
+
+ // Copy the outline levels
+ maxRowOutlineLevel = fromSheet.getMaxRowOutlineLevel();
+ maxColumnOutlineLevel = fromSheet.getMaxColumnOutlineLevel();
+ }
+
+ /**
+ * Copies a sheet from a read-only version to the writable version.
+ * Performs shallow copies
+ */
+ public void copyWritableSheet()
+ {
+ shallowCopyCells();
+
+ /*
+ // Copy the column formats
+ Iterator cfit = fromWritableSheet.columnFormats.iterator();
+ while (cfit.hasNext())
+ {
+ ColumnInfoRecord cv = new ColumnInfoRecord
+ ((ColumnInfoRecord) cfit.next());
+ columnFormats.add(cv);
+ }
+
+ // Copy the merged cells
+ Range[] merged = fromWritableSheet.getMergedCells();
+
+ for (int i = 0; i < merged.length; i++)
+ {
+ mergedCells.add(new SheetRangeImpl((SheetRangeImpl)merged[i], this));
+ }
+
+ // Copy the row properties
+ try
+ {
+ RowRecord[] copyRows = fromWritableSheet.rows;
+ RowRecord row = null;
+ for (int i = 0; i < copyRows.length ; i++)
+ {
+ row = copyRows[i];
+
+ if (row != null &&
+ (!row.isDefaultHeight() ||
+ row.isCollapsed()))
+ {
+ RowRecord rr = getRowRecord(i);
+ rr.setRowDetails(row.getRowHeight(),
+ row.matchesDefaultFontHeight(),
+ row.isCollapsed(),
+ row.getStyle());
+ }
+ }
+ }
+ catch (RowsExceededException e)
+ {
+ // Handle the rows exceeded exception - this cannot occur since
+ // the sheet we are copying from will have a valid number of rows
+ Assert.verify(false);
+ }
+
+ // Copy the horizontal page breaks
+ rowBreaks = new ArrayList(fromWritableSheet.rowBreaks);
+
+ // Copy the vertical page breaks
+ columnBreaks = new ArrayList(fromWritableSheet.columnBreaks);
+
+ // Copy the data validations
+ DataValidation rdv = fromWritableSheet.dataValidation;
+ if (rdv != null)
+ {
+ dataValidation = new DataValidation(rdv,
+ workbook,
+ workbook,
+ workbookSettings);
+ }
+
+ // Copy the charts
+ sheetWriter.setCharts(fromWritableSheet.getCharts());
+
+ // Copy the drawings
+ DrawingGroupObject[] dr = si.getDrawings();
+ for (int i = 0 ; i < dr.length ; i++)
+ {
+ if (dr[i] instanceof jxl.biff.drawing.Drawing)
+ {
+ WritableImage wi = new WritableImage(dr[i],
+ workbook.getDrawingGroup());
+ drawings.add(wi);
+ images.add(wi);
+ }
+
+ // Not necessary to copy the comments, as they will be handled by
+ // the deep copy of the individual cells
+ }
+
+ // Copy the workspace options
+ sheetWriter.setWorkspaceOptions(fromWritableSheet.getWorkspaceOptions());
+
+ // Copy the environment specific print record
+ if (fromWritableSheet.plsRecord != null)
+ {
+ plsRecord = new PLSRecord(fromWritableSheet.plsRecord);
+ }
+
+ // Copy the button property set
+ if (fromWritableSheet.buttonPropertySet != null)
+ {
+ buttonPropertySet = new ButtonPropertySetRecord
+ (fromWritableSheet.buttonPropertySet);
+ }
+ */
+ }
+
+ /**
+ * Imports a sheet from a different workbook, doing a deep copy
+ */
+ public void importSheet()
+ {
+ xfRecords = new HashMap();
+ fonts = new HashMap();
+ formats = new HashMap();
+
+ deepCopyCells();
+
+ // Copy the column info records
+ jxl.read.biff.ColumnInfoRecord[] readCirs = fromSheet.getColumnInfos();
+
+ for (int i = 0 ; i < readCirs.length; i++)
+ {
+ jxl.read.biff.ColumnInfoRecord rcir = readCirs[i];
+ for (int j = rcir.getStartColumn(); j <= rcir.getEndColumn() ; j++)
+ {
+ ColumnInfoRecord cir = new ColumnInfoRecord(rcir, j);
+ int xfIndex = cir.getXfIndex();
+ XFRecord cf = (WritableCellFormat) xfRecords.get(new Integer(xfIndex));
+
+ if (cf == null)
+ {
+ CellFormat readFormat = fromSheet.getColumnView(j).getFormat();
+ WritableCellFormat wcf = copyCellFormat(readFormat);
+ }
+
+ cir.setCellFormat(cf);
+ cir.setHidden(rcir.getHidden());
+ columnFormats.add(cir);
+ }
+ }
+
+ // Copy the hyperlinks
+ Hyperlink[] hls = fromSheet.getHyperlinks();
+ for (int i = 0 ; i < hls.length; i++)
+ {
+ WritableHyperlink hr = new WritableHyperlink
+ (hls[i], toSheet);
+ hyperlinks.add(hr);
+ }
+
+ // Copy the merged cells
+ Range[] merged = fromSheet.getMergedCells();
+
+ for (int i = 0; i < merged.length; i++)
+ {
+ mergedCells.add(new SheetRangeImpl((SheetRangeImpl)merged[i], toSheet));
+ }
+
+ // Copy the row properties
+ try
+ {
+ jxl.read.biff.RowRecord[] rowprops = fromSheet.getRowProperties();
+
+ for (int i = 0; i < rowprops.length; i++)
+ {
+ RowRecord rr = toSheet.getRowRecord(rowprops[i].getRowNumber());
+ XFRecord format = null;
+ jxl.read.biff.RowRecord rowrec = rowprops[i];
+ if (rowrec.hasDefaultFormat())
+ {
+ format = (WritableCellFormat)
+ xfRecords.get(new Integer(rowrec.getXFIndex()));
+
+ if (format == null)
+ {
+ int rownum = rowrec.getRowNumber();
+ CellFormat readFormat = fromSheet.getRowView(rownum).getFormat();
+ WritableCellFormat wcf = copyCellFormat(readFormat);
+ }
+ }
+
+ rr.setRowDetails(rowrec.getRowHeight(),
+ rowrec.matchesDefaultFontHeight(),
+ rowrec.isCollapsed(),
+ rowrec.getOutlineLevel(),
+ rowrec.getGroupStart(),
+ format);
+ numRows = Math.max(numRows, rowprops[i].getRowNumber() + 1);
+ }
+ }
+ catch (RowsExceededException e)
+ {
+ // Handle the rows exceeded exception - this cannot occur since
+ // the sheet we are copying from will have a valid number of rows
+ Assert.verify(false);
+ }
+
+ // Copy the headers and footers
+ // sheetWriter.setHeader(new HeaderRecord(si.getHeader()));
+ // sheetWriter.setFooter(new FooterRecord(si.getFooter()));
+
+ // Copy the page breaks
+ int[] rowbreaks = fromSheet.getRowPageBreaks();
+
+ if (rowbreaks != null)
+ {
+ for (int i = 0; i < rowbreaks.length; i++)
+ {
+ rowBreaks.add(new Integer(rowbreaks[i]));
+ }
+ }
+
+ int[] columnbreaks = fromSheet.getColumnPageBreaks();
+
+ if (columnbreaks != null)
+ {
+ for (int i = 0; i < columnbreaks.length; i++)
+ {
+ columnBreaks.add(new Integer(columnbreaks[i]));
+ }
+ }
+
+ // Copy the charts
+ Chart[] fromCharts = fromSheet.getCharts();
+ if (fromCharts != null && fromCharts.length > 0)
+ {
+ logger.warn("Importing of charts is not supported");
+ /*
+ sheetWriter.setCharts(fromSheet.getCharts());
+ IndexMapping xfMapping = new IndexMapping(200);
+ for (Iterator i = xfRecords.keySet().iterator(); i.hasNext();)
+ {
+ Integer key = (Integer) i.next();
+ XFRecord xfmapping = (XFRecord) xfRecords.get(key);
+ xfMapping.setMapping(key.intValue(), xfmapping.getXFIndex());
+ }
+
+ IndexMapping fontMapping = new IndexMapping(200);
+ for (Iterator i = fonts.keySet().iterator(); i.hasNext();)
+ {
+ Integer key = (Integer) i.next();
+ Integer fontmap = (Integer) fonts.get(key);
+ fontMapping.setMapping(key.intValue(), fontmap.intValue());
+ }
+
+ IndexMapping formatMapping = new IndexMapping(200);
+ for (Iterator i = formats.keySet().iterator(); i.hasNext();)
+ {
+ Integer key = (Integer) i.next();
+ Integer formatmap = (Integer) formats.get(key);
+ formatMapping.setMapping(key.intValue(), formatmap.intValue());
+ }
+
+ // Now reuse the rationalization feature on each chart to
+ // handle the new fonts
+ for (int i = 0; i < fromCharts.length ; i++)
+ {
+ fromCharts[i].rationalize(xfMapping, fontMapping, formatMapping);
+ }
+ */
+ }
+
+ // Copy the drawings
+ DrawingGroupObject[] dr = fromSheet.getDrawings();
+
+ // Make sure the destination workbook has a drawing group
+ // created in it
+ if (dr.length > 0 &&
+ toSheet.getWorkbook().getDrawingGroup() == null)
+ {
+ toSheet.getWorkbook().createDrawingGroup();
+ }
+
+ for (int i = 0 ; i < dr.length ; i++)
+ {
+ if (dr[i] instanceof jxl.biff.drawing.Drawing)
+ {
+ WritableImage wi = new WritableImage
+ (dr[i].getX(), dr[i].getY(),
+ dr[i].getWidth(), dr[i].getHeight(),
+ dr[i].getImageData());
+ toSheet.getWorkbook().addDrawing(wi);
+ drawings.add(wi);
+ images.add(wi);
+ }
+ else if (dr[i] instanceof jxl.biff.drawing.Comment)
+ {
+ jxl.biff.drawing.Comment c =
+ new jxl.biff.drawing.Comment(dr[i],
+ toSheet.getWorkbook().getDrawingGroup(),
+ workbookSettings);
+ drawings.add(c);
+
+ // Set up the reference on the cell value
+ CellValue cv = (CellValue) toSheet.getWritableCell(c.getColumn(),
+ c.getRow());
+ Assert.verify(cv.getCellFeatures() != null);
+ cv.getWritableCellFeatures().setCommentDrawing(c);
+ }
+ else if (dr[i] instanceof jxl.biff.drawing.Button)
+ {
+ jxl.biff.drawing.Button b =
+ new jxl.biff.drawing.Button
+ (dr[i],
+ toSheet.getWorkbook().getDrawingGroup(),
+ workbookSettings);
+ drawings.add(b);
+ }
+ else if (dr[i] instanceof jxl.biff.drawing.ComboBox)
+ {
+ jxl.biff.drawing.ComboBox cb =
+ new jxl.biff.drawing.ComboBox
+ (dr[i],
+ toSheet.getWorkbook().getDrawingGroup(),
+ workbookSettings);
+ drawings.add(cb);
+ }
+ }
+
+ // Copy the data validations
+ DataValidation rdv = fromSheet.getDataValidation();
+ if (rdv != null)
+ {
+ dataValidation = new DataValidation(rdv,
+ toSheet.getWorkbook(),
+ toSheet.getWorkbook(),
+ workbookSettings);
+ int objid = dataValidation.getComboBoxObjectId();
+ if (objid != 0)
+ {
+ comboBox = (ComboBox) drawings.get(objid);
+ }
+ }
+
+ // Copy the workspace options
+ sheetWriter.setWorkspaceOptions(fromSheet.getWorkspaceOptions());
+
+ // Set a flag to indicate if it contains a chart only
+ if (fromSheet.getSheetBof().isChart())
+ {
+ chartOnly = true;
+ sheetWriter.setChartOnly();
+ }
+
+ // Copy the environment specific print record
+ if (fromSheet.getPLS() != null)
+ {
+ if (fromSheet.getWorkbookBof().isBiff7())
+ {
+ logger.warn("Cannot copy Biff7 print settings record - ignoring");
+ }
+ else
+ {
+ plsRecord = new PLSRecord(fromSheet.getPLS());
+ }
+ }
+
+ // Copy the button property set
+ if (fromSheet.getButtonPropertySet() != null)
+ {
+ buttonPropertySet = new ButtonPropertySetRecord
+ (fromSheet.getButtonPropertySet());
+ }
+
+ importNames();
+
+ // Copy the outline levels
+ maxRowOutlineLevel = fromSheet.getMaxRowOutlineLevel();
+ maxColumnOutlineLevel = fromSheet.getMaxColumnOutlineLevel();
+ }
+
+ /**
+ * Performs a shallow copy of the specified cell
+ */
+ private WritableCell shallowCopyCell(Cell cell)
+ {
+ CellType ct = cell.getType();
+ WritableCell newCell = null;
+
+ if (ct == CellType.LABEL)
+ {
+ newCell = new Label((LabelCell) cell);
+ }
+ else if (ct == CellType.NUMBER)
+ {
+ newCell = new Number((NumberCell) cell);
+ }
+ else if (ct == CellType.DATE)
+ {
+ newCell = new DateTime((DateCell) cell);
+ }
+ else if (ct == CellType.BOOLEAN)
+ {
+ newCell = new Boolean((BooleanCell) cell);
+ }
+ else if (ct == CellType.NUMBER_FORMULA)
+ {
+ newCell = new ReadNumberFormulaRecord((FormulaData) cell);
+ }
+ else if (ct == CellType.STRING_FORMULA)
+ {
+ newCell = new ReadStringFormulaRecord((FormulaData) cell);
+ }
+ else if( ct == CellType.BOOLEAN_FORMULA)
+ {
+ newCell = new ReadBooleanFormulaRecord((FormulaData) cell);
+ }
+ else if (ct == CellType.DATE_FORMULA)
+ {
+ newCell = new ReadDateFormulaRecord((FormulaData) cell);
+ }
+ else if(ct == CellType.FORMULA_ERROR)
+ {
+ newCell = new ReadErrorFormulaRecord((FormulaData) cell);
+ }
+ else if (ct == CellType.EMPTY)
+ {
+ if (cell.getCellFormat() != null)
+ {
+ // It is a blank cell, rather than an empty cell, so
+ // it may have formatting information, so
+ // it must be copied
+ newCell = new Blank(cell);
+ }
+ }
+
+ return newCell;
+ }
+
+ /**
+ * Performs a deep copy of the specified cell, handling the cell format
+ *
+ * @param cell the cell to copy
+ */
+ private WritableCell deepCopyCell(Cell cell)
+ {
+ WritableCell c = shallowCopyCell(cell);
+
+ if (c == null)
+ {
+ return c;
+ }
+
+ if (c instanceof ReadFormulaRecord)
+ {
+ ReadFormulaRecord rfr = (ReadFormulaRecord) c;
+ boolean crossSheetReference = !rfr.handleImportedCellReferences
+ (fromSheet.getWorkbook(),
+ fromSheet.getWorkbook(),
+ workbookSettings);
+
+ if (crossSheetReference)
+ {
+ try
+ {
+ logger.warn("Formula " + rfr.getFormula() +
+ " in cell " +
+ CellReferenceHelper.getCellReference(cell.getColumn(),
+ cell.getRow()) +
+ " cannot be imported because it references another " +
+ " sheet from the source workbook");
+ }
+ catch (FormulaException e)
+ {
+ logger.warn("Formula in cell " +
+ CellReferenceHelper.getCellReference(cell.getColumn(),
+ cell.getRow()) +
+ " cannot be imported: " + e.getMessage());
+ }
+
+ // Create a new error formula and add it instead
+ c = new Formula(cell.getColumn(), cell.getRow(), "\"ERROR\"");
+ }
+ }
+
+ // Copy the cell format
+ CellFormat cf = c.getCellFormat();
+ int index = ( (XFRecord) cf).getXFIndex();
+ WritableCellFormat wcf = (WritableCellFormat)
+ xfRecords.get(new Integer(index));
+
+ if (wcf == null)
+ {
+ wcf = copyCellFormat(cf);
+ }
+
+ c.setCellFormat(wcf);
+
+ return c;
+ }
+
+ /**
+ * Perform a shallow copy of the cells from the specified sheet into this one
+ */
+ void shallowCopyCells()
+ {
+ // Copy the cells
+ int cells = fromSheet.getRows();
+ Cell[] row = null;
+ Cell cell = null;
+ for (int i = 0; i < cells; i++)
+ {
+ row = fromSheet.getRow(i);
+
+ for (int j = 0; j < row.length; j++)
+ {
+ cell = row[j];
+ WritableCell c = shallowCopyCell(cell);
+
+ // Encase the calls to addCell in a try-catch block
+ // These should not generate any errors, because we are
+ // copying from an existing spreadsheet. In the event of
+ // errors, catch the exception and then bomb out with an
+ // assertion
+ try
+ {
+ if (c != null)
+ {
+ toSheet.addCell(c);
+ }
+ }
+ catch (WriteException e)
+ {
+ Assert.verify(false);
+ }
+ }
+ }
+ numRows = toSheet.getRows();
+ }
+
+ /**
+ * Perform a deep copy of the cells from the specified sheet into this one
+ */
+ void deepCopyCells()
+ {
+ // Copy the cells
+ int cells = fromSheet.getRows();
+ Cell[] row = null;
+ Cell cell = null;
+ for (int i = 0; i < cells; i++)
+ {
+ row = fromSheet.getRow(i);
+
+ for (int j = 0; j < row.length; j++)
+ {
+ cell = row[j];
+ WritableCell c = deepCopyCell(cell);
+
+ // Encase the calls to addCell in a try-catch block
+ // These should not generate any errors, because we are
+ // copying from an existing spreadsheet. In the event of
+ // errors, catch the exception and then bomb out with an
+ // assertion
+ try
+ {
+ if (c != null)
+ {
+ toSheet.addCell(c);
+ }
+ }
+ catch (WriteException e)
+ {
+ Assert.verify(false);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns an initialized copy of the cell format
+ *
+ * @param cf the cell format to copy
+ * @return a deep copy of the cell format
+ */
+ private WritableCellFormat copyCellFormat(CellFormat cf)
+ {
+ try
+ {
+ // just do a deep copy of the cell format for now. This will create
+ // a copy of the format and font also - in the future this may
+ // need to be sorted out
+ XFRecord xfr = (XFRecord) cf;
+ WritableCellFormat f = new WritableCellFormat(xfr);
+ formatRecords.addStyle(f);
+
+ // Maintain the local list of formats
+ int xfIndex = xfr.getXFIndex();
+ xfRecords.put(new Integer(xfIndex), f);
+
+ int fontIndex = xfr.getFontIndex();
+ fonts.put(new Integer(fontIndex), new Integer(f.getFontIndex()));
+
+ int formatIndex = xfr.getFormatRecord();
+ formats.put(new Integer(formatIndex), new Integer(f.getFormatRecord()));
+
+ return f;
+ }
+ catch (NumFormatRecordsException e)
+ {
+ logger.warn("Maximum number of format records exceeded. Using " +
+ "default format.");
+
+ return WritableWorkbook.NORMAL_STYLE;
+ }
+ }
+
+ /**
+ * Imports any names defined on the source sheet to the destination workbook
+ */
+ private void importNames()
+ {
+ WorkbookParser fromWorkbook = (WorkbookParser) fromSheet.getWorkbook();
+ WritableWorkbook toWorkbook = toSheet.getWorkbook();
+ int fromSheetIndex = fromWorkbook.getIndex(fromSheet);
+ NameRecord[] nameRecords = fromWorkbook.getNameRecords();
+ String[] names = toWorkbook.getRangeNames();
+
+ for (int i = 0 ; i < nameRecords.length ;i++)
+ {
+ NameRecord.NameRange[] nameRanges = nameRecords[i].getRanges();
+
+ for (int j = 0; j < nameRanges.length; j++)
+ {
+ int nameSheetIndex = fromWorkbook.getExternalSheetIndex
+ (nameRanges[j].getExternalSheet());
+
+ if (fromSheetIndex == nameSheetIndex)
+ {
+ String name = nameRecords[i].getName();
+ if (Arrays.binarySearch(names, name) < 0)
+ {
+ toWorkbook.addNameArea(name,
+ toSheet,
+ nameRanges[j].getFirstColumn(),
+ nameRanges[j].getFirstRow(),
+ nameRanges[j].getLastColumn(),
+ nameRanges[j].getLastRow());
+ }
+ else
+ {
+ logger.warn("Named range " + name +
+ " is already present in the destination workbook");
+ }
+
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the number of rows - allows for the case where formatting has
+ * been applied to rows, even though the row has no data
+ *
+ * @return the number of rows
+ */
+ int getRows()
+ {
+ return numRows;
+ }
+
+ /**
+ * Accessor for the maximum column outline level
+ *
+ * @return the maximum column outline level, or 0 if no outlines/groups
+ */
+ public int getMaxColumnOutlineLevel()
+ {
+ return maxColumnOutlineLevel;
+ }
+
+ /**
+ * Accessor for the maximum row outline level
+ *
+ * @return the maximum row outline level, or 0 if no outlines/groups
+ */
+ public int getMaxRowOutlineLevel()
+ {
+ return maxRowOutlineLevel;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/SheetWriter.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/SheetWriter.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/SheetWriter.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,1147 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.TreeSet;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.Cell;
+import jxl.CellFeatures;
+import jxl.Range;
+import jxl.SheetSettings;
+import jxl.WorkbookSettings;
+import jxl.biff.AutoFilter;
+import jxl.biff.ConditionalFormat;
+import jxl.biff.DataValidation;
+import jxl.biff.DataValiditySettingsRecord;
+import jxl.biff.DVParser;
+import jxl.biff.WorkspaceInformationRecord;
+import jxl.biff.XFRecord;
+import jxl.biff.drawing.Chart;
+import jxl.biff.drawing.SheetDrawingWriter;
+import jxl.biff.formula.FormulaException;
+import jxl.format.Border;
+import jxl.format.BorderLineStyle;
+import jxl.format.Colour;
+import jxl.write.Blank;
+import jxl.write.WritableCell;
+import jxl.write.WritableCellFormat;
+import jxl.write.WritableHyperlink;
+import jxl.write.WriteException;
+
+/**
+ * Contains the functionality necessary for writing out a sheet. Originally
+ * this was incorporated in WritableSheetImpl, but was moved out into
+ * a dedicated class in order to reduce the over bloated nature of that
+ * class
+ */
+final class SheetWriter
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(SheetWriter.class);
+
+ /**
+ * A handle to the output file which the binary data is written to
+ */
+ private File outputFile;
+
+ /**
+ * The rows within this sheet
+ */
+ private RowRecord[] rows;
+
+ /**
+ * A number of rows. This is a count of the maximum row number + 1
+ */
+ private int numRows;
+
+ /**
+ * The number of columns. This is a count of the maximum column number + 1
+ */
+ private int numCols;
+
+ /**
+ * The page header
+ */
+ private HeaderRecord header;
+ /**
+ * The page footer
+ */
+ private FooterRecord footer;
+ /**
+ * The settings for the sheet
+ */
+ private SheetSettings settings;
+ /**
+ * The settings for the workbook
+ */
+ private WorkbookSettings workbookSettings;
+ /**
+ * Array of row page breaks
+ */
+ private ArrayList rowBreaks;
+ /**
+ * Array of column page breaks
+ */
+ private ArrayList columnBreaks;
+ /**
+ * Array of hyperlinks
+ */
+ private ArrayList hyperlinks;
+ /**
+ * Array of conditional formats
+ */
+ private ArrayList conditionalFormats;
+ /**
+ * The autofilter info
+ */
+ private AutoFilter autoFilter;
+ /**
+ * Array of validated cells
+ */
+ private ArrayList validatedCells;
+ /**
+ * The data validation validations
+ */
+ private DataValidation dataValidation;
+
+ /**
+ * The list of merged ranges
+ */
+ private MergedCells mergedCells;
+
+ /**
+ * The environment specific print record
+ */
+ private PLSRecord plsRecord;
+
+ /**
+ * The button property ste
+ */
+ private ButtonPropertySetRecord buttonPropertySet;
+
+ /**
+ * The workspace options
+ */
+ private WorkspaceInformationRecord workspaceOptions;
+ /**
+ * The column format overrides
+ */
+ private TreeSet columnFormats;
+
+ /**
+ * The list of drawings
+ */
+ private SheetDrawingWriter drawingWriter;
+
+ /**
+ * Flag indicates that this sheet contains just a chart, and nothing
+ * else
+ */
+ private boolean chartOnly;
+
+ /**
+ * The maximum row outline level
+ */
+ private int maxRowOutlineLevel;
+
+ /**
+ * The maximum column outline level
+ */
+ private int maxColumnOutlineLevel;
+
+ /**
+ * A handle back to the writable sheet, in order for this class
+ * to invoke the get accessor methods
+ */
+ private WritableSheetImpl sheet;
+
+
+ /**
+ * Creates a new SheetWriter
instance.
+ *
+ * @param of the output file
+ */
+ public SheetWriter(File of,
+ WritableSheetImpl wsi,
+ WorkbookSettings ws)
+ {
+ outputFile = of;
+ sheet = wsi;
+ workspaceOptions = new WorkspaceInformationRecord();
+ workbookSettings = ws;
+ chartOnly = false;
+ drawingWriter = new SheetDrawingWriter(ws);
+ }
+
+ /**
+ * Writes out this sheet. First writes out the standard sheet
+ * information then writes out each row in turn.
+ * Once all the rows have been written out, it retrospectively adjusts
+ * the offset references in the file
+ *
+ * @exception IOException
+ */
+ public void write() throws IOException
+ {
+ Assert.verify(rows != null);
+
+ // This worksheet consists of just one chart, so write it and return
+ if (chartOnly)
+ {
+ drawingWriter.write(outputFile);
+ return;
+ }
+
+ BOFRecord bof = new BOFRecord(BOFRecord.sheet);
+ outputFile.write(bof);
+
+ // Compute the number of blocks of 32 rows that will be needed
+ int numBlocks = numRows / 32;
+ if (numRows - numBlocks * 32 != 0)
+ {
+ numBlocks++;
+ }
+
+ int indexPos = outputFile.getPos();
+
+ // Write the index record out now in order to serve as a place holder
+ // The bof passed in is the bof of the workbook, not this sheet
+ IndexRecord indexRecord = new IndexRecord(0, numRows, numBlocks);
+ outputFile.write(indexRecord);
+
+ if (settings.getAutomaticFormulaCalculation())
+ {
+ CalcModeRecord cmr = new CalcModeRecord(CalcModeRecord.automatic);
+ outputFile.write(cmr);
+ }
+ else
+ {
+ CalcModeRecord cmr = new CalcModeRecord(CalcModeRecord.manual);
+ outputFile.write(cmr);
+ }
+
+ CalcCountRecord ccr = new CalcCountRecord(0x64);
+ outputFile.write(ccr);
+
+ RefModeRecord rmr = new RefModeRecord();
+ outputFile.write(rmr);
+
+ IterationRecord itr = new IterationRecord(false);
+ outputFile.write(itr);
+
+ DeltaRecord dtr = new DeltaRecord(0.001);
+ outputFile.write(dtr);
+
+ SaveRecalcRecord srr = new SaveRecalcRecord
+ (settings.getRecalculateFormulasBeforeSave());
+ outputFile.write(srr);
+
+ PrintHeadersRecord phr = new PrintHeadersRecord
+ (settings.getPrintHeaders());
+ outputFile.write(phr);
+
+ PrintGridLinesRecord pglr = new PrintGridLinesRecord
+ (settings.getPrintGridLines());
+ outputFile.write(pglr);
+
+ GridSetRecord gsr = new GridSetRecord(true);
+ outputFile.write(gsr);
+
+ GuttersRecord gutr = new GuttersRecord();
+ gutr.setMaxColumnOutline(maxColumnOutlineLevel + 1);
+ gutr.setMaxRowOutline(maxRowOutlineLevel + 1);
+
+ outputFile.write(gutr);
+
+ DefaultRowHeightRecord drhr = new DefaultRowHeightRecord
+ (settings.getDefaultRowHeight(),
+ settings.getDefaultRowHeight() !=
+ SheetSettings.DEFAULT_DEFAULT_ROW_HEIGHT);
+ outputFile.write(drhr);
+
+ if (maxRowOutlineLevel > 0)
+ {
+ workspaceOptions.setRowOutlines(true);
+ }
+
+ if (maxColumnOutlineLevel > 0)
+ {
+ workspaceOptions.setColumnOutlines(true);
+ }
+
+ workspaceOptions.setFitToPages(settings.getFitToPages());
+ outputFile.write(workspaceOptions);
+
+ if (rowBreaks.size() > 0)
+ {
+ int[] rb = new int[rowBreaks.size()];
+
+ for (int i = 0; i < rb.length; i++)
+ {
+ rb[i] = ( (Integer) rowBreaks.get(i)).intValue();
+ }
+
+ HorizontalPageBreaksRecord hpbr = new HorizontalPageBreaksRecord(rb);
+ outputFile.write(hpbr);
+ }
+
+ if (columnBreaks.size() > 0)
+ {
+ int[] rb = new int[columnBreaks.size()];
+
+ for (int i = 0; i < rb.length; i++)
+ {
+ rb[i] = ( (Integer) columnBreaks.get(i)).intValue();
+ }
+
+ VerticalPageBreaksRecord hpbr = new VerticalPageBreaksRecord(rb);
+ outputFile.write(hpbr);
+ }
+
+ HeaderRecord header = new HeaderRecord(settings.getHeader().toString());
+ outputFile.write(header);
+
+ FooterRecord footer = new FooterRecord(settings.getFooter().toString());
+ outputFile.write(footer);
+
+ HorizontalCentreRecord hcr = new HorizontalCentreRecord
+ (settings.isHorizontalCentre());
+ outputFile.write(hcr);
+
+ VerticalCentreRecord vcr = new VerticalCentreRecord
+ (settings.isVerticalCentre());
+ outputFile.write(vcr);
+
+ // Write out the margins if they don't equal the default
+ if (settings.getLeftMargin() != settings.getDefaultWidthMargin())
+ {
+ MarginRecord mr = new LeftMarginRecord(settings.getLeftMargin());
+ outputFile.write(mr);
+ }
+
+ if (settings.getRightMargin() != settings.getDefaultWidthMargin())
+ {
+ MarginRecord mr = new RightMarginRecord(settings.getRightMargin());
+ outputFile.write(mr);
+ }
+
+ if (settings.getTopMargin() != settings.getDefaultHeightMargin())
+ {
+ MarginRecord mr = new TopMarginRecord(settings.getTopMargin());
+ outputFile.write(mr);
+ }
+
+ if (settings.getBottomMargin() != settings.getDefaultHeightMargin())
+ {
+ MarginRecord mr = new BottomMarginRecord(settings.getBottomMargin());
+ outputFile.write(mr);
+ }
+
+ if (plsRecord != null)
+ {
+ outputFile.write(plsRecord);
+ }
+
+ SetupRecord setup = new SetupRecord(settings);
+ outputFile.write(setup);
+
+ if (settings.isProtected())
+ {
+ ProtectRecord pr = new ProtectRecord(settings.isProtected());
+ outputFile.write(pr);
+
+ ScenarioProtectRecord spr = new ScenarioProtectRecord
+ (settings.isProtected());
+ outputFile.write(spr);
+
+ ObjectProtectRecord opr = new ObjectProtectRecord
+ (settings.isProtected());
+ outputFile.write(opr);
+
+ if (settings.getPassword() != null)
+ {
+ PasswordRecord pw = new PasswordRecord(settings.getPassword());
+ outputFile.write(pw);
+ }
+ else if (settings.getPasswordHash() != 0)
+ {
+ PasswordRecord pw = new PasswordRecord(settings.getPasswordHash());
+ outputFile.write(pw);
+ }
+ }
+
+ indexRecord.setDataStartPosition(outputFile.getPos());
+ DefaultColumnWidth dcw =
+ new DefaultColumnWidth(settings.getDefaultColumnWidth());
+ outputFile.write(dcw);
+
+ // Get a handle to the normal styles
+ WritableCellFormat normalStyle =
+ sheet.getWorkbook().getStyles().getNormalStyle();
+ WritableCellFormat defaultDateFormat =
+ sheet.getWorkbook().getStyles().getDefaultDateFormat();
+
+ // Write out all the column formats
+ ColumnInfoRecord cir = null;
+ for (Iterator colit = columnFormats.iterator(); colit.hasNext() ; )
+ {
+ cir = (ColumnInfoRecord) colit.next();
+
+ // Writing out the column info with index 0x100 causes excel to crash
+ if (cir.getColumn() < 0x100)
+ {
+ outputFile.write(cir);
+ }
+
+ XFRecord xfr = cir.getCellFormat();
+
+ if (xfr != normalStyle && cir.getColumn() < 0x100)
+ {
+ // Make this the format for every cell in the column
+ Cell[] cells = getColumn(cir.getColumn());
+
+ for (int i = 0; i < cells.length; i++)
+ {
+ if (cells[i] != null &&
+ (cells[i].getCellFormat() == normalStyle ||
+ cells[i].getCellFormat() == defaultDateFormat))
+ {
+ // The cell has no overriding format specified, so
+ // set it to the column default
+ ((WritableCell) cells[i]).setCellFormat(xfr);
+ }
+ }
+ }
+ }
+
+ // Write out the auto filter
+ if (autoFilter != null)
+ {
+ autoFilter.write(outputFile);
+ }
+
+ DimensionRecord dr = new DimensionRecord(numRows, numCols);
+ outputFile.write(dr);
+
+ // Write out all the rows, in blocks of 32
+ for (int block = 0; block < numBlocks; block++)
+ {
+ DBCellRecord dbcell = new DBCellRecord(outputFile.getPos());
+
+ int blockRows = Math.min(32, numRows - block * 32);
+ boolean firstRow = true;
+
+ // First write out all the row records
+ for (int i = block * 32; i < block * 32 + blockRows; i++)
+ {
+ if (rows[i] != null)
+ {
+ rows[i].write(outputFile);
+ if (firstRow)
+ {
+ dbcell.setCellOffset(outputFile.getPos());
+ firstRow = false;
+ }
+ }
+ }
+
+ // Now write out all the cells
+ for (int i = block * 32; i < block * 32 + blockRows; i++)
+ {
+ if (rows[i] != null)
+ {
+ dbcell.addCellRowPosition(outputFile.getPos());
+ rows[i].writeCells(outputFile);
+ }
+ }
+
+ // Now set the current file position in the index record
+ indexRecord.addBlockPosition(outputFile.getPos());
+
+ // Set the position of the file pointer and write out the DBCell
+ // record
+ dbcell.setPosition(outputFile.getPos());
+ outputFile.write(dbcell);
+ }
+
+ // Do the drawings and charts if enabled
+ if (!workbookSettings.getDrawingsDisabled())
+ {
+ drawingWriter.write(outputFile);
+ }
+
+ Window2Record w2r = new Window2Record(settings);
+ outputFile.write(w2r);
+
+ // Handle the frozen panes
+ if (settings.getHorizontalFreeze() != 0 ||
+ settings.getVerticalFreeze() != 0)
+ {
+ PaneRecord pr = new PaneRecord(settings.getHorizontalFreeze(),
+ settings.getVerticalFreeze());
+ outputFile.write(pr);
+
+ // Handle the selection record. First, there will always be a top left
+ SelectionRecord sr = new SelectionRecord
+ (SelectionRecord.upperLeft, 0, 0);
+ outputFile.write(sr);
+
+ // Top right
+ if (settings.getHorizontalFreeze() != 0)
+ {
+ sr = new SelectionRecord
+ (SelectionRecord.upperRight, settings.getHorizontalFreeze(), 0);
+ outputFile.write(sr);
+ }
+
+ // Bottom left
+ if (settings.getVerticalFreeze() != 0)
+ {
+ sr = new SelectionRecord
+ (SelectionRecord.lowerLeft, 0, settings.getVerticalFreeze());
+ outputFile.write(sr);
+ }
+
+ // Bottom right
+ if (settings.getHorizontalFreeze() != 0 &&
+ settings.getVerticalFreeze() != 0)
+ {
+ sr = new SelectionRecord
+ (SelectionRecord.lowerRight,
+ settings.getHorizontalFreeze(),
+ settings.getVerticalFreeze());
+ outputFile.write(sr);
+ }
+
+ Weird1Record w1r = new Weird1Record();
+ outputFile.write(w1r);
+ }
+ else
+ {
+ // No frozen panes - just write out the selection record for the
+ // whole sheet
+ SelectionRecord sr = new SelectionRecord
+ (SelectionRecord.upperLeft, 0, 0);
+ outputFile.write(sr);
+ }
+
+ // Handle the zoom factor
+ if (settings.getZoomFactor() != 100)
+ {
+ SCLRecord sclr = new SCLRecord(settings.getZoomFactor());
+ outputFile.write(sclr);
+ }
+
+ // Now write out all the merged cells
+ mergedCells.write(outputFile);
+
+ // Write out all the hyperlinks
+ Iterator hi = hyperlinks.iterator();
+ WritableHyperlink hlr = null;
+ while (hi.hasNext())
+ {
+ hlr = (WritableHyperlink) hi.next();
+ outputFile.write(hlr);
+ }
+
+ if (buttonPropertySet != null)
+ {
+ outputFile.write(buttonPropertySet);
+ }
+
+ // Write out the data validations
+ if (dataValidation != null || validatedCells.size() > 0)
+ {
+ writeDataValidation();
+ }
+
+ // Write out the conditional formats
+ if (conditionalFormats != null && conditionalFormats.size() > 0)
+ {
+ for (Iterator i = conditionalFormats.iterator() ; i.hasNext() ; )
+ {
+ ConditionalFormat cf = (ConditionalFormat) i.next();
+ cf.write(outputFile);
+ }
+ }
+
+ EOFRecord eof = new EOFRecord();
+ outputFile.write(eof);
+
+ // Now the various cross reference offsets have been calculated,
+ // retrospectively set the values in the output file
+ outputFile.setData(indexRecord.getData(), indexPos+4);
+ }
+
+ /**
+ * Gets the header. Called when copying sheets
+ *
+ * @return the page header
+ */
+ final HeaderRecord getHeader()
+ {
+ return header;
+ }
+
+ /**
+ * Gets the footer. Called when copying sheets
+ *
+ * @return the page footer
+ */
+ final FooterRecord getFooter()
+ {
+ return footer;
+ }
+
+ /**
+ * Sets the data necessary for writing out the sheet. This method must
+ * be called immediately prior to writing
+ *
+ * @param rws the rows in the spreadsheet
+ */
+ void setWriteData(RowRecord[] rws,
+ ArrayList rb,
+ ArrayList cb,
+ ArrayList hl,
+ MergedCells mc,
+ TreeSet cf,
+ int mrol,
+ int mcol)
+ {
+ rows = rws;
+ rowBreaks = rb;
+ columnBreaks = cb;
+ hyperlinks = hl;
+ mergedCells = mc;
+ columnFormats = cf;
+ maxRowOutlineLevel = mrol;
+ maxColumnOutlineLevel = mcol;
+ }
+
+ /**
+ * Sets the dimensions of this spreadsheet. This method must be called
+ * immediately prior to writing
+ *
+ * @param rws the number of rows
+ * @param cls the number of columns
+ */
+ void setDimensions(int rws, int cls)
+ {
+ numRows = rws;
+ numCols = cls;
+ }
+
+ /**
+ * Sets the sheet settings for this particular sheet. Must be
+ * called immediately prior to writing
+ *
+ * @param sr the sheet settings
+ */
+ void setSettings(SheetSettings sr)
+ {
+ settings = sr;
+ }
+
+ /**
+ * Accessor for the workspace options
+ *
+ * @return the workspace options
+ */
+ WorkspaceInformationRecord getWorkspaceOptions()
+ {
+ return workspaceOptions;
+ }
+
+ /**
+ * Accessor for the workspace options
+ *
+ * @param wo the workspace options
+ */
+ void setWorkspaceOptions(WorkspaceInformationRecord wo)
+ {
+ if (wo != null)
+ {
+ workspaceOptions = wo;
+ }
+ }
+
+
+ /**
+ * Sets the charts for this sheet
+ *
+ * @param ch the charts
+ */
+ void setCharts(Chart[] ch)
+ {
+ drawingWriter.setCharts(ch);
+ }
+
+ /**
+ * Sets the drawings on this sheet
+ *
+ * @param dr the list of drawings
+ * @param mod a modified flag
+ */
+ void setDrawings(ArrayList dr, boolean mod)
+ {
+ drawingWriter.setDrawings(dr, mod);
+ }
+
+ /**
+ * Accessor for the charts on this sheet
+ *
+ * @return the charts
+ */
+ Chart[] getCharts()
+ {
+ return drawingWriter.getCharts();
+ }
+
+ /**
+ * Check all the merged cells for borders. If the merge record has
+ * borders, then we need to rejig the cell formats to take account of this.
+ * This is called by the write method of the WritableWorkbookImpl, so that
+ * any new XFRecords that are created may be written out with the others
+ */
+ void checkMergedBorders()
+ {
+ Range[] mcells = mergedCells.getMergedCells();
+ ArrayList borderFormats = new ArrayList();
+ for (int mci = 0 ; mci < mcells.length ; mci++)
+ {
+ Range range = mcells[mci];
+ Cell topLeft = range.getTopLeft();
+ XFRecord tlformat = (XFRecord) topLeft.getCellFormat();
+
+ if (tlformat != null &&
+ tlformat.hasBorders() == true &&
+ !tlformat.isRead())
+ {
+ try
+ {
+ CellXFRecord cf1 = new CellXFRecord(tlformat);
+ Cell bottomRight = range.getBottomRight();
+
+ cf1.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
+ cf1.setBorder(Border.LEFT,
+ tlformat.getBorderLine(Border.LEFT),
+ tlformat.getBorderColour(Border.LEFT));
+ cf1.setBorder(Border.TOP,
+ tlformat.getBorderLine(Border.TOP),
+ tlformat.getBorderColour(Border.TOP));
+
+ if (topLeft.getRow() == bottomRight.getRow())
+ {
+ cf1.setBorder(Border.BOTTOM,
+ tlformat.getBorderLine(Border.BOTTOM),
+ tlformat.getBorderColour(Border.BOTTOM));
+ }
+
+ if (topLeft.getColumn() == bottomRight.getColumn())
+ {
+ cf1.setBorder(Border.RIGHT,
+ tlformat.getBorderLine(Border.RIGHT),
+ tlformat.getBorderColour(Border.RIGHT));
+ }
+
+ int index = borderFormats.indexOf(cf1);
+ if (index != -1)
+ {
+ cf1 = (CellXFRecord) borderFormats.get(index);
+ }
+ else
+ {
+ borderFormats.add(cf1);
+ }
+ ( (WritableCell) topLeft).setCellFormat(cf1);
+
+ // Handle the bottom left corner
+ if (bottomRight.getRow() > topLeft.getRow())
+ {
+ // Handle the corner cell
+ if (bottomRight.getColumn() != topLeft.getColumn())
+ {
+ CellXFRecord cf2 = new CellXFRecord(tlformat);
+ cf2.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
+ cf2.setBorder(Border.LEFT,
+ tlformat.getBorderLine(Border.LEFT),
+ tlformat.getBorderColour(Border.LEFT));
+ cf2.setBorder(Border.BOTTOM,
+ tlformat.getBorderLine(Border.BOTTOM),
+ tlformat.getBorderColour(Border.BOTTOM));
+
+ index = borderFormats.indexOf(cf2);
+ if (index != -1)
+ {
+ cf2 = (CellXFRecord) borderFormats.get(index);
+ }
+ else
+ {
+ borderFormats.add(cf2);
+ }
+
+ sheet.addCell(new Blank(topLeft.getColumn(),
+ bottomRight.getRow(), cf2));
+ }
+
+ // Handle the cells down the left hand side (and along the
+ // right too, if necessary)
+ for (int i = topLeft.getRow() + 1; i < bottomRight.getRow() ;i++)
+ {
+ CellXFRecord cf3 = new CellXFRecord(tlformat);
+ cf3.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
+ cf3.setBorder(Border.LEFT,
+ tlformat.getBorderLine(Border.LEFT),
+ tlformat.getBorderColour(Border.LEFT));
+
+ if (topLeft.getColumn() == bottomRight.getColumn())
+ {
+ cf3.setBorder(Border.RIGHT,
+ tlformat.getBorderLine(Border.RIGHT),
+ tlformat.getBorderColour(Border.RIGHT));
+ }
+
+ index = borderFormats.indexOf(cf3);
+ if (index != -1)
+ {
+ cf3 = (CellXFRecord) borderFormats.get(index);
+ }
+ else
+ {
+ borderFormats.add(cf3);
+ }
+
+ sheet.addCell(new Blank(topLeft.getColumn(), i, cf3));
+ }
+ }
+
+ // Handle the top right corner
+ if (bottomRight.getColumn() > topLeft.getColumn())
+ {
+ if (bottomRight.getRow() != topLeft.getRow())
+ {
+ // Handle the corner cell
+ CellXFRecord cf6 = new CellXFRecord(tlformat);
+ cf6.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
+ cf6.setBorder(Border.RIGHT,
+ tlformat.getBorderLine(Border.RIGHT),
+ tlformat.getBorderColour(Border.RIGHT));
+ cf6.setBorder(Border.TOP,
+ tlformat.getBorderLine(Border.TOP),
+ tlformat.getBorderColour(Border.TOP));
+ index = borderFormats.indexOf(cf6);
+ if (index != -1)
+ {
+ cf6 = (CellXFRecord) borderFormats.get(index);
+ }
+ else
+ {
+ borderFormats.add(cf6);
+ }
+
+ sheet.addCell(new Blank(bottomRight.getColumn(),
+ topLeft.getRow(), cf6));
+ }
+
+ // Handle the cells along the right
+ for (int i = topLeft.getRow() + 1;
+ i < bottomRight.getRow() ;i++)
+ {
+ CellXFRecord cf7 = new CellXFRecord(tlformat);
+ cf7.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
+ cf7.setBorder(Border.RIGHT,
+ tlformat.getBorderLine(Border.RIGHT),
+ tlformat.getBorderColour(Border.RIGHT));
+
+ index = borderFormats.indexOf(cf7);
+ if (index != -1)
+ {
+ cf7 = (CellXFRecord) borderFormats.get(index);
+ }
+ else
+ {
+ borderFormats.add(cf7);
+ }
+
+ sheet.addCell(new Blank(bottomRight.getColumn(), i, cf7));
+ }
+
+ // Handle the cells along the top, and along the bottom too
+ for (int i = topLeft.getColumn() + 1;
+ i < bottomRight.getColumn() ;i++)
+ {
+ CellXFRecord cf8 = new CellXFRecord(tlformat);
+ cf8.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
+ cf8.setBorder(Border.TOP,
+ tlformat.getBorderLine(Border.TOP),
+ tlformat.getBorderColour(Border.TOP));
+
+ if (topLeft.getRow() == bottomRight.getRow())
+ {
+ cf8.setBorder(Border.BOTTOM,
+ tlformat.getBorderLine(Border.BOTTOM),
+ tlformat.getBorderColour(Border.BOTTOM));
+ }
+
+ index = borderFormats.indexOf(cf8);
+ if (index != -1)
+ {
+ cf8 = (CellXFRecord) borderFormats.get(index);
+ }
+ else
+ {
+ borderFormats.add(cf8);
+ }
+
+ sheet.addCell(new Blank(i, topLeft.getRow(), cf8));
+ }
+ }
+
+ // Handle the bottom right corner
+ if (bottomRight.getColumn() > topLeft.getColumn() ||
+ bottomRight.getRow() > topLeft.getRow())
+ {
+ // Handle the corner cell
+ CellXFRecord cf4 = new CellXFRecord(tlformat);
+ cf4.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
+ cf4.setBorder(Border.RIGHT,
+ tlformat.getBorderLine(Border.RIGHT),
+ tlformat.getBorderColour(Border.RIGHT));
+ cf4.setBorder(Border.BOTTOM,
+ tlformat.getBorderLine(Border.BOTTOM),
+ tlformat.getBorderColour(Border.BOTTOM));
+
+ if (bottomRight.getRow() == topLeft.getRow())
+ {
+ cf4.setBorder(Border.TOP,
+ tlformat.getBorderLine(Border.TOP),
+ tlformat.getBorderColour(Border.TOP));
+ }
+
+ if (bottomRight.getColumn() == topLeft.getColumn())
+ {
+ cf4.setBorder(Border.LEFT,
+ tlformat.getBorderLine(Border.LEFT),
+ tlformat.getBorderColour(Border.LEFT));
+ }
+
+ index = borderFormats.indexOf(cf4);
+ if (index != -1)
+ {
+ cf4 = (CellXFRecord) borderFormats.get(index);
+ }
+ else
+ {
+ borderFormats.add(cf4);
+ }
+
+ sheet.addCell(new Blank(bottomRight.getColumn(),
+ bottomRight.getRow(), cf4));
+
+ // Handle the cells along the bottom (and along the top
+ // as well, if appropriate)
+ for (int i = topLeft.getColumn() + 1;
+ i < bottomRight.getColumn() ;i++)
+ {
+ CellXFRecord cf5 = new CellXFRecord(tlformat);
+ cf5.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
+ cf5.setBorder(Border.BOTTOM,
+ tlformat.getBorderLine(Border.BOTTOM),
+ tlformat.getBorderColour(Border.BOTTOM));
+
+ if (topLeft.getRow() == bottomRight.getRow())
+ {
+ cf5.setBorder(Border.TOP,
+ tlformat.getBorderLine(Border.TOP),
+ tlformat.getBorderColour(Border.TOP));
+ }
+
+ index = borderFormats.indexOf(cf5);
+ if (index != -1)
+ {
+ cf5 = (CellXFRecord) borderFormats.get(index);
+ }
+ else
+ {
+ borderFormats.add(cf5);
+ }
+
+ sheet.addCell(new Blank(i, bottomRight.getRow(), cf5));
+ }
+ }
+ }
+ catch (WriteException e)
+ {
+ // just log e.toString(), not the whole stack trace
+ logger.warn(e.toString());
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the cells in the column. Don't use the interface method
+ * getColumn for this as this will create loads of empty cells,
+ * and we could do without that overhead
+ */
+ private Cell[] getColumn(int col)
+ {
+ // Find the last non-null cell
+ boolean found = false;
+ int row = numRows - 1;
+
+ while (row >= 0 && !found)
+ {
+ if (rows[row] != null &&
+ rows[row].getCell(col) != null)
+ {
+ found = true;
+ }
+ else
+ {
+ row--;
+ }
+ }
+
+ // Only create entries for non-empty cells
+ Cell[] cells = new Cell[row+1];
+
+ for (int i = 0; i <= row; i++)
+ {
+ cells[i] = rows[i] != null ? rows[i].getCell(col) : null;
+ }
+
+ return cells;
+ }
+
+ /**
+ * Sets a flag to indicate that this sheet contains a chart only
+ */
+ void setChartOnly()
+ {
+ chartOnly = true;
+ }
+
+ /**
+ * Sets the environment specific print record
+ *
+ * @param pls the print record
+ */
+ void setPLS(PLSRecord pls)
+ {
+ plsRecord = pls;
+ }
+
+ /**
+ * Sets the button property set record
+ *
+ * @param bps the button property set
+ */
+ void setButtonPropertySet(ButtonPropertySetRecord bps)
+ {
+ buttonPropertySet = bps;
+ }
+
+ /**
+ * Sets the data validations
+ *
+ * @param dv the read-in list of data validations
+ * @param vc the api manipulated set of data validations
+ */
+ void setDataValidation(DataValidation dv, ArrayList vc)
+ {
+ dataValidation = dv;
+ validatedCells = vc;
+ }
+
+ /**
+ * Sets the conditional formats
+ *
+ * @param cf the conditonal formats
+ */
+ void setConditionalFormats(ArrayList cf)
+ {
+ conditionalFormats = cf;
+ }
+
+ /**
+ * Sets the auto filter
+ *
+ * @param af the autofilter
+ */
+ void setAutoFilter(AutoFilter af)
+ {
+ autoFilter = af;
+ }
+
+ /**
+ * Writes out the data validations
+ */
+ private void writeDataValidation() throws IOException
+ {
+ if (dataValidation != null && validatedCells.size() == 0)
+ {
+ // only data validations are those read in
+ dataValidation.write(outputFile);
+ return;
+ }
+
+ if (dataValidation == null && validatedCells.size() > 0)
+ {
+ int comboBoxId = sheet.getComboBox() != null ?
+ sheet.getComboBox().getObjectId() : DataValidation.DEFAULT_OBJECT_ID;
+ dataValidation = new DataValidation(comboBoxId,
+ sheet.getWorkbook(),
+ sheet.getWorkbook(),
+ workbookSettings);
+
+ for (Iterator i = validatedCells.iterator(); i.hasNext(); )
+ {
+ CellValue cv = (CellValue) i.next();
+ CellFeatures cf = cv.getCellFeatures();
+ DataValiditySettingsRecord dvsr =
+ new DataValiditySettingsRecord(cf.getDVParser());
+ dataValidation.add(dvsr);
+ }
+ dataValidation.write(outputFile);
+ return;
+ }
+
+ // Read and write validations
+ for (Iterator i = validatedCells.iterator(); i.hasNext(); )
+ {
+ CellValue cv = (CellValue) i.next();
+ CellFeatures cf = cv.getCellFeatures();
+ DataValiditySettingsRecord dvsr =
+ new DataValiditySettingsRecord(cf.getDVParser());
+ dataValidation.add(dvsr);
+ }
+ dataValidation.write(outputFile);
+ return;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/SortRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/SortRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/SortRecord.java 17 Aug 2012 14:51:08 -0000 1.1
@@ -0,0 +1,118 @@
+/*********************************************************************
+ *
+ * Copyright (C) 200r Andrew Khan, Al Mantei
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Record which specifies sort dialog box values
+ */
+class SortRecord extends WritableRecordData
+{
+ private String column1Name;
+ private String column2Name;
+ private String column3Name;
+ private boolean sortColumns;
+ private boolean sortKey1Desc;
+ private boolean sortKey2Desc;
+ private boolean sortKey3Desc;
+ private boolean sortCaseSensitive;
+
+ /**
+ * Constructor
+ *
+ * @param a Sort Column 1 Name
+ * @param b Sort Column 2 Name
+ * @param c Sort Column 3 Name
+ * @param sc Sort Columns
+ * @param sk1d Sort Key 1 Descending
+ * @param sk2d Sort Key 2 Descending
+ * @param sk3d Sort Key 3 Descending
+ * @param scs Sort Case Sensitive
+ */
+ public SortRecord(String a, String b, String c,
+ boolean sc, boolean sk1d,
+ boolean sk2d, boolean sk3d, boolean scs)
+ {
+ super(Type.SORT);
+
+ column1Name = a;
+ column2Name = b;
+ column3Name = c;
+ sortColumns = sc;
+ sortKey1Desc = sk1d;
+ sortKey2Desc = sk2d;
+ sortKey3Desc = sk3d;
+ sortCaseSensitive = scs;
+ }
+
+/**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ int byteCount = 5 + (column1Name.length() * 2) + 1;
+ if (column2Name.length() > 0)
+ byteCount += (column2Name.length() * 2) + 1;
+ if (column3Name.length() > 0)
+ byteCount += (column3Name.length() * 2) + 1;
+ byte[] data = new byte[byteCount + 1];
+ // there is supposed to be an extra "unused" byte at the end
+ int optionFlag = 0;
+ if (sortColumns)
+ optionFlag = optionFlag | 0x01;
+ if (sortKey1Desc)
+ optionFlag = optionFlag | 0x02;
+ if (sortKey2Desc)
+ optionFlag = optionFlag | 0x04;
+ if (sortKey3Desc)
+ optionFlag = optionFlag | 0x08;
+ if (sortCaseSensitive)
+ optionFlag = optionFlag | 0x10;
+
+ data[0] = (byte) optionFlag;
+ // data[1] is an index for sorting by a list - not implemented
+ data[2] = (byte) column1Name.length();
+ data[3] = (byte) column2Name.length();
+ data[4] = (byte) column3Name.length();
+ // always write the headings in unicode
+ data[5] = 0x01;
+ StringHelper.getUnicodeBytes(column1Name, data, 6);
+ int curPos = 6 + (column1Name.length() * 2);
+ if (column2Name.length() > 0)
+ {
+ data[curPos++] = 0x01;
+ StringHelper.getUnicodeBytes(column2Name, data, curPos);
+ curPos += column2Name.length() * 2;
+ }
+ if (column3Name.length() > 0)
+ {
+ data[curPos++] = 0x01;
+ StringHelper.getUnicodeBytes(column3Name, data, curPos);
+ curPos += column3Name.length() * 2;
+ }
+
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/StringRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/StringRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/StringRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,62 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores the string result of a formula calculation. This record
+ * occurs immediately after the formula
+ */
+class StringRecord extends WritableRecordData
+{
+ /**
+ * The string value
+ */
+ private String value;
+
+ /**
+ * Constructor
+ */
+ public StringRecord(String val)
+ {
+ super(Type.STRING);
+
+ value = val;
+ }
+
+ /**
+ * The binary data to be written out
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[value.length() * 2 + 3];
+ IntegerHelper.getTwoBytes(value.length(), data, 0);
+ data[2] = 0x01; // unicode
+ StringHelper.getUnicodeBytes(value, data, 3);
+
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/StyleXFRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/StyleXFRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/StyleXFRecord.java 17 Aug 2012 14:51:08 -0000 1.1
@@ -0,0 +1,67 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.DisplayFormat;
+import jxl.biff.FontRecord;
+import jxl.biff.XFRecord;
+
+/**
+ * A style XF Record
+ */
+public class StyleXFRecord extends XFRecord
+{
+ /**
+ * Constructor
+ *
+ * @param fnt the font for this style
+ * @param form the format of this style
+ */
+ public StyleXFRecord(FontRecord fnt, DisplayFormat form)
+ {
+ super(fnt, form);
+
+ setXFDetails(XFRecord.style, 0xfff0);
+ }
+
+
+ /**
+ * Sets the raw cell options. Called by WritableFormattingRecord
+ * when setting the built in cell formats
+ *
+ * @param opt the cell options
+ */
+ public final void setCellOptions(int opt)
+ {
+ super.setXFCellOptions(opt);
+ }
+
+ /**
+ * Sets whether or not this XF record locks the cell
+ *
+ * @param l the locked flag
+ * @exception WriteException
+ */
+ public void setLocked(boolean l)
+ {
+ super.setXFLocked(l);
+ }
+
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/Styles.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/Styles.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/Styles.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,225 @@
+/*********************************************************************
+*
+* Copyright (C) 2004 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Logger;
+
+import jxl.biff.XFRecord;
+import jxl.write.DateFormat;
+import jxl.write.DateFormats;
+import jxl.write.NumberFormats;
+import jxl.write.WritableCellFormat;
+import jxl.write.WritableFont;
+import jxl.write.WritableWorkbook;
+
+/**
+ * A structure containing the styles used by this workbook. This is used
+ * to enforce thread safety by tying the default styles to a workbook
+ * instance rather than by initializing them statically
+ */
+class Styles
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(Styles.class);
+
+ /**
+ * The default font for Cell formats
+ */
+ private WritableFont arial10pt;
+
+ /**
+ * The font used for hyperlinks
+ */
+ private WritableFont hyperlinkFont;
+
+ /**
+ * The default style for cells
+ */
+ private WritableCellFormat normalStyle;
+
+ /**
+ * The style used for hyperlinks
+ */
+ private WritableCellFormat hyperlinkStyle;
+
+ /**
+ * A cell format used to hide the cell contents
+ */
+ private WritableCellFormat hiddenStyle;
+
+ /**
+ * A cell format used for the default date format
+ */
+ private WritableCellFormat defaultDateFormat;
+
+ /**
+ * Constructor
+ */
+ public Styles()
+ {
+ arial10pt = null;
+ hyperlinkFont = null;
+ normalStyle = null;
+ hyperlinkStyle = null;
+ hiddenStyle = null;
+ }
+
+ private synchronized void initNormalStyle()
+ {
+ normalStyle = new WritableCellFormat(getArial10Pt(),
+ NumberFormats.DEFAULT);
+ normalStyle.setFont(getArial10Pt());
+ }
+
+ public WritableCellFormat getNormalStyle()
+ {
+ if (normalStyle == null)
+ {
+ initNormalStyle();
+ }
+
+ return normalStyle;
+ }
+
+ private synchronized void initHiddenStyle()
+ {
+ hiddenStyle = new WritableCellFormat
+ (getArial10Pt(), new DateFormat(";;;"));
+ }
+
+ public WritableCellFormat getHiddenStyle()
+ {
+ if (hiddenStyle == null)
+ {
+ initHiddenStyle();
+ }
+
+ return hiddenStyle;
+ }
+
+ private synchronized void initHyperlinkStyle()
+ {
+ hyperlinkStyle = new WritableCellFormat(getHyperlinkFont(),
+ NumberFormats.DEFAULT);
+ }
+
+ public WritableCellFormat getHyperlinkStyle()
+ {
+ if (hyperlinkStyle == null)
+ {
+ initHyperlinkStyle();
+ }
+
+ return hyperlinkStyle;
+ }
+
+ private synchronized void initArial10Pt()
+ {
+ arial10pt = new WritableFont(WritableWorkbook.ARIAL_10_PT);
+ }
+
+ public WritableFont getArial10Pt()
+ {
+ if (arial10pt == null)
+ {
+ initArial10Pt();
+ }
+
+ return arial10pt;
+ }
+
+ private synchronized void initHyperlinkFont()
+ {
+ hyperlinkFont = new WritableFont(WritableWorkbook.HYPERLINK_FONT);
+ }
+
+ public WritableFont getHyperlinkFont()
+ {
+ if (hyperlinkFont == null)
+ {
+ initHyperlinkFont();
+ }
+
+ return hyperlinkFont;
+ }
+
+ private synchronized void initDefaultDateFormat()
+ {
+ defaultDateFormat = new WritableCellFormat(DateFormats.DEFAULT);
+ }
+
+ public WritableCellFormat getDefaultDateFormat()
+ {
+ if (defaultDateFormat == null)
+ {
+ initDefaultDateFormat();
+ }
+
+ return defaultDateFormat;
+ }
+
+ /**
+ * Gets the thread safe version of the cell format passed in. If the
+ * format is already thread safe (ie. it doesn't use a statically initialized
+ * format or font) then the same object is simply returned
+ * This object is already tied to a workbook instance, so no synchronisation
+ * is necesasry
+ *
+ * @param wf a format to verify
+ * @return the thread safe format
+ */
+ public XFRecord getFormat(XFRecord wf)
+ {
+ XFRecord format = wf;
+
+ // Check to see if the format is one of the shared Workbook defaults. If
+ // so, then get hold of the Workbook's specific instance
+ if (format == WritableWorkbook.NORMAL_STYLE)
+ {
+ format = getNormalStyle();
+ }
+ else if (format == WritableWorkbook.HYPERLINK_STYLE)
+ {
+ format = getHyperlinkStyle();
+ }
+ else if (format == WritableWorkbook.HIDDEN_STYLE)
+ {
+ format = getHiddenStyle();
+ }
+ else if (format == DateRecord.defaultDateFormat)
+ {
+ format = getDefaultDateFormat();
+ }
+
+ // Do the same with the statically shared fonts
+ if (format.getFont() == WritableWorkbook.ARIAL_10_PT)
+ {
+ format.setFont(getArial10Pt());
+ }
+ else if (format.getFont() == WritableWorkbook.HYPERLINK_FONT)
+ {
+ format.setFont(getHyperlinkFont());
+ }
+
+ return format;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/SupbookRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/SupbookRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/SupbookRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,349 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.WorkbookSettings;
+import jxl.biff.EncodedURLHelper;
+import jxl.biff.IntegerHelper;
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores the supporting workbook information. For files written by
+ * JExcelApi this will only reference internal sheets
+ */
+class SupbookRecord extends WritableRecordData
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(SupbookRecord.class);
+
+ /**
+ * The type of this supbook record
+ */
+ private SupbookType type;
+
+ /**
+ * The data to be written to the binary file
+ */
+ private byte[] data;
+
+ /**
+ * The number of sheets - internal & external supbooks only
+ */
+ private int numSheets;
+
+ /**
+ * The name of the external file
+ */
+ private String fileName;
+
+ /**
+ * The names of the external sheets
+ */
+ private String[] sheetNames;
+
+ /**
+ * The workbook settings
+ */
+ private WorkbookSettings workbookSettings;
+
+ /**
+ * The type of supbook this refers to
+ */
+ private static class SupbookType {};
+
+ public final static SupbookType INTERNAL = new SupbookType();
+ public final static SupbookType EXTERNAL = new SupbookType();
+ public final static SupbookType ADDIN = new SupbookType();
+ public final static SupbookType LINK = new SupbookType();
+ public final static SupbookType UNKNOWN = new SupbookType();
+
+ /**
+ * Constructor for add in function names
+ */
+ public SupbookRecord()
+ {
+ super(Type.SUPBOOK);
+ type = ADDIN;
+ try
+ {
+ throw new Exception();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Constructor for internal sheets
+ */
+ public SupbookRecord(int sheets, WorkbookSettings ws)
+ {
+ super(Type.SUPBOOK);
+
+ numSheets = sheets;
+ type = INTERNAL;
+ workbookSettings = ws;
+ }
+
+ /**
+ * Constructor for external sheets
+ *
+ * @param fn the filename of the external supbook
+ * @param ws the workbook settings
+ */
+ public SupbookRecord(String fn, WorkbookSettings ws)
+ {
+ super(Type.SUPBOOK);
+
+ fileName = fn;
+ numSheets = 1;
+ sheetNames = new String[0];
+ workbookSettings = ws;
+
+ type = EXTERNAL;
+ }
+
+ /**
+ * Constructor used when copying from an external workbook
+ */
+ public SupbookRecord(jxl.read.biff.SupbookRecord sr, WorkbookSettings ws)
+ {
+ super(Type.SUPBOOK);
+
+ workbookSettings = ws;
+ if (sr.getType() == sr.INTERNAL)
+ {
+ type = INTERNAL;
+ numSheets = sr.getNumberOfSheets();
+ }
+ else if (sr.getType() == sr.EXTERNAL)
+ {
+ type = EXTERNAL;
+ numSheets = sr.getNumberOfSheets();
+ fileName = sr.getFileName();
+ sheetNames = new String[numSheets];
+
+ for (int i = 0; i < numSheets; i++)
+ {
+ sheetNames[i] = sr.getSheetName(i);
+ }
+ }
+
+ if (sr.getType() == sr.ADDIN)
+ {
+ logger.warn("Supbook type is addin");
+ }
+ }
+
+ /**
+ * Initializes an internal supbook record
+ *
+ * @param sr the read supbook record to copy from
+ */
+ private void initInternal(jxl.read.biff.SupbookRecord sr)
+ {
+ numSheets = sr.getNumberOfSheets();
+ initInternal();
+ }
+
+ /**
+ * Initializes an internal supbook record
+ */
+ private void initInternal()
+ {
+ data = new byte[4];
+
+ IntegerHelper.getTwoBytes(numSheets, data, 0);
+ data[2] = 0x1;
+ data[3] = 0x4;
+ type = INTERNAL;
+ }
+
+ /**
+ * Adjust the number of internal sheets. Called by WritableSheet when
+ * a sheet is added or or removed to the workbook
+ *
+ * @param sheets the new number of sheets
+ */
+ void adjustInternal(int sheets)
+ {
+ Assert.verify(type == INTERNAL);
+ numSheets = sheets;
+ initInternal();
+ }
+
+ /**
+ * Initializes an external supbook record
+ */
+ private void initExternal()
+ {
+ int totalSheetNameLength = 0;
+ for (int i = 0; i < numSheets; i++)
+ {
+ totalSheetNameLength += sheetNames[i].length();
+ }
+
+ byte[] fileNameData = EncodedURLHelper.getEncodedURL(fileName,
+ workbookSettings);
+ int dataLength = 2 + // numsheets
+ 4 + fileNameData.length +
+ numSheets * 3 + totalSheetNameLength * 2;
+
+ data = new byte[dataLength];
+
+ IntegerHelper.getTwoBytes(numSheets, data, 0);
+
+ // Add in the file name. Precede with a byte denoting that it is a
+ // file name
+ int pos = 2;
+ IntegerHelper.getTwoBytes(fileNameData.length+1, data, pos);
+ data[pos+2] = 0; // ascii indicator
+ data[pos+3] = 1; // file name indicator
+ System.arraycopy(fileNameData, 0, data, pos+4, fileNameData.length);
+
+ pos += 4 + fileNameData.length;
+
+ // Get the sheet names
+ for (int i = 0; i < sheetNames.length; i++)
+ {
+ IntegerHelper.getTwoBytes(sheetNames[i].length(), data, pos);
+ data[pos+2] = 1; // unicode indicator
+ StringHelper.getUnicodeBytes(sheetNames[i], data, pos+3);
+ pos += 3 + sheetNames[i].length() * 2;
+ }
+ }
+
+ /**
+ * Initializes the supbook record for add in functions
+ */
+ private void initAddin()
+ {
+ data = new byte[] {0x1, 0x0, 0x1, 0x3a};
+ }
+
+ /**
+ * The binary data to be written out
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ if (type == INTERNAL)
+ {
+ initInternal();
+ }
+ else if (type == EXTERNAL)
+ {
+ initExternal();
+ }
+ else if (type == ADDIN)
+ {
+ initAddin();
+ }
+ else
+ {
+ logger.warn("unsupported supbook type - defaulting to internal");
+ initInternal();
+ }
+
+ return data;
+ }
+
+ /**
+ * Gets the type of this supbook record
+ *
+ * @return the type of this supbook
+ */
+ public SupbookType getType()
+ {
+ return type;
+ }
+
+ /**
+ * Gets the number of sheets. This will only be non-zero for internal
+ * and external supbooks
+ *
+ * @return the number of sheets
+ */
+ public int getNumberOfSheets()
+ {
+ return numSheets;
+ }
+
+ /**
+ * Accessor for the file name
+ *
+ * @return the file name
+ */
+ public String getFileName()
+ {
+ return fileName;
+ }
+
+ /**
+ * Adds the worksheet name to this supbook
+ *
+ * @param name the worksheet name
+ * @return the index of this sheet in the supbook record
+ */
+ public int getSheetIndex(String s)
+ {
+ boolean found = false;
+ int sheetIndex = 0;
+ for (int i = 0; i < sheetNames.length && !found; i++)
+ {
+ if (sheetNames[i].equals(s))
+ {
+ found = true;
+ sheetIndex = 0;
+ }
+ }
+
+ if (found)
+ {
+ return sheetIndex;
+ }
+
+ // Grow the array
+ String[] names = new String[sheetNames.length + 1];
+ System.arraycopy(sheetNames, 0, names, 0, sheetNames.length);
+ names[sheetNames.length] = s;
+ sheetNames = names;
+ return sheetNames.length - 1;
+ }
+
+ /**
+ * Accessor for the sheet name
+ *
+ * @param s the sheet index
+ */
+ public String getSheetName(int s)
+ {
+ return sheetNames[s];
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/TabIdRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/TabIdRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/TabIdRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,62 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Contains an array of sheet tab index numbers
+ */
+class TabIdRecord extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param sheets the number of sheets
+ */
+ public TabIdRecord(int sheets)
+ {
+ super(Type.TABID);
+
+ data = new byte[sheets * 2];
+
+ for (int i = 0 ; i < sheets; i++)
+ {
+ IntegerHelper.getTwoBytes(i+1, data, i * 2);
+ }
+ }
+
+ /**
+ * Gets the data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/TopMarginRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/TopMarginRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/TopMarginRecord.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,33 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+
+/**
+ * The settings for the left margin
+ */
+class TopMarginRecord extends MarginRecord
+{
+ TopMarginRecord(double v)
+ {
+ super(Type.TOPMARGIN, v);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/UsesElfsRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/UsesElfsRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/UsesElfsRecord.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,66 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores the flag which indicates whether the version of excel can
+ * understand natural language input for formulae
+ */
+class UsesElfsRecord extends WritableRecordData
+{
+ /**
+ * The binary data for output to file
+ */
+ private byte[] data;
+ /**
+ * The uses ELFs flag
+ */
+ private boolean usesElfs;
+
+ /**
+ * Constructor
+ */
+ public UsesElfsRecord()
+ {
+ super(Type.USESELFS);
+
+ usesElfs = true;
+
+ data = new byte[2];
+
+ if (usesElfs)
+ {
+ data[0] = 1;
+ }
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/VerticalCentreRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/VerticalCentreRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/VerticalCentreRecord.java 17 Aug 2012 14:51:08 -0000 1.1
@@ -0,0 +1,70 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Indicates whether the centre vertically on page option has been
+ * set from the options dialog box
+ */
+class VerticalCentreRecord extends WritableRecordData
+{
+ /**
+ * The binary data for output to file
+ */
+ private byte[] data;
+ /**
+ * The centre flag
+ */
+ private boolean centre;
+
+ /**
+ * Constructor
+ *
+ * @param ce the centre flag
+ */
+ public VerticalCentreRecord(boolean ce)
+ {
+ super(Type.VCENTER);
+
+ centre = ce;
+
+ data = new byte[2];
+
+ if (centre)
+ {
+ data[0] = 1;
+ }
+ }
+
+ /**
+ * Gets the data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/VerticalPageBreaksRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/VerticalPageBreaksRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/VerticalPageBreaksRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,72 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Contains the list of explicit horizontal page breaks on the current sheet
+ */
+class VerticalPageBreaksRecord extends WritableRecordData
+{
+ /**
+ * The row breaks
+ */
+ private int[] columnBreaks;
+
+ /**
+ * Constructor
+ *
+ * @param break the row breaks
+ */
+ public VerticalPageBreaksRecord(int[] breaks)
+ {
+ super(Type.VERTICALPAGEBREAKS);
+
+ columnBreaks = breaks;
+ }
+
+ /**
+ * Gets the binary data to write to the output file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[columnBreaks.length * 6 + 2];
+
+ // The number of breaks on the list
+ IntegerHelper.getTwoBytes(columnBreaks.length, data, 0);
+ int pos = 2;
+
+ for (int i = 0; i < columnBreaks.length; i++)
+ {
+ IntegerHelper.getTwoBytes(columnBreaks[i], data, pos);
+ IntegerHelper.getTwoBytes(0xff, data, pos+4);
+ pos += 6;
+ }
+
+ return data;
+ }
+}
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/Weird1Record.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/Weird1Record.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/Weird1Record.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,51 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Don't know what this does - something to do with freezing panes I think
+ */
+class Weird1Record extends WritableRecordData
+{
+ /**
+ * Constructor
+ */
+ public Weird1Record()
+ {
+ super(Type.WEIRD1);
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ byte[] data = new byte[6];
+
+ data[2] = 0x37;
+
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/Window1Record.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/Window1Record.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/Window1Record.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,83 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Contains workbook level windowing attributes
+ */
+class Window1Record extends WritableRecordData
+{
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * The selected sheet
+ */
+ private int selectedSheet;
+
+ /**
+ * Constructor
+ */
+ public Window1Record(int selSheet)
+ {
+ super(Type.WINDOW1);
+
+ selectedSheet = selSheet;
+
+ // hard code the data in for now
+ data = new byte[]
+ {(byte) 0x68,
+ (byte) 0x1,
+ (byte) 0xe,
+ (byte) 0x1,
+ (byte) 0x5c,
+ (byte) 0x3a,
+ (byte) 0xbe,
+ (byte) 0x23,
+ (byte) 0x38,
+ (byte) 0,
+ (byte) 0,
+ (byte) 0,
+ (byte) 0,
+ (byte) 0,
+ (byte) 0x1,
+ (byte) 0,
+ (byte) 0x58,
+ (byte) 0x2 };
+
+ IntegerHelper.getTwoBytes(selectedSheet, data, 10);
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/Window2Record.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/Window2Record.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/Window2Record.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,106 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.SheetSettings;
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Contains the window attributes for a worksheet
+ */
+class Window2Record extends WritableRecordData
+{
+ /**
+ * The binary data for output to file
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ */
+ public Window2Record(SheetSettings settings)
+ {
+ super(Type.WINDOW2);
+
+ int options = 0;
+
+ options |= 0x0; // display formula values, not formulas
+
+ if (settings.getShowGridLines())
+ {
+ options |= 0x02;
+ }
+
+ options |= 0x04; // display row and column headings
+
+ options |= 0x0; // panes should be not frozen
+
+ if (settings.getDisplayZeroValues())
+ {
+ options |= 0x10;
+ }
+
+ options |= 0x20; // default header
+
+ options |= 0x80; // display outline symbols
+
+ // Handle the freeze panes
+ if (settings.getHorizontalFreeze() != 0 ||
+ settings.getVerticalFreeze() != 0)
+ {
+ options |= 0x08;
+ options |= 0x100;
+ }
+
+ // Handle the selected flag
+ if (settings.isSelected())
+ {
+ options |= 0x600;
+ }
+
+ // Handle the view mode
+ if (settings.getPageBreakPreviewMode())
+ {
+ options |= 0x800;
+ }
+
+ // hard code the data in for now
+ data = new byte[18];
+ IntegerHelper.getTwoBytes(options, data, 0);
+ IntegerHelper.getTwoBytes(0x40, data, 6); // grid line colour
+ IntegerHelper.getTwoBytes(settings.getPageBreakPreviewMagnification(),
+ data, 10);
+ IntegerHelper.getTwoBytes(settings.getNormalMagnification(),
+ data, 12);
+
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/WindowProtectRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/WindowProtectRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/WindowProtectRecord.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,68 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.IntegerHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * Stores an option from the Protect Workbook dialog box
+ */
+class WindowProtectRecord extends WritableRecordData
+{
+ /**
+ * Protect flag
+ */
+ private boolean protection;
+ /**
+ * The binary data
+ */
+ private byte[] data;
+
+ /**
+ * Constructor
+ *
+ * @param prot the protect flag
+ */
+ public WindowProtectRecord(boolean prot)
+ {
+ super(Type.WINDOWPROTECT);
+
+ protection = prot;
+
+ data = new byte[2];
+
+ if (protection)
+ {
+ IntegerHelper.getTwoBytes(1, data, 0);
+ }
+ }
+
+ /**
+ * Gets the binary data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/WritableFontRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/WritableFontRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/WritableFontRecord.java 17 Aug 2012 14:51:09 -0000 1.1
@@ -0,0 +1,174 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.FontRecord;
+import jxl.format.Font;
+import jxl.write.WriteException;
+
+/**
+ * A writable Font record. This class intercepts any set accessor calls
+ * and throws and exception if the Font is already initialized
+ */
+public class WritableFontRecord extends FontRecord
+{
+ /**
+ * Constructor, used when creating a new font for writing out.
+ *
+ * @param bold the bold indicator
+ * @param ps the point size
+ * @param us the underline style
+ * @param fn the name
+ * @param it italicised indicator
+ * @param c the colour
+ * @param ss the script style
+ */
+ protected WritableFontRecord(String fn, int ps, int bold, boolean it,
+ int us, int ci, int ss)
+ {
+ super(fn, ps, bold, it, us, ci, ss);
+ }
+
+ /**
+ * Publicly available copy constructor
+ *
+ * @param the font to copy
+ */
+ protected WritableFontRecord(Font f)
+ {
+ super(f);
+ }
+
+
+ /**
+ * Sets the point size for this font, if the font hasn't been initialized
+ *
+ * @param pointSize the point size
+ * @exception WriteException, if this font is already in use elsewhere
+ */
+ protected void setPointSize(int pointSize) throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+
+ super.setFontPointSize(pointSize);
+ }
+
+ /**
+ * Sets the bold style for this font, if the font hasn't been initialized
+ *
+ * @param boldStyle the bold style
+ * @exception WriteException, if this font is already in use elsewhere
+ */
+ protected void setBoldStyle(int boldStyle) throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+
+ super.setFontBoldStyle(boldStyle);
+ }
+
+ /**
+ * Sets the italic indicator for this font, if the font hasn't been
+ * initialized
+ *
+ * @param italic the italic flag
+ * @exception WriteException, if this font is already in use elsewhere
+ */
+ protected void setItalic(boolean italic) throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+
+ super.setFontItalic(italic);
+ }
+
+ /**
+ * Sets the underline style for this font, if the font hasn't been
+ * initialized
+ *
+ * @param us the underline style
+ * @exception WriteException, if this font is already in use elsewhere
+ */
+ protected void setUnderlineStyle(int us) throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+
+ super.setFontUnderlineStyle(us);
+ }
+
+ /**
+ * Sets the colour for this font, if the font hasn't been
+ * initialized
+ *
+ * @param colour the colour
+ * @exception WriteException, if this font is already in use elsewhere
+ */
+ protected void setColour(int colour) throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+
+ super.setFontColour(colour);
+ }
+
+ /**
+ * Sets the script style (eg. superscript, subscript) for this font,
+ * if the font hasn't been initialized
+ *
+ * @param scriptStyle the colour
+ * @exception WriteException, if this font is already in use elsewhere
+ */
+ protected void setScriptStyle(int scriptStyle) throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+
+ super.setFontScriptStyle(scriptStyle);
+ }
+
+ /**
+ * Sets the struck out flag
+ *
+ * @param so TRUE if the font is struck out, false otherwise
+ * @exception WriteException, if this font is already in use elsewhere
+ */
+ protected void setStruckout(boolean os) throws WriteException
+ {
+ if (isInitialized())
+ {
+ throw new JxlWriteException(JxlWriteException.formatInitialized);
+ }
+ super.setFontStruckout(os);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/WritableFonts.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/WritableFonts.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/WritableFonts.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,51 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.biff.Fonts;
+import jxl.write.WritableFont;
+
+/**
+ * A container for the list of fonts used in this workbook The writable
+ * subclass instantiates the predetermined list of fonts available to
+ * users of the writable API
+ */
+public class WritableFonts extends Fonts
+{
+ /**
+ * Constructor. Creates the predetermined list of fonts
+ */
+ public WritableFonts(WritableWorkbookImpl w)
+ {
+ super();
+
+ addFont(w.getStyles().getArial10Pt());
+
+ // Create the default fonts
+ WritableFont f = new WritableFont(WritableFont.ARIAL);
+ addFont(f);
+
+ f = new WritableFont(WritableFont.ARIAL);
+ addFont(f);
+
+ f = new WritableFont(WritableFont.ARIAL);
+ addFont(f);
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/WritableFormattingRecords.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/WritableFormattingRecords.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/WritableFormattingRecords.java 17 Aug 2012 14:51:08 -0000 1.1
@@ -0,0 +1,231 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import common.Assert;
+
+import jxl.biff.Fonts;
+import jxl.biff.FormattingRecords;
+import jxl.biff.NumFormatRecordsException;
+import jxl.write.NumberFormats;
+import jxl.write.WritableCellFormat;
+
+
+/**
+ * Handles the Format and XF record indexing. The writable subclass
+ * instantiates the predetermined list of XF records and formats
+ * present in every Excel Workbook
+ */
+public class WritableFormattingRecords extends FormattingRecords
+{
+ /**
+ * The statically defined normal style
+ */
+ public static WritableCellFormat normalStyle;
+
+ /**
+ * Constructor. Instantiates the prerequisite list of formats and
+ * styles required by all Excel workbooks
+ *
+ * @param f the list of Fonts
+ * @param styles the list of style clones
+ */
+ public WritableFormattingRecords(Fonts f, Styles styles)
+ {
+ super(f);
+
+ try
+ {
+ // Hard code all the styles
+ StyleXFRecord sxf = new StyleXFRecord
+ (styles.getArial10Pt(),NumberFormats.DEFAULT);
+ sxf.setLocked(true);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(getFonts().getFont(1),NumberFormats.DEFAULT);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf400);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(getFonts().getFont(1),NumberFormats.DEFAULT);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf400);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(getFonts().getFont(1),NumberFormats.DEFAULT);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf400);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(getFonts().getFont(2),NumberFormats.DEFAULT);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf400);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(getFonts().getFont(3),NumberFormats.DEFAULT);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf400);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(styles.getArial10Pt(),
+ NumberFormats.DEFAULT);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf400);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(styles.getArial10Pt(),
+ NumberFormats.DEFAULT);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf400);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(styles.getArial10Pt(),
+ NumberFormats.DEFAULT);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf400);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(styles.getArial10Pt(),
+ NumberFormats.DEFAULT);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf400);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(styles.getArial10Pt(),
+ NumberFormats.DEFAULT);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf400);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(styles.getArial10Pt(),
+ NumberFormats.DEFAULT);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf400);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(styles.getArial10Pt(),
+ NumberFormats.DEFAULT);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf400);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(styles.getArial10Pt(),
+ NumberFormats.DEFAULT);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf400);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(styles.getArial10Pt(),
+ NumberFormats.DEFAULT);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf400);
+ addStyle(sxf);
+
+ // That's the end of the built ins. Write the normal style
+ // cell XF here
+ addStyle(styles.getNormalStyle());
+
+ // Continue with "user defined" styles
+ sxf = new StyleXFRecord(getFonts().getFont(1),
+ NumberFormats.FORMAT7);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf800);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(getFonts().getFont(1),
+ NumberFormats.FORMAT5);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf800);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(getFonts().getFont(1),
+ NumberFormats.FORMAT8);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf800);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(getFonts().getFont(1),
+ NumberFormats.FORMAT6);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf800);
+ addStyle(sxf);
+
+ sxf = new StyleXFRecord(getFonts().getFont(1),
+ NumberFormats.PERCENT_INTEGER);
+ sxf.setLocked(true);
+ sxf.setCellOptions(0xf800);
+ addStyle(sxf);
+
+ // Hard code in the pre-defined number formats for now
+ /*
+ FormatRecord fr = new FormatRecord
+ ("\"$\"#,##0_);\\(\"$\"#,##0\\)",5);
+ addFormat(fr);
+
+ fr = new FormatRecord
+ ("\"$\"#,##0_);[Red]\\(\"$\"#,##0\\)", 6);
+ addFormat(fr);
+
+ fr = new FormatRecord
+ ("\"$\"#,##0.00_);\\(\"$\"#,##0.00\\)", 7);
+ addFormat(fr);
+
+ fr = new FormatRecord
+ ("\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)", 8);
+ addFormat(fr);
+
+ fr = new FormatRecord
+ ("_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)",
+ 0x2a);
+ // outputFile.write(fr);
+
+ fr = new FormatRecord
+ ("_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)",
+ 0x2e);
+ // outputFile.write(fr);
+
+ fr = new FormatRecord
+ ("_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)",
+ 0x2c);
+ // outputFile.write(fr);
+
+ fr = new FormatRecord
+ ("_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)",
+ 0x2b);
+ // outputFile.write(fr);
+ */
+ }
+ catch (NumFormatRecordsException e)
+ {
+ // This should not happen yet, since we are just creating the file.
+ // Bomb out
+ Assert.verify(false, e.getMessage());
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/WritableSheetCopier.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/WritableSheetCopier.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/WritableSheetCopier.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,597 @@
+/*********************************************************************
+*
+* Copyright (C) 2006 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.TreeSet;
+import java.util.Iterator;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.BooleanCell;
+import jxl.Cell;
+import jxl.CellType;
+import jxl.CellView;
+import jxl.DateCell;
+import jxl.HeaderFooter;
+import jxl.Hyperlink;
+import jxl.Image;
+import jxl.LabelCell;
+import jxl.NumberCell;
+import jxl.Range;
+import jxl.Sheet;
+import jxl.SheetSettings;
+import jxl.WorkbookSettings;
+import jxl.biff.AutoFilter;
+import jxl.biff.CellReferenceHelper;
+import jxl.biff.ConditionalFormat;
+import jxl.biff.DataValidation;
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.IndexMapping;
+import jxl.biff.NumFormatRecordsException;
+import jxl.biff.SheetRangeImpl;
+import jxl.biff.WorkspaceInformationRecord;
+import jxl.biff.XFRecord;
+import jxl.biff.drawing.Chart;
+import jxl.biff.drawing.ComboBox;
+import jxl.biff.drawing.Drawing;
+import jxl.biff.drawing.DrawingGroupObject;
+import jxl.format.CellFormat;
+import jxl.biff.formula.FormulaException;
+import jxl.read.biff.SheetImpl;
+import jxl.read.biff.NameRecord;
+import jxl.read.biff.WorkbookParser;
+import jxl.write.Blank;
+import jxl.write.Boolean;
+import jxl.write.DateTime;
+import jxl.write.Formula;
+import jxl.write.Label;
+import jxl.write.Number;
+import jxl.write.WritableCell;
+import jxl.write.WritableCellFormat;
+import jxl.write.WritableFont;
+import jxl.write.WritableHyperlink;
+import jxl.write.WritableImage;
+import jxl.write.WritableSheet;
+import jxl.write.WritableWorkbook;
+import jxl.write.WriteException;
+
+/**
+ * A transient utility object used to copy sheets. This
+ * functionality has been farmed out to a different class
+ * in order to reduce the bloat of the WritableSheetImpl
+ */
+class WritableSheetCopier
+{
+ private static Logger logger = Logger.getLogger(SheetCopier.class);
+
+ private WritableSheetImpl fromSheet;
+ private WritableSheetImpl toSheet;
+ private WorkbookSettings workbookSettings;
+
+ // Objects used by the sheet
+ private TreeSet fromColumnFormats;
+ private TreeSet toColumnFormats;
+ private MergedCells fromMergedCells;
+ private MergedCells toMergedCells;
+ private RowRecord[] fromRows;
+ private ArrayList fromRowBreaks;
+ private ArrayList fromColumnBreaks;
+ private ArrayList toRowBreaks;
+ private ArrayList toColumnBreaks;
+ private DataValidation fromDataValidation;
+ private DataValidation toDataValidation;
+ private SheetWriter sheetWriter;
+ private ArrayList fromDrawings;
+ private ArrayList toDrawings;
+ private ArrayList toImages;
+ private WorkspaceInformationRecord fromWorkspaceOptions;
+ private PLSRecord fromPLSRecord;
+ private PLSRecord toPLSRecord;
+ private ButtonPropertySetRecord fromButtonPropertySet;
+ private ButtonPropertySetRecord toButtonPropertySet;
+ private ArrayList fromHyperlinks;
+ private ArrayList toHyperlinks;
+ private int numRows;
+ private int maxRowOutlineLevel;
+ private int maxColumnOutlineLevel;
+
+
+ private boolean chartOnly;
+ private FormattingRecords formatRecords;
+
+
+
+ // Objects used to maintain state during the copy process
+ private HashMap xfRecords;
+ private HashMap fonts;
+ private HashMap formats;
+
+ public WritableSheetCopier(WritableSheet f, WritableSheet t)
+ {
+ fromSheet = (WritableSheetImpl) f;
+ toSheet = (WritableSheetImpl) t;
+ workbookSettings = toSheet.getWorkbook().getSettings();
+ chartOnly = false;
+ }
+
+ void setColumnFormats(TreeSet fcf, TreeSet tcf)
+ {
+ fromColumnFormats = fcf;
+ toColumnFormats = tcf;
+ }
+
+ void setMergedCells(MergedCells fmc, MergedCells tmc)
+ {
+ fromMergedCells = fmc;
+ toMergedCells = tmc;
+ }
+
+ void setRows(RowRecord[] r)
+ {
+ fromRows = r;
+ }
+
+ void setRowBreaks(ArrayList frb, ArrayList trb)
+ {
+ fromRowBreaks = frb;
+ toRowBreaks = trb;
+ }
+
+ void setColumnBreaks(ArrayList fcb, ArrayList tcb)
+ {
+ fromColumnBreaks = fcb;
+ toColumnBreaks = tcb;
+ }
+
+ void setDrawings(ArrayList fd, ArrayList td, ArrayList ti)
+ {
+ fromDrawings = fd;
+ toDrawings = td;
+ toImages = ti;
+ }
+
+ void setHyperlinks(ArrayList fh, ArrayList th)
+ {
+ fromHyperlinks = fh;
+ toHyperlinks = th;
+ }
+
+ void setWorkspaceOptions(WorkspaceInformationRecord wir)
+ {
+ fromWorkspaceOptions = wir;
+ }
+
+ void setDataValidation(DataValidation dv)
+ {
+ fromDataValidation = dv;
+ }
+
+ void setPLSRecord(PLSRecord plsr)
+ {
+ fromPLSRecord = plsr;
+ }
+
+ void setButtonPropertySetRecord(ButtonPropertySetRecord bpsr)
+ {
+ fromButtonPropertySet = bpsr;
+ }
+
+ void setSheetWriter(SheetWriter sw)
+ {
+ sheetWriter = sw;
+ }
+
+
+ DataValidation getDataValidation()
+ {
+ return toDataValidation;
+ }
+
+ PLSRecord getPLSRecord()
+ {
+ return toPLSRecord;
+ }
+
+ boolean isChartOnly()
+ {
+ return chartOnly;
+ }
+
+ ButtonPropertySetRecord getButtonPropertySet()
+ {
+ return toButtonPropertySet;
+ }
+
+ /**
+ * Copies a sheet from a read-only version to the writable version.
+ * Performs shallow copies
+ */
+ public void copySheet()
+ {
+ shallowCopyCells();
+
+ // Copy the column formats
+ Iterator cfit = fromColumnFormats.iterator();
+ while (cfit.hasNext())
+ {
+ ColumnInfoRecord cv = new ColumnInfoRecord
+ ((ColumnInfoRecord) cfit.next());
+ toColumnFormats.add(cv);
+ }
+
+ // Copy the merged cells
+ Range[] merged = fromMergedCells.getMergedCells();
+
+ for (int i = 0; i < merged.length; i++)
+ {
+ toMergedCells.add(new SheetRangeImpl((SheetRangeImpl)merged[i],
+ toSheet));
+ }
+
+ try
+ {
+ RowRecord row = null;
+ RowRecord newRow = null;
+ for (int i = 0; i < fromRows.length ; i++)
+ {
+ row = fromRows[i];
+
+ if (row != null &&
+ (!row.isDefaultHeight() ||
+ row.isCollapsed()))
+ {
+ newRow = toSheet.getRowRecord(i);
+ newRow.setRowDetails(row.getRowHeight(),
+ row.matchesDefaultFontHeight(),
+ row.isCollapsed(),
+ row.getOutlineLevel(),
+ row.getGroupStart(),
+ row.getStyle());
+ }
+ }
+ }
+ catch (RowsExceededException e)
+ {
+ // Handle the rows exceeded exception - this cannot occur since
+ // the sheet we are copying from will have a valid number of rows
+ Assert.verify(false);
+ }
+
+ // Copy the horizontal page breaks
+ toRowBreaks = new ArrayList(fromRowBreaks);
+
+ // Copy the vertical page breaks
+ toColumnBreaks = new ArrayList(fromColumnBreaks);
+
+ // Copy the data validations
+ if (fromDataValidation != null)
+ {
+ toDataValidation = new DataValidation
+ (fromDataValidation,
+ toSheet.getWorkbook(),
+ toSheet.getWorkbook(),
+ toSheet.getWorkbook().getSettings());
+ }
+
+ // Copy the charts
+ sheetWriter.setCharts(fromSheet.getCharts());
+
+ // Copy the drawings
+ for (Iterator i = fromDrawings.iterator(); i.hasNext(); )
+ {
+ Object o = i.next();
+ if (o instanceof jxl.biff.drawing.Drawing)
+ {
+ WritableImage wi = new WritableImage
+ ((jxl.biff.drawing.Drawing) o,
+ toSheet.getWorkbook().getDrawingGroup());
+ toDrawings.add(wi);
+ toImages.add(wi);
+ }
+
+ // Not necessary to copy the comments, as they will be handled by
+ // the deep copy of the individual cells
+ }
+
+ // Copy the workspace options
+ sheetWriter.setWorkspaceOptions(fromWorkspaceOptions);
+
+ // Copy the environment specific print record
+ if (fromPLSRecord != null)
+ {
+ toPLSRecord = new PLSRecord(fromPLSRecord);
+ }
+
+ // Copy the button property set
+ if (fromButtonPropertySet != null)
+ {
+ toButtonPropertySet = new ButtonPropertySetRecord(fromButtonPropertySet);
+ }
+
+ // Copy the hyperlinks
+ for (Iterator i = fromHyperlinks.iterator(); i.hasNext();)
+ {
+ WritableHyperlink hr = new WritableHyperlink
+ ((WritableHyperlink) i.next(), toSheet);
+ toHyperlinks.add(hr);
+ }
+ }
+
+ /**
+ * Performs a shallow copy of the specified cell
+ */
+ private WritableCell shallowCopyCell(Cell cell)
+ {
+ CellType ct = cell.getType();
+ WritableCell newCell = null;
+
+ if (ct == CellType.LABEL)
+ {
+ newCell = new Label((LabelCell) cell);
+ }
+ else if (ct == CellType.NUMBER)
+ {
+ newCell = new Number((NumberCell) cell);
+ }
+ else if (ct == CellType.DATE)
+ {
+ newCell = new DateTime((DateCell) cell);
+ }
+ else if (ct == CellType.BOOLEAN)
+ {
+ newCell = new Boolean((BooleanCell) cell);
+ }
+ else if (ct == CellType.NUMBER_FORMULA)
+ {
+ newCell = new ReadNumberFormulaRecord((FormulaData) cell);
+ }
+ else if (ct == CellType.STRING_FORMULA)
+ {
+ newCell = new ReadStringFormulaRecord((FormulaData) cell);
+ }
+ else if( ct == CellType.BOOLEAN_FORMULA)
+ {
+ newCell = new ReadBooleanFormulaRecord((FormulaData) cell);
+ }
+ else if (ct == CellType.DATE_FORMULA)
+ {
+ newCell = new ReadDateFormulaRecord((FormulaData) cell);
+ }
+ else if(ct == CellType.FORMULA_ERROR)
+ {
+ newCell = new ReadErrorFormulaRecord((FormulaData) cell);
+ }
+ else if (ct == CellType.EMPTY)
+ {
+ if (cell.getCellFormat() != null)
+ {
+ // It is a blank cell, rather than an empty cell, so
+ // it may have formatting information, so
+ // it must be copied
+ newCell = new Blank(cell);
+ }
+ }
+
+ return newCell;
+ }
+
+ /**
+ * Performs a deep copy of the specified cell, handling the cell format
+ *
+ * @param cell the cell to copy
+ */
+ private WritableCell deepCopyCell(Cell cell)
+ {
+ WritableCell c = shallowCopyCell(cell);
+
+ if (c == null)
+ {
+ return c;
+ }
+
+ if (c instanceof ReadFormulaRecord)
+ {
+ ReadFormulaRecord rfr = (ReadFormulaRecord) c;
+ boolean crossSheetReference = !rfr.handleImportedCellReferences
+ (fromSheet.getWorkbook(),
+ fromSheet.getWorkbook(),
+ workbookSettings);
+
+ if (crossSheetReference)
+ {
+ try
+ {
+ logger.warn("Formula " + rfr.getFormula() +
+ " in cell " +
+ CellReferenceHelper.getCellReference(cell.getColumn(),
+ cell.getRow()) +
+ " cannot be imported because it references another " +
+ " sheet from the source workbook");
+ }
+ catch (FormulaException e)
+ {
+ logger.warn("Formula in cell " +
+ CellReferenceHelper.getCellReference(cell.getColumn(),
+ cell.getRow()) +
+ " cannot be imported: " + e.getMessage());
+ }
+
+ // Create a new error formula and add it instead
+ c = new Formula(cell.getColumn(), cell.getRow(), "\"ERROR\"");
+ }
+ }
+
+ // Copy the cell format
+ CellFormat cf = c.getCellFormat();
+ int index = ( (XFRecord) cf).getXFIndex();
+ WritableCellFormat wcf = (WritableCellFormat)
+ xfRecords.get(new Integer(index));
+
+ if (wcf == null)
+ {
+ wcf = copyCellFormat(cf);
+ }
+
+ c.setCellFormat(wcf);
+
+ return c;
+ }
+
+ /**
+ * Perform a shallow copy of the cells from the specified sheet into this one
+ */
+ void shallowCopyCells()
+ {
+ // Copy the cells
+ int cells = fromSheet.getRows();
+ Cell[] row = null;
+ Cell cell = null;
+ for (int i = 0; i < cells; i++)
+ {
+ row = fromSheet.getRow(i);
+
+ for (int j = 0; j < row.length; j++)
+ {
+ cell = row[j];
+ WritableCell c = shallowCopyCell(cell);
+
+ // Encase the calls to addCell in a try-catch block
+ // These should not generate any errors, because we are
+ // copying from an existing spreadsheet. In the event of
+ // errors, catch the exception and then bomb out with an
+ // assertion
+ try
+ {
+ if (c != null)
+ {
+ toSheet.addCell(c);
+ }
+ }
+ catch (WriteException e)
+ {
+ Assert.verify(false);
+ }
+ }
+ }
+ numRows = toSheet.getRows();
+ }
+
+ /**
+ * Perform a deep copy of the cells from the specified sheet into this one
+ */
+ void deepCopyCells()
+ {
+ // Copy the cells
+ int cells = fromSheet.getRows();
+ Cell[] row = null;
+ Cell cell = null;
+ for (int i = 0; i < cells; i++)
+ {
+ row = fromSheet.getRow(i);
+
+ for (int j = 0; j < row.length; j++)
+ {
+ cell = row[j];
+ WritableCell c = deepCopyCell(cell);
+
+ // Encase the calls to addCell in a try-catch block
+ // These should not generate any errors, because we are
+ // copying from an existing spreadsheet. In the event of
+ // errors, catch the exception and then bomb out with an
+ // assertion
+ try
+ {
+ if (c != null)
+ {
+ toSheet.addCell(c);
+ }
+ }
+ catch (WriteException e)
+ {
+ Assert.verify(false);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns an initialized copy of the cell format
+ *
+ * @param cf the cell format to copy
+ * @return a deep copy of the cell format
+ */
+ private WritableCellFormat copyCellFormat(CellFormat cf)
+ {
+ try
+ {
+ // just do a deep copy of the cell format for now. This will create
+ // a copy of the format and font also - in the future this may
+ // need to be sorted out
+ XFRecord xfr = (XFRecord) cf;
+ WritableCellFormat f = new WritableCellFormat(xfr);
+ formatRecords.addStyle(f);
+
+ // Maintain the local list of formats
+ int xfIndex = xfr.getXFIndex();
+ xfRecords.put(new Integer(xfIndex), f);
+
+ int fontIndex = xfr.getFontIndex();
+ fonts.put(new Integer(fontIndex), new Integer(f.getFontIndex()));
+
+ int formatIndex = xfr.getFormatRecord();
+ formats.put(new Integer(formatIndex), new Integer(f.getFormatRecord()));
+
+ return f;
+ }
+ catch (NumFormatRecordsException e)
+ {
+ logger.warn("Maximum number of format records exceeded. Using " +
+ "default format.");
+
+ return WritableWorkbook.NORMAL_STYLE;
+ }
+ }
+
+
+ /**
+ * Accessor for the maximum column outline level
+ *
+ * @return the maximum column outline level, or 0 if no outlines/groups
+ */
+ public int getMaxColumnOutlineLevel()
+ {
+ return maxColumnOutlineLevel;
+ }
+
+ /**
+ * Accessor for the maximum row outline level
+ *
+ * @return the maximum row outline level, or 0 if no outlines/groups
+ */
+ public int getMaxRowOutlineLevel()
+ {
+ return maxRowOutlineLevel;
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/WritableSheetImpl.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/WritableSheetImpl.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/WritableSheetImpl.java 17 Aug 2012 14:51:12 -0000 1.1
@@ -0,0 +1,2649 @@
+/**********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.BooleanCell;
+import jxl.Cell;
+import jxl.CellFeatures;
+import jxl.CellType;
+import jxl.CellView;
+import jxl.DateCell;
+import jxl.HeaderFooter;
+import jxl.Hyperlink;
+import jxl.Image;
+import jxl.LabelCell;
+import jxl.NumberCell;
+import jxl.Range;
+import jxl.Sheet;
+import jxl.SheetSettings;
+import jxl.WorkbookSettings;
+import jxl.biff.AutoFilter;
+import jxl.biff.BuiltInName;
+import jxl.biff.CellFinder;
+import jxl.biff.CellReferenceHelper;
+import jxl.biff.ConditionalFormat;
+import jxl.biff.DataValidation;
+import jxl.biff.EmptyCell;
+import jxl.biff.FormattingRecords;
+import jxl.biff.FormulaData;
+import jxl.biff.IndexMapping;
+import jxl.biff.NumFormatRecordsException;
+import jxl.biff.SheetRangeImpl;
+import jxl.biff.WorkspaceInformationRecord;
+import jxl.biff.XFRecord;
+import jxl.biff.drawing.Chart;
+import jxl.biff.drawing.ComboBox;
+import jxl.biff.drawing.Drawing;
+import jxl.biff.drawing.DrawingGroupObject;
+import jxl.format.CellFormat;
+import jxl.format.Font;
+import jxl.format.PageOrientation;
+import jxl.format.PaperSize;
+import jxl.write.Blank;
+import jxl.write.Boolean;
+import jxl.write.DateTime;
+import jxl.write.Label;
+import jxl.write.Number;
+import jxl.write.WritableCell;
+import jxl.write.WritableCellFormat;
+import jxl.write.WritableFont;
+import jxl.write.WritableHyperlink;
+import jxl.write.WritableImage;
+import jxl.write.WritableSheet;
+import jxl.write.WritableWorkbook;
+import jxl.write.WriteException;
+
+/**
+ * A writable sheet. This class contains implementation of all the
+ * writable sheet methods which may be invoke by the API
+ */
+class WritableSheetImpl implements WritableSheet
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(WritableSheetImpl.class);
+
+ /**
+ * The name of this sheet
+ */
+ private String name;
+ /**
+ * A handle to the output file which the binary data is written to
+ */
+ private File outputFile;
+ /**
+ * The rows within this sheet
+ */
+ private RowRecord[] rows;
+ /**
+ * A handle to workbook format records
+ */
+ private FormattingRecords formatRecords;
+ /**
+ * A handle to the shared strings used by this workbook
+ */
+ private SharedStrings sharedStrings;
+
+ /**
+ * The list of non-default column formats
+ */
+ private TreeSet columnFormats;
+
+ /**
+ * The list of autosized columns
+ */
+ private TreeSet autosizedColumns;
+
+ /**
+ * The list of hyperlinks
+ */
+ private ArrayList hyperlinks;
+
+ /**
+ * The list of merged ranged
+ */
+ private MergedCells mergedCells;
+
+ /**
+ * A number of rows. This is a count of the maximum row number + 1
+ */
+ private int numRows;
+
+ /**
+ * The number of columns. This is a count of the maximum column number + 1
+ */
+ private int numColumns;
+
+ /**
+ * The environment specific print record, copied from the read spreadsheet
+ */
+ private PLSRecord plsRecord;
+
+ /**
+ * The buttons property set
+ */
+ private ButtonPropertySetRecord buttonPropertySet;
+
+ /**
+ * A flag indicating that this sheet is a chart only
+ */
+ private boolean chartOnly;
+
+ /**
+ * The data validations on this page
+ */
+ private DataValidation dataValidation;
+
+ /**
+ * Array of row page breaks
+ */
+ private ArrayList rowBreaks;
+
+ /**
+ * Array of column page breaks
+ */
+ private ArrayList columnBreaks;
+
+ /**
+ * The drawings on this sheet
+ */
+ private ArrayList drawings;
+
+ /**
+ * The images on this sheet. This is a subset of the drawings list
+ */
+ private ArrayList images;
+
+ /**
+ * The conditional formats on this sheet
+ */
+ private ArrayList conditionalFormats;
+
+ /**
+ * The autofilter
+ */
+ private AutoFilter autoFilter;
+
+ /**
+ * The writable cells on this sheet which may have validation added
+ * to them
+ */
+ private ArrayList validatedCells;
+
+ /**
+ * The combo box object used for list validations on this sheet
+ */
+ private ComboBox comboBox;
+
+ /**
+ * Drawings modified flag. Set to true if the drawings list has
+ * been modified
+ */
+ private boolean drawingsModified;
+
+ /**
+ * The maximum row outline level
+ */
+ private int maxRowOutlineLevel;
+
+ /**
+ * The maximum column outline level
+ */
+ private int maxColumnOutlineLevel;
+
+ /**
+ * The settings for this sheet
+ */
+ private SheetSettings settings;
+
+ /**
+ * The sheet writer engine
+ */
+ private SheetWriter sheetWriter;
+
+ /**
+ * The settings for the workbook
+ */
+ private WorkbookSettings workbookSettings;
+
+ /**
+ * The workbook
+ */
+ private WritableWorkbookImpl workbook;
+
+ /**
+ * The amount by which to grow the rows array
+ */
+ private final static int rowGrowSize = 10;
+
+ /**
+ * The maximum number of rows excel allows in a worksheet
+ */
+ private final static int numRowsPerSheet = 65536;
+
+ /**
+ * The maximum number of characters permissible for a sheet name
+ */
+ private final static int maxSheetNameLength = 31;
+
+ /**
+ * The illegal characters for a sheet name
+ */
+ private final static char[] illegalSheetNameCharacters =
+ new char[] {'*', ':', '?', '\\'};
+
+ /**
+ * The supported file types
+ */
+ private static final String[] imageTypes = new String[] {"png"};
+
+ /**
+ * The comparator for column info record
+ */
+ private static class ColumnInfoComparator implements Comparator
+ {
+ /**
+ * Equals method
+ *
+ * @param o the object to compare
+ * @return TRUE if equal, FALSE otherwise
+ */
+ public boolean equals(Object o)
+ {
+ return o == this;
+ }
+
+ /**
+ * Comparison function for to ColumnInfoRecords
+ *
+ * @param o2 first object to compare
+ * @param o1 second object to compare
+ * @return the result of the comparison
+ */
+ public int compare(Object o1, Object o2)
+ {
+ if (o1 == o2)
+ {
+ return 0;
+ }
+
+ Assert.verify(o1 instanceof ColumnInfoRecord);
+ Assert.verify(o2 instanceof ColumnInfoRecord);
+
+ ColumnInfoRecord ci1 = (ColumnInfoRecord) o1;
+ ColumnInfoRecord ci2 = (ColumnInfoRecord) o2;
+
+ return ci1.getColumn() - ci2.getColumn();
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param fr the formatting records used by the workbook
+ * @param of the output file to write the binary data
+ * @param f the fonts used by the workbook
+ * @param n the name of this sheet
+ * @param ss the shared strings used by the workbook
+ * @param ws the workbook settings
+ */
+ public WritableSheetImpl(String n,
+ File of,
+ FormattingRecords fr,
+ SharedStrings ss,
+ WorkbookSettings ws,
+ WritableWorkbookImpl ww)
+ {
+ name = validateName(n);
+ outputFile = of;
+ rows = new RowRecord[0];
+ numRows = 0;
+ numColumns = 0;
+ chartOnly = false;
+ workbook = ww;
+
+ formatRecords = fr;
+ sharedStrings = ss;
+ workbookSettings = ws;
+ drawingsModified = false;
+ columnFormats = new TreeSet(new ColumnInfoComparator());
+ autosizedColumns = new TreeSet();
+ hyperlinks = new ArrayList();
+ mergedCells = new MergedCells(this);
+ rowBreaks = new ArrayList();
+ columnBreaks = new ArrayList();
+ drawings = new ArrayList();
+ images = new ArrayList();
+ conditionalFormats = new ArrayList();
+ validatedCells = new ArrayList();
+ settings = new SheetSettings(this);
+
+
+ sheetWriter = new SheetWriter(outputFile,
+ this,
+ workbookSettings);
+ }
+
+ /**
+ * Returns the cell for the specified location eg. "A4", using the
+ * CellReferenceHelper
+ *
+ * @param loc the cell reference
+ * @return the cell at the specified co-ordinates
+ */
+ public Cell getCell(String loc)
+ {
+ return getCell(CellReferenceHelper.getColumn(loc),
+ CellReferenceHelper.getRow(loc));
+ }
+
+ /**
+ * Returns the cell specified at this row and at this column
+ *
+ * @param column the column number
+ * @param row the row number
+ * @return the cell at the specified co-ordinates
+ */
+ public Cell getCell(int column, int row)
+ {
+ return getWritableCell(column, row);
+ }
+
+ /**
+ * Returns the cell for the specified location eg. "A4". Note that this
+ * method is identical to calling getCell(CellReferenceHelper.getColumn(loc),
+ * CellReferenceHelper.getRow(loc)) and its implicit performance
+ * overhead for string parsing. As such,this method should therefore
+ * be used sparingly
+ *
+ * @param loc the cell reference
+ * @return the cell at the specified co-ordinates
+ */
+ public WritableCell getWritableCell(String loc)
+ {
+ return getWritableCell(CellReferenceHelper.getColumn(loc),
+ CellReferenceHelper.getRow(loc));
+ }
+
+ /**
+ * Returns the cell specified at this row and at this column
+ *
+ * @param column the column number
+ * @param row the row number
+ * @return the cell at the specified co-ordinates
+ */
+ public WritableCell getWritableCell(int column, int row)
+ {
+ WritableCell c = null;
+
+ if (row < rows.length && rows[row] != null)
+ {
+ c = rows[row].getCell(column);
+ }
+
+ if (c == null)
+ {
+ c = new EmptyCell(column, row);
+ }
+
+ return c;
+ }
+
+ /**
+ * Returns the number of rows in this sheet
+ *
+ * @return the number of rows in this sheet
+ */
+ public int getRows()
+ {
+ return numRows;
+ }
+
+ /**
+ * Returns the number of columns in this sheet
+ *
+ * @return the number of columns in this sheet
+ */
+ public int getColumns()
+ {
+ return numColumns;
+ }
+
+ /**
+ * Gets the cell whose contents match the string passed in.
+ * If no match is found, then null is returned. The search is performed
+ * on a row by row basis, so the lower the row number, the more
+ * efficiently the algorithm will perform
+ *
+ * @param contents the string to match
+ * @return the Cell whose contents match the paramter, null if not found
+ */
+ public Cell findCell(String contents)
+ {
+ CellFinder cellFinder = new CellFinder(this);
+ return cellFinder.findCell(contents);
+ }
+
+ /**
+ * Gets the cell whose contents match the string passed in.
+ * If no match is found, then null is returned. The search is performed
+ * on a row by row basis, so the lower the row number, the more
+ * efficiently the algorithm will perform
+ *
+ * @param contents the string to match
+ * @param firstCol the first column within the range
+ * @param firstRow the first row of the range
+ * @param lastCol the last column within the range
+ * @param lastRow the last row within the range
+ * @param reverse indicates whether to perform a reverse search or not
+ * @return the Cell whose contents match the parameter, null if not found
+ */
+ public Cell findCell(String contents,
+ int firstCol,
+ int firstRow,
+ int lastCol,
+ int lastRow,
+ boolean reverse)
+ {
+ CellFinder cellFinder = new CellFinder(this);
+ return cellFinder.findCell(contents,
+ firstCol,
+ firstRow,
+ lastCol,
+ lastRow,
+ reverse);
+ }
+
+ /**
+ * Gets the cell whose contents match the regular expressionstring passed in.
+ * If no match is found, then null is returned. The search is performed
+ * on a row by row basis, so the lower the row number, the more
+ * efficiently the algorithm will perform
+ *
+ * @param pattern the regular expression string to match
+ * @param firstCol the first column within the range
+ * @param firstRow the first row of the range
+ * @param lastRow the last row within the range
+ * @param lastCol the last column within the ranage
+ * @param reverse indicates whether to perform a reverse search or not
+ * @return the Cell whose contents match the parameter, null if not found
+ */
+ public Cell findCell(Pattern pattern,
+ int firstCol,
+ int firstRow,
+ int lastCol,
+ int lastRow,
+ boolean reverse)
+ {
+ CellFinder cellFinder = new CellFinder(this);
+ return cellFinder.findCell(pattern,
+ firstCol,
+ firstRow,
+ lastCol,
+ lastRow,
+ reverse);
+ }
+
+ /**
+ * Gets the cell whose contents match the string passed in.
+ * If no match is found, then null is returned. The search is performed
+ * on a row by row basis, so the lower the row number, the more
+ * efficiently the algorithm will perform. This method differs
+ * from the findCell methods in that only cells with labels are
+ * queried - all numerical cells are ignored. This should therefore
+ * improve performance.
+ *
+ * @param contents the string to match
+ * @return the Cell whose contents match the paramter, null if not found
+ */
+ public LabelCell findLabelCell(String contents)
+ {
+ CellFinder cellFinder = new CellFinder(this);
+ return cellFinder.findLabelCell(contents);
+ }
+
+ /**
+ * Gets all the cells on the specified row
+ *
+ * @param row the rows whose cells are to be returned
+ * @return the cells on the given row
+ */
+ public Cell[] getRow(int row)
+ {
+ // Find the last non-null cell
+ boolean found = false;
+ int col = numColumns - 1;
+ while (col >= 0 && !found)
+ {
+ if (getCell(col, row).getType() != CellType.EMPTY)
+ {
+ found = true;
+ }
+ else
+ {
+ col--;
+ }
+ }
+
+ // Only create entries for non-empty cells
+ Cell[] cells = new Cell[col+1];
+
+ for (int i = 0; i <= col; i++)
+ {
+ cells[i] = getCell(i, row);
+ }
+ return cells;
+ }
+
+ /**
+ * Gets all the cells on the specified column
+ *
+ * @param col the column whose cells are to be returned
+ * @return the cells on the specified column
+ */
+ public Cell[] getColumn(int col)
+ {
+ // Find the last non-null cell
+ boolean found = false;
+ int row = numRows - 1;
+
+ while (row >= 0 && !found)
+ {
+ if (getCell(col, row).getType() != CellType.EMPTY)
+ {
+ found = true;
+ }
+ else
+ {
+ row--;
+ }
+ }
+
+ // Only create entries for non-empty cells
+ Cell[] cells = new Cell[row+1];
+
+ for (int i = 0; i <= row; i++)
+ {
+ cells[i] = getCell(col, i);
+ }
+ return cells;
+ }
+
+ /**
+ * Gets the name of this sheet
+ *
+ * @return the name of the sheet
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Inserts a blank row into this spreadsheet. If the row is out of range
+ * of the rows in the sheet, then no action is taken
+ *
+ * @param row the row to insert
+ */
+ public void insertRow(int row)
+ {
+ if (row < 0 || row >= numRows)
+ {
+ return;
+ }
+
+ // Create a new array to hold the new rows. Grow it if need be
+ RowRecord[] oldRows = rows;
+
+ if (numRows == rows.length)
+ {
+ rows = new RowRecord[oldRows.length + rowGrowSize];
+ }
+ else
+ {
+ rows = new RowRecord[oldRows.length];
+ }
+
+ // Copy in everything up to the new row
+ System.arraycopy(oldRows, 0, rows, 0, row);
+
+ // Copy in the remaining rows
+ System.arraycopy(oldRows, row, rows, row+1, numRows - row);
+
+ // Increment all the internal row number by one
+ for (int i = row+1; i <= numRows; i++)
+ {
+ if (rows[i] != null)
+ {
+ rows[i].incrementRow();
+ }
+ }
+
+ // Adjust any hyperlinks
+ HyperlinkRecord hr = null;
+ Iterator i = hyperlinks.iterator();
+ while (i.hasNext())
+ {
+ hr = (HyperlinkRecord) i.next();
+ hr.insertRow(row);
+ }
+
+ // Adjust any data validations
+ if (dataValidation != null)
+ {
+ dataValidation.insertRow(row);
+ }
+
+ if (validatedCells != null && validatedCells.size() > 0)
+ {
+ for (Iterator vci = validatedCells.iterator(); vci.hasNext();)
+ {
+ CellValue cv = (CellValue) vci.next();
+ CellFeatures cf = cv.getCellFeatures();
+ if (cf.getDVParser() != null)
+ {
+ cf.getDVParser().insertRow(row);
+ }
+ }
+ }
+
+ // Adjust any merged cells
+ mergedCells.insertRow(row);
+
+ // Adjust any page breaks
+ ArrayList newRowBreaks = new ArrayList();
+ Iterator ri = rowBreaks.iterator();
+ while (ri.hasNext())
+ {
+ int val = ( (Integer) ri.next()).intValue();
+ if (val >= row)
+ {
+ val++;
+ }
+
+ newRowBreaks.add(new Integer(val));
+ }
+ rowBreaks = newRowBreaks;
+
+ // Adjust any conditional formats
+ for (Iterator cfit = conditionalFormats.iterator(); cfit.hasNext() ;)
+ {
+ ConditionalFormat cf = (ConditionalFormat) cfit.next();
+ cf.insertRow(row);
+ }
+
+ // Handle interested cell references on the main workbook
+ if (workbookSettings.getFormulaAdjust())
+ {
+ workbook.rowInserted(this, row);
+ }
+
+ // Adjust the maximum row record
+ numRows++;
+ }
+
+ /**
+ * Inserts a blank column into this spreadsheet. If the column is out of
+ * range of the columns in the sheet, then no action is taken
+ *
+ * @param col the column to insert
+ */
+ public void insertColumn(int col)
+ {
+ if (col < 0 || col >= numColumns)
+ {
+ return;
+ }
+
+ // Iterate through all the row records adding in the column
+ for (int i = 0 ; i < numRows ; i++)
+ {
+ if (rows[i] != null)
+ {
+ rows[i].insertColumn(col);
+ }
+ }
+
+ // Adjust any hyperlinks
+ HyperlinkRecord hr = null;
+ Iterator i = hyperlinks.iterator();
+ while (i.hasNext())
+ {
+ hr = (HyperlinkRecord) i.next();
+ hr.insertColumn(col);
+ }
+
+ // Iterate through the column views, incrementing the column number
+ i = columnFormats.iterator();
+ while (i.hasNext())
+ {
+ ColumnInfoRecord cir = (ColumnInfoRecord) i.next();
+
+ if (cir.getColumn() >= col)
+ {
+ cir.incrementColumn();
+ }
+ }
+
+ // Iterate through the autosized columns, incrementing the column number
+ if (autosizedColumns.size() > 0)
+ {
+ TreeSet newAutosized = new TreeSet();
+ i = autosizedColumns.iterator();
+ while (i.hasNext())
+ {
+ Integer colnumber = (Integer) i.next();
+
+ if (colnumber.intValue() >= col)
+ {
+ newAutosized.add(new Integer(colnumber.intValue() + 1));
+ }
+ else
+ {
+ newAutosized.add(colnumber);
+ }
+ }
+ autosizedColumns = newAutosized;
+ }
+
+ // Handle any data validations
+ if (dataValidation != null)
+ {
+ dataValidation.insertColumn(col);
+ }
+
+ if (validatedCells != null && validatedCells.size() > 0)
+ {
+ for (Iterator vci = validatedCells.iterator(); vci.hasNext();)
+ {
+ CellValue cv = (CellValue) vci.next();
+ CellFeatures cf = cv.getCellFeatures();
+ if (cf.getDVParser() != null)
+ {
+ cf.getDVParser().insertColumn(col);
+ }
+ }
+ }
+
+ // Adjust any merged cells
+ mergedCells.insertColumn(col);
+
+ // Adjust any page breaks
+ ArrayList newColumnBreaks = new ArrayList();
+ Iterator ri = columnBreaks.iterator();
+ while (ri.hasNext())
+ {
+ int val = ( (Integer) ri.next()).intValue();
+ if (val >= col)
+ {
+ val++;
+ }
+
+ newColumnBreaks.add(new Integer(val));
+ }
+ columnBreaks = newColumnBreaks;
+
+ // Adjust any conditional formats
+ for (Iterator cfit = conditionalFormats.iterator(); cfit.hasNext() ;)
+ {
+ ConditionalFormat cf = (ConditionalFormat) cfit.next();
+ cf.insertColumn(col);
+ }
+
+ // Handle interested cell references on the main workbook
+ if (workbookSettings.getFormulaAdjust())
+ {
+ workbook.columnInserted(this, col);
+ }
+
+ numColumns++;
+ }
+
+ /**
+ * Removes a column from this spreadsheet. If the column is out of range
+ * of the columns in the sheet, then no action is taken
+ *
+ * @param col the column to remove
+ */
+ public void removeColumn(int col)
+ {
+ if (col < 0 || col >= numColumns)
+ {
+ return;
+ }
+
+ // Iterate through all the row records removing the column
+ for (int i = 0 ; i < numRows ; i++)
+ {
+ if (rows[i] != null)
+ {
+ rows[i].removeColumn(col);
+ }
+ }
+
+ // Adjust any hyperlinks
+ HyperlinkRecord hr = null;
+ Iterator i = hyperlinks.iterator();
+ while (i.hasNext())
+ {
+ hr = (HyperlinkRecord) i.next();
+
+ if (hr.getColumn() == col &&
+ hr.getLastColumn() == col)
+ {
+ // The row with the hyperlink on has been removed, so get
+ // rid of it from the list
+ i.remove();
+ }
+ else
+ {
+ hr.removeColumn(col);
+ }
+ }
+
+ // Adjust any data validations
+ if (dataValidation != null)
+ {
+ dataValidation.removeColumn(col);
+ }
+
+ if (validatedCells != null && validatedCells.size() > 0)
+ {
+ for (Iterator vci = validatedCells.iterator(); vci.hasNext();)
+ {
+ CellValue cv = (CellValue) vci.next();
+ CellFeatures cf = cv.getCellFeatures();
+ if (cf.getDVParser() != null)
+ {
+ cf.getDVParser().removeColumn(col);
+ }
+ }
+ }
+
+ // Adjust any merged cells
+ mergedCells.removeColumn(col);
+
+ // Adjust any page breaks
+ ArrayList newColumnBreaks = new ArrayList();
+ Iterator ri = columnBreaks.iterator();
+ while (ri.hasNext())
+ {
+ int val = ( (Integer) ri.next()).intValue();
+
+ if (val != col)
+ {
+ if (val > col)
+ {
+ val--;
+ }
+
+ newColumnBreaks.add(new Integer(val));
+ }
+ }
+
+ columnBreaks = newColumnBreaks;
+
+
+ // Iterate through the column views, decrementing the column number
+ i = columnFormats.iterator();
+ ColumnInfoRecord removeColumn = null;
+ while (i.hasNext())
+ {
+ ColumnInfoRecord cir = (ColumnInfoRecord) i.next();
+
+ if (cir.getColumn() == col)
+ {
+ removeColumn = cir;
+ }
+ else if (cir.getColumn() > col)
+ {
+ cir.decrementColumn();
+ }
+ }
+
+ if (removeColumn != null)
+ {
+ columnFormats.remove(removeColumn);
+ }
+
+ // Iterate through the autosized columns, decrementing the column number
+ if (autosizedColumns.size() > 0)
+ {
+ TreeSet newAutosized = new TreeSet();
+ i = autosizedColumns.iterator();
+ while (i.hasNext())
+ {
+ Integer colnumber = (Integer) i.next();
+
+ if (colnumber.intValue() == col)
+ {
+ // do nothing
+ }
+ else if (colnumber.intValue() > col)
+ {
+ newAutosized.add(new Integer(colnumber.intValue() - 1));
+ }
+ else
+ {
+ newAutosized.add(colnumber);
+ }
+ }
+ autosizedColumns = newAutosized;
+ }
+
+ // Adjust any conditional formats
+ for (Iterator cfit = conditionalFormats.iterator(); cfit.hasNext() ;)
+ {
+ ConditionalFormat cf = (ConditionalFormat) cfit.next();
+ cf.removeColumn(col);
+ }
+
+ // Handle interested cell references on the main workbook
+ if (workbookSettings.getFormulaAdjust())
+ {
+ workbook.columnRemoved(this, col);
+ }
+
+ numColumns--;
+ }
+
+ /**
+ * Removes a row from this spreadsheet. If the row is out of
+ * range of the columns in the sheet, then no action is taken
+ *
+ * @param row the row to remove
+ */
+ public void removeRow(int row)
+ {
+ if (row < 0 || row >= numRows)
+ {
+ // Call rowRemoved anyway, to adjust the named cells
+ if (workbookSettings.getFormulaAdjust())
+ {
+ workbook.rowRemoved(this, row);
+ }
+
+ return;
+ }
+
+ // Create a new array to hold the new rows. Grow it if need be
+ RowRecord[] oldRows = rows;
+
+ rows = new RowRecord[oldRows.length];
+
+ // Copy in everything up to the row to be removed
+ System.arraycopy(oldRows, 0, rows, 0, row);
+
+ // Copy in the remaining rows
+ System.arraycopy(oldRows, row + 1, rows, row, numRows - (row + 1));
+
+ // Decrement all the internal row numbers by one
+ for (int i = row; i < numRows; i++)
+ {
+ if (rows[i] != null)
+ {
+ rows[i].decrementRow();
+ }
+ }
+
+ // Adjust any hyperlinks
+ HyperlinkRecord hr = null;
+ Iterator i = hyperlinks.iterator();
+ while (i.hasNext())
+ {
+ hr = (HyperlinkRecord) i.next();
+
+ if (hr.getRow() == row &&
+ hr.getLastRow() == row)
+ {
+ // The row with the hyperlink on has been removed, so get
+ // rid of it from the list
+ i.remove();
+ }
+ else
+ {
+ hr.removeRow(row);
+ }
+ }
+
+ // Adjust any data validations
+ if (dataValidation != null)
+ {
+ dataValidation.removeRow(row);
+ }
+
+ if (validatedCells != null && validatedCells.size() > 0)
+ {
+ for (Iterator vci = validatedCells.iterator(); vci.hasNext();)
+ {
+ CellValue cv = (CellValue) vci.next();
+ CellFeatures cf = cv.getCellFeatures();
+ if (cf.getDVParser() != null)
+ {
+ cf.getDVParser().removeRow(row);
+ }
+ }
+ }
+
+ // Adjust any merged cells
+ mergedCells.removeRow(row);
+
+ // Adjust any page breaks
+ ArrayList newRowBreaks = new ArrayList();
+ Iterator ri = rowBreaks.iterator();
+ while (ri.hasNext())
+ {
+ int val = ( (Integer) ri.next()).intValue();
+
+ if (val != row)
+ {
+ if (val > row)
+ {
+ val--;
+ }
+
+ newRowBreaks.add(new Integer(val));
+ }
+ }
+
+ rowBreaks = newRowBreaks;
+
+ // Adjust any conditional formats
+ for (Iterator cfit = conditionalFormats.iterator(); cfit.hasNext() ;)
+ {
+ ConditionalFormat cf = (ConditionalFormat) cfit.next();
+ cf.removeRow(row);
+ }
+
+ // Handle interested cell references on the main workbook
+ if (workbookSettings.getFormulaAdjust())
+ {
+ workbook.rowRemoved(this, row);
+ }
+
+ // Adjust any drawings
+ /*
+ if (drawings != null)
+ {
+ for (Iterator drawingIt = drawings.iterator() ; drawingIt.hasNext() ; )
+ {
+ DrawingGroupObject dgo = (DrawingGroupObject) drawingIt.next();
+ dgo.removeRow(row);
+ }
+ }
+ */
+
+ // Adjust the maximum row record
+ numRows--;
+ }
+
+ /**
+ * Adds the cell to this sheet. If the cell has already been added to
+ * this sheet or another sheet, a WriteException is thrown. If the
+ * position to be occupied by this cell is already taken, the incumbent
+ * cell is replaced.
+ * The cell is then marked as referenced, and its formatting information
+ * registered with the list of formatting records updated if necessary
+ * The RowsExceededException may be caught if client code wishes to
+ * explicitly trap the case where too many rows have been written
+ * to the current sheet. If this behaviour is not desired, it is
+ * sufficient simply to handle the WriteException, since this is a base
+ * class of RowsExceededException
+ *
+ * @exception WriteException
+ * @exception RowsExceededException
+ * @param cell the cell to add
+ */
+ public void addCell(WritableCell cell)
+ throws WriteException, RowsExceededException
+ {
+ if (cell.getType() == CellType.EMPTY)
+ {
+ if (cell != null && cell.getCellFormat() == null)
+ {
+ // return if it's a blank cell with no particular cell formatting
+ // information
+ return;
+ }
+ }
+
+ CellValue cv = (CellValue) cell;
+
+ if (cv.isReferenced())
+ {
+ throw new JxlWriteException(JxlWriteException.cellReferenced);
+ }
+
+ int row = cell.getRow();
+ RowRecord rowrec = getRowRecord(row);
+ rowrec.addCell(cv);
+
+ // Adjust the max rows and max columns accordingly
+ numRows = Math.max(row+1, numRows);
+ numColumns = Math.max(numColumns, rowrec.getMaxColumn());
+
+ // Indicate this cell is now part of a worksheet, so that it can't be
+ // added anywhere else
+ cv.setCellDetails(formatRecords, sharedStrings, this);
+ }
+
+ /**
+ * Gets the row record at the specified row number, growing the
+ * array as needs dictate
+ *
+ * @param row the row number we are interested in
+ * @return the row record at the specified row
+ * @exception RowsExceededException
+ */
+ RowRecord getRowRecord(int row) throws RowsExceededException
+ {
+ if (row >= numRowsPerSheet)
+ {
+ throw new RowsExceededException();
+ }
+
+ // Grow the array of rows if needs be
+ // Thanks to Brendan for spotting the flaw in merely adding on the
+ // grow size
+ if (row >= rows.length)
+ {
+ RowRecord[] oldRows = rows;
+ rows = new RowRecord[Math.max(oldRows.length + rowGrowSize, row+1)];
+ System.arraycopy(oldRows, 0, rows, 0, oldRows.length);
+ oldRows = null;
+ }
+
+ RowRecord rowrec = rows[row];
+
+ if (rowrec == null)
+ {
+ rowrec = new RowRecord(row, this);
+ rows[row] = rowrec;
+ }
+
+ return rowrec;
+ }
+
+ /**
+ * Gets the row record for the specified row
+ *
+ * @param r the row
+ * @return the row record
+ */
+ RowRecord getRowInfo(int r)
+ {
+ if (r < 0 || r > rows.length)
+ {
+ return null;
+ }
+
+ return rows[r];
+ }
+
+ /**
+ * Gets the column info record for the specified column
+ *
+ * @param c the column
+ * @return the column record
+ */
+ ColumnInfoRecord getColumnInfo(int c)
+ {
+ Iterator i = columnFormats.iterator();
+ ColumnInfoRecord cir = null;
+ boolean stop = false;
+
+ while (i.hasNext() && !stop)
+ {
+ cir = (ColumnInfoRecord) i.next();
+
+ if (cir.getColumn() >= c)
+ {
+ stop = true;
+ }
+ }
+
+ if (!stop)
+ {
+ return null;
+ }
+
+ return cir.getColumn() == c ? cir : null;
+ }
+
+ /**
+ * Sets the name of this worksheet
+ *
+ * @param n the name of this sheet
+ */
+ public void setName(String n)
+ {
+ name = n;
+ }
+
+ /**
+ * Sets the hidden status of this sheet
+ *
+ * @param h the hiden flag
+ * @deprecated Use the settings bean instead
+ */
+ public void setHidden(boolean h)
+ {
+ settings.setHidden(h);
+ }
+
+ /**
+ * Indicates whether or not this sheet is protected
+ *
+ * @param prot protected flag
+ * @deprecated Use the settings bean instead
+ */
+ public void setProtected(boolean prot)
+ {
+ settings.setProtected(prot);
+ }
+
+ /**
+ * Sets this sheet as selected
+ * @deprecated Use the settings bean
+ */
+ public void setSelected()
+ {
+ settings.setSelected();
+ }
+
+ /**
+ * Retrieves the hidden status of this sheet
+ *
+ * @return TRUE if hidden, FALSE otherwise
+ * @deprecated Use the sheet settings bean instead
+ */
+ public boolean isHidden()
+ {
+ return settings.isHidden();
+ }
+
+ /**
+ * Sets the width (in characters) for a particular column in this sheet
+ *
+ * @param col the column whose width to set
+ * @param width the width of the column in characters
+ */
+ public void setColumnView(int col, int width)
+ {
+ CellView cv = new CellView();
+ cv.setSize(width * 256);
+ setColumnView(col, cv);
+ }
+
+ /**
+ * Sets the width (in characters) and format options for a
+ * particular column in this sheet
+ *
+ * @param col the column to set
+ * @param width the width in characters
+ * @param format the formt details for the column
+ */
+ public void setColumnView(int col, int width, CellFormat format)
+ {
+ CellView cv = new CellView();
+ cv.setSize(width * 256);
+ cv.setFormat(format);
+ setColumnView(col, cv);
+ }
+
+ /**
+ * Sets the view for this column
+ *
+ * @param col the column on which to set the view
+ * @param view the view to set
+ */
+ public void setColumnView(int col, CellView view)
+ {
+ XFRecord xfr = (XFRecord) view.getFormat();
+ if (xfr == null)
+ {
+ Styles styles = getWorkbook().getStyles();
+ xfr = styles.getNormalStyle();
+ }
+
+ try
+ {
+ if (!xfr.isInitialized())
+ {
+ formatRecords.addStyle(xfr);
+ }
+
+ int width = view.depUsed() ? view.getDimension() * 256 : view.getSize();
+
+ if (view.isAutosize())
+ {
+ autosizedColumns.add(new Integer(col));
+ }
+
+ ColumnInfoRecord cir = new ColumnInfoRecord(col,
+ width,
+ xfr);
+
+ if (view.isHidden())
+ {
+ cir.setHidden(true);
+ }
+
+ if (!columnFormats.contains(cir))
+ {
+ columnFormats.add(cir);
+ }
+ else
+ {
+ columnFormats.remove(cir);
+ columnFormats.add(cir);
+ }
+ }
+ catch (NumFormatRecordsException e)
+ {
+ logger.warn("Maximum number of format records exceeded. Using " +
+ "default format.");
+
+ ColumnInfoRecord cir = new ColumnInfoRecord
+ (col, view.getDimension()*256, WritableWorkbook.NORMAL_STYLE);
+ if (!columnFormats.contains(cir))
+ {
+ columnFormats.add(cir);
+ }
+ }
+ }
+
+
+ /**
+ * Sets the height of the specified row, as well as its collapse status
+ *
+ * @param row the row to be formatted
+ * @param height the row height in 1/20ths of a point
+ * @exception RowsExceededException
+ * @deprecated use the override which takes a CellView object
+ */
+ public void setRowView(int row, int height) throws RowsExceededException
+ {
+ CellView cv = new CellView();
+ cv.setSize(height);
+ cv.setHidden(false);
+ setRowView(row, cv);
+ }
+
+ /**
+ * Sets the height of the specified row, as well as its collapse status
+ *
+ * @param row the row to be formatted
+ * @param collapsed indicates whether the row is collapsed
+ * @exception jxl.write.biff.RowsExceededException
+ * @deprecated use the override which takes a CellView object
+ */
+ public void setRowView(int row, boolean collapsed)
+ throws RowsExceededException
+ {
+ CellView cv = new CellView();
+ cv.setHidden(collapsed);
+ setRowView(row, cv);
+ }
+
+ /**
+ * Sets the height of the specified row, as well as its collapse status
+ *
+ * @param row the row to be formatted
+ * @param height the row height in 1/20th of a point
+ * @param collapsed indicates whether the row is collapsed
+ * @param zeroHeight indicates that the row has zero height
+ * @exception RowsExceededException
+ * @deprecated use the override which takes a CellView object
+ */
+ public void setRowView(int row, int height,
+ boolean collapsed)
+ throws RowsExceededException
+ {
+ CellView cv = new CellView();
+ cv.setSize(height);
+ cv.setHidden(collapsed);
+ setRowView(row, cv);
+ }
+
+ /**
+ * Sets the view for this column
+ *
+ * @param row the column on which to set the view
+ * @param view the view to set
+ * @exception RowsExceededException
+ */
+ public void setRowView(int row, CellView view) throws RowsExceededException
+ {
+ RowRecord rowrec = getRowRecord(row);
+
+ XFRecord xfr = (XFRecord) view.getFormat();
+
+ try
+ {
+ if (xfr != null)
+ {
+ if (!xfr.isInitialized())
+ {
+ formatRecords.addStyle(xfr);
+ }
+ }
+ }
+ catch (NumFormatRecordsException e)
+ {
+ logger.warn("Maximum number of format records exceeded. Using " +
+ "default format.");
+
+ xfr = null;
+ }
+
+ rowrec.setRowDetails(view.getSize(),
+ false,
+ view.isHidden(),
+ 0,
+ false,
+ xfr);
+ numRows = Math.max(numRows, row + 1);
+ }
+
+ /**
+ * Writes out this sheet. This functionality is delegated off to the
+ * SheetWriter class in order to reduce the bloated nature of this source
+ * file
+ *
+ * @exception IOException
+ */
+ public void write() throws IOException
+ {
+ boolean dmod = drawingsModified;
+ if (workbook.getDrawingGroup() != null)
+ {
+ dmod |= workbook.getDrawingGroup().hasDrawingsOmitted();
+ }
+
+ if (autosizedColumns.size() > 0)
+ {
+ autosizeColumns();
+ }
+
+ sheetWriter.setWriteData(rows,
+ rowBreaks,
+ columnBreaks,
+ hyperlinks,
+ mergedCells,
+ columnFormats,
+ maxRowOutlineLevel,
+ maxColumnOutlineLevel);
+ sheetWriter.setDimensions(getRows(), getColumns());
+ sheetWriter.setSettings(settings);
+ sheetWriter.setPLS(plsRecord);
+ sheetWriter.setDrawings(drawings, dmod);
+ sheetWriter.setButtonPropertySet(buttonPropertySet);
+ sheetWriter.setDataValidation(dataValidation, validatedCells);
+ sheetWriter.setConditionalFormats(conditionalFormats);
+ sheetWriter.setAutoFilter(autoFilter);
+
+ sheetWriter.write();
+ }
+
+ /**
+ * Copies the specified sheet, row by row and cell by cell
+ *
+ * @param s the sheet to copy
+ */
+ void copy(Sheet s)
+ {
+ // Copy the settings
+ settings = new SheetSettings(s.getSettings(), this);
+
+ SheetCopier si = new SheetCopier(s, this);
+ si.setColumnFormats(columnFormats);
+ si.setFormatRecords(formatRecords);
+ si.setHyperlinks(hyperlinks);
+ si.setMergedCells(mergedCells);
+ si.setRowBreaks(rowBreaks);
+ si.setColumnBreaks(columnBreaks);
+ si.setSheetWriter(sheetWriter);
+ si.setDrawings(drawings);
+ si.setImages(images);
+ si.setConditionalFormats(conditionalFormats);
+
+ si.copySheet();
+
+ dataValidation = si.getDataValidation();
+ comboBox = si.getComboBox();
+ plsRecord = si.getPLSRecord();
+ chartOnly = si.isChartOnly();
+ buttonPropertySet = si.getButtonPropertySet();
+ numRows = si.getRows();
+ autoFilter = si.getAutoFilter();
+ maxRowOutlineLevel = si.getMaxRowOutlineLevel();
+ maxColumnOutlineLevel = si.getMaxColumnOutlineLevel();
+ }
+
+ /**
+ * Copies the specified sheet, row by row and cell by cell
+ *
+ * @param s the sheet to copy
+ */
+ void copy(WritableSheet s)
+ {
+ settings = new SheetSettings(s.getSettings(), this);
+ WritableSheetImpl si = (WritableSheetImpl) s;
+
+ WritableSheetCopier sc = new WritableSheetCopier(s, this);
+ sc.setColumnFormats(si.columnFormats, columnFormats);
+ sc.setMergedCells(si.mergedCells, mergedCells);
+ sc.setRows(si.rows);
+ sc.setRowBreaks(si.rowBreaks, rowBreaks);
+ sc.setColumnBreaks(si.columnBreaks, columnBreaks);
+ sc.setDataValidation(si.dataValidation);
+ sc.setSheetWriter(sheetWriter);
+ sc.setDrawings(si.drawings, drawings, images);
+ sc.setWorkspaceOptions(si.getWorkspaceOptions());
+ sc.setPLSRecord(si.plsRecord);
+ sc.setButtonPropertySetRecord(si.buttonPropertySet);
+ sc.setHyperlinks(si.hyperlinks, hyperlinks);
+
+ sc.copySheet();
+
+ dataValidation = sc.getDataValidation();
+ plsRecord = sc.getPLSRecord();
+ buttonPropertySet = sc.getButtonPropertySet();
+ }
+
+ /**
+ * Gets the header. Called when copying sheets
+ *
+ * @return the page header
+ */
+ final HeaderRecord getHeader()
+ {
+ return sheetWriter.getHeader();
+ }
+
+ /**
+ * Gets the footer. Called when copying sheets
+ *
+ * @return the page footer
+ */
+ final FooterRecord getFooter()
+ {
+ return sheetWriter.getFooter();
+ }
+ /**
+ * Determines whether the sheet is protected
+ *
+ * @return whether or not the sheet is protected
+ * @deprecated Use the SheetSettings bean instead
+ */
+ public boolean isProtected()
+ {
+ return settings.isProtected();
+ }
+
+ /**
+ * Gets the hyperlinks on this sheet
+ *
+ * @return an array of hyperlinks
+ */
+ public Hyperlink[] getHyperlinks()
+ {
+ Hyperlink[] hl = new Hyperlink[hyperlinks.size()];
+
+ for (int i = 0; i < hyperlinks.size(); i++)
+ {
+ hl[i] = (Hyperlink) hyperlinks.get(i);
+ }
+
+ return hl;
+ }
+
+ /**
+ * Gets the cells which have been merged on this sheet
+ *
+ * @return an array of range objects
+ */
+ public Range[] getMergedCells()
+ {
+ return mergedCells.getMergedCells();
+ }
+
+ /**
+ * Gets the writable hyperlinks on this sheet
+ *
+ * @return an array of hyperlinks
+ */
+ public WritableHyperlink[] getWritableHyperlinks()
+ {
+ WritableHyperlink[] hl = new WritableHyperlink[hyperlinks.size()];
+
+ for (int i = 0; i < hyperlinks.size(); i++)
+ {
+ hl[i] = (WritableHyperlink) hyperlinks.get(i);
+ }
+
+ return hl;
+ }
+
+ /**
+ * Removes the specified hyperlink. Note that if you merely set the
+ * cell contents to be an Empty cell, then the cells containing the
+ * hyperlink will still be active. The contents of the cell which
+ * activate the hyperlink are removed.
+ * The hyperlink passed in must be a hyperlink retrieved using the
+ * getHyperlinks method
+ *
+ * @param h the hyperlink to remove.
+ * @param preserveLabel if TRUE preserves the label contents, if FALSE
+ * removes them
+ */
+ public void removeHyperlink(WritableHyperlink h)
+ {
+ removeHyperlink(h, false);
+ }
+
+ /**
+ * Removes the specified hyperlink. Note that if you merely set the
+ * cell contents to be an Empty cell, then the cells containing the
+ * hyperlink will still be active.
+ * If the preserveLabel field is set, the cell contents of the
+ * hyperlink are preserved, although the hyperlink is deactivated. If
+ * this value is FALSE, the cell contents are removed
+ * The hyperlink passed in must be a hyperlink retrieved using the
+ * getHyperlinks method
+ *
+ * @param h the hyperlink to remove.
+ * @param preserveLabel if TRUE preserves the label contents, if FALSE
+ * removes them
+ */
+ public void removeHyperlink(WritableHyperlink h, boolean preserveLabel)
+ {
+ // Remove the hyperlink
+ hyperlinks.remove(hyperlinks.indexOf(h));
+
+ if (!preserveLabel)
+ {
+ // Set the cell contents for the hyperlink - including any formatting
+ // information - to be empty
+ Assert.verify(rows.length > h.getRow() && rows[h.getRow()] != null);
+ rows[h.getRow()].removeCell(h.getColumn());
+ }
+ }
+
+ /**
+ * Adds the specified hyperlink
+ *
+ * @param the hyperlink
+ * @exception WriteException
+ * @exception RowsExceededException
+ */
+ public void addHyperlink(WritableHyperlink h)
+ throws WriteException, RowsExceededException
+ {
+ // First set the label on the sheet
+ Cell c = getCell(h.getColumn(), h.getRow());
+
+ String contents = null;
+ if (h.isFile() || h.isUNC())
+ {
+ String cnts = ( (HyperlinkRecord) h).getContents();
+ if (cnts == null)
+ {
+ contents = h.getFile().getPath();
+ }
+ else
+ {
+ contents = cnts;
+ }
+ }
+ else if (h.isURL())
+ {
+ String cnts = ( (HyperlinkRecord) h).getContents();
+ if (cnts == null)
+ {
+ contents = h.getURL().toString();
+ }
+ else
+ {
+ contents=cnts;
+ }
+ }
+ else if (h.isLocation())
+ {
+ contents = ( (HyperlinkRecord) h).getContents();
+ }
+
+ // If the cell type is a label, then preserve the cell contents
+ // and most of the format (apart from the font)
+ // otherwise overwrite the cell content and the format with the contents
+ // and the standard hyperlink format
+ if (c.getType() == CellType.LABEL)
+ {
+ Label l = (Label) c;
+ l.setString(contents);
+ WritableCellFormat wcf = new WritableCellFormat(l.getCellFormat());
+ ( (XFRecord) wcf).setFont(WritableWorkbook.HYPERLINK_FONT);
+ l.setCellFormat(wcf);
+ }
+ else
+ {
+ Label l = new Label(h.getColumn(), h.getRow(), contents,
+ WritableWorkbook.HYPERLINK_STYLE);
+ addCell(l);
+ }
+
+ // Set all other cells within range to be empty
+ for (int i = h.getRow(); i <= h.getLastRow(); i++)
+ {
+ for (int j = h.getColumn(); j <= h.getLastColumn(); j++)
+ {
+ if (i != h.getRow() && j != h.getColumn())
+ {
+ // Set the cell to be empty
+ if (rows.length < h.getLastColumn() && rows[i] != null)
+ {
+ rows[i].removeCell(j);
+ }
+ }
+ }
+ }
+
+ ((HyperlinkRecord) h).initialize(this);
+ hyperlinks.add(h);
+ }
+
+ /**
+ * Merges the specified cells. Any clashes or intersections between
+ * merged cells are resolved when the spreadsheet is written out
+ *
+ * @param col1 the column number of the top left cell
+ * @param row1 the row number of the top left cell
+ * @param col2 the column number of the bottom right cell
+ * @param row2 the row number of the bottom right cell
+ * @return the Range object representing the merged cells
+ * @exception jxl.write..WriteException
+ * @exception jxl.write.biff.RowsExceededException
+ */
+ public Range mergeCells(int col1, int row1, int col2, int row2)
+ throws WriteException, RowsExceededException
+ {
+ // First check that the cells make sense
+ if (col2 < col1 || row2 < row1)
+ {
+ logger.warn("Cannot merge cells - top left and bottom right "+
+ "incorrectly specified");
+ }
+
+ // Make sure the spreadsheet is up to size
+ if (col2 >= numColumns || row2 >= numRows)
+ {
+ addCell(new Blank(col2, row2));
+ }
+
+ SheetRangeImpl range = new SheetRangeImpl(this, col1, row1, col2, row2);
+ mergedCells.add(range);
+
+ return range;
+ }
+
+ /**
+ * Sets a row grouping
+ *
+ * @param row1 the first row of the group
+ * @param row2 the last row of the group
+ * @param collapsed should the group be collapsed?
+ * @exception WriteException
+ * @exception RowsExceededException
+ */
+ public void setRowGroup(int row1, int row2,
+ boolean collapsed)
+ throws WriteException, RowsExceededException
+ {
+ if (row2 < row1)
+ {
+ logger.warn("Cannot merge cells - top and bottom rows incorrectly " +
+ "specified");
+ }
+
+ for (int i = row1; i <= row2; i++)
+ {
+ RowRecord row = getRowRecord(i);
+ numRows = Math.max(i+1, numRows);
+ row.incrementOutlineLevel();
+ row.setCollapsed(collapsed);
+ maxRowOutlineLevel = Math.max(maxRowOutlineLevel,
+ row.getOutlineLevel());
+ }
+ }
+
+ /**
+ * Unsets a row grouping
+ *
+ * @param row1 the first row to unset
+ * @param row2 the last row to unset
+ * @exception WriteException
+ * @exception RowsExceededException
+ */
+ public void unsetRowGroup(int row1, int row2)
+ throws WriteException, RowsExceededException
+ {
+ if (row2 < row1)
+ {
+ logger.warn("Cannot merge cells - top and bottom rows incorrectly " +
+ "specified");
+ }
+
+ // Make sure the spreadsheet is up to size
+ if (row2 >= numRows)
+ {
+ logger.warn("" + row2 +
+ " is greater than the sheet bounds");
+ row2 = numRows - 1;
+ }
+
+ for (int i = row1; i <= row2; i++)
+ {
+ rows[i].decrementOutlineLevel();
+ }
+
+ // Recalculate the max outline level
+ maxRowOutlineLevel = 0;
+ for (int i = rows.length; i-- > 0; )
+ {
+ maxRowOutlineLevel = Math.max(maxRowOutlineLevel,
+ rows[i].getOutlineLevel());
+ }
+ }
+
+ /**
+ * Sets a column grouping
+ *
+ * @param col1 the first column of the group
+ * @param col2 the last column of the group
+ * @param collapsed should the group be collapsed?
+ * @exception WriteException
+ * @exception RowsExceededException
+ */
+ public void setColumnGroup(int col1, int col2, boolean collapsed)
+ throws WriteException, RowsExceededException
+ {
+ if (col2 < col1)
+ {
+ logger.warn("Cannot merge cells - top and bottom rows incorrectly " +
+ "specified");
+ }
+
+ for (int i = col1; i <= col2; i++)
+ {
+ ColumnInfoRecord cir = getColumnInfo(i);
+
+ // Create the column info record if not present using a default
+ // cell view
+ if (cir == null)
+ {
+ setColumnView(i, new CellView());
+ cir = getColumnInfo(i);
+ }
+
+ cir.incrementOutlineLevel();
+ cir.setCollapsed(collapsed);
+ maxColumnOutlineLevel = Math.max(maxColumnOutlineLevel,
+ cir.getOutlineLevel());
+ }
+ }
+
+ /**
+ * Unsets a column grouping
+ *
+ * @param col1 the first column to unset
+ * @param col2 the last column to unset
+ * @exception WriteException
+ * @exception RowsExceededException
+ */
+ public void unsetColumnGroup(int col1, int col2)
+ throws WriteException, RowsExceededException
+ {
+ if (col2 < col1)
+ {
+ logger.warn("Cannot merge cells - top and bottom rows incorrectly " +
+ "specified");
+ }
+
+ for (int i = col1; i <= col2; i++)
+ {
+ ColumnInfoRecord cir = getColumnInfo(i);
+ cir.decrementOutlineLevel();
+ }
+
+ // Recalculate the max outline level
+ maxColumnOutlineLevel = 0;
+ for (Iterator it = columnFormats.iterator(); it.hasNext(); )
+ {
+ ColumnInfoRecord cir = (ColumnInfoRecord)it.next();
+ maxColumnOutlineLevel = Math.max(maxColumnOutlineLevel,
+ cir.getOutlineLevel());
+ }
+ }
+
+ /**
+ * Unmerges the specified cells. The Range passed in should be one that
+ * has been previously returned as a result of the getMergedCells method
+ *
+ * @param r the range of cells to unmerge
+ */
+ public void unmergeCells(Range r)
+ {
+ mergedCells.unmergeCells(r);
+ }
+
+ /**
+ * Sets the header for this page
+ *
+ * @param l the print header to print on the left side
+ * @param c the print header to print in the centre
+ * @param r the print header to print on the right hand side
+ * @deprecated Use the sheet settings bean
+ */
+ public void setHeader(String l, String c, String r)
+ {
+ HeaderFooter header = new HeaderFooter();
+ header.getLeft().append(l);
+ header.getCentre().append(c);
+ header.getRight().append(r);
+ settings.setHeader(header);
+ }
+
+ /**
+ * Sets the footer for this page
+ *
+ * @param l the print header to print on the left side
+ * @param c the print header to print in the centre
+ * @param r the print header to print on the right hand side
+ * @deprecated Use the sheet settings bean
+ */
+ public void setFooter(String l, String c, String r)
+ {
+ HeaderFooter footer = new HeaderFooter();
+ footer.getLeft().append(l);
+ footer.getCentre().append(c);
+ footer.getRight().append(r);
+ settings.setFooter(footer);
+ }
+
+ /**
+ * Sets the page setup details
+ *
+ * @param p the page orientation
+ * @deprecated Use the SheetSettings bean
+ */
+ public void setPageSetup(PageOrientation p)
+ {
+ settings.setOrientation(p);
+ }
+
+ /**
+ * Sets the page setup details
+ *
+ * @param p the page orientation
+ * @param hm the header margin, in inches
+ * @param fm the footer margin, in inches
+ * @deprecated Use the SheetSettings bean
+ */
+ public void setPageSetup(PageOrientation p, double hm, double fm)
+ {
+ settings.setOrientation(p);
+ settings.setHeaderMargin(hm);
+ settings.setFooterMargin(fm);
+ }
+
+ /**
+ * Sets the page setup details
+ *
+ * @param p the page orientation
+ * @param ps the paper size
+ * @param hm the header margin, in inches
+ * @param fm the footer margin, in inches
+ * @deprecated Use the SheetSettings bean
+ */
+ public void setPageSetup(PageOrientation p, PaperSize ps,
+ double hm, double fm)
+ {
+ settings.setPaperSize(ps);
+ settings.setOrientation(p);
+ settings.setHeaderMargin(hm);
+ settings.setFooterMargin(fm);
+ }
+
+ /**
+ * Gets the settings for this sheet
+ *
+ * @return the page settings bean
+ */
+ public SheetSettings getSettings()
+ {
+ return settings;
+ }
+
+ /**
+ * Gets the workbook settings
+ */
+ WorkbookSettings getWorkbookSettings()
+ {
+ return workbookSettings;
+ }
+
+ /**
+ * Forces a page break at the specified row
+ *
+ * @param row the row to break at
+ */
+ public void addRowPageBreak(int row)
+ {
+ // First check that the row is not already present
+ Iterator i = rowBreaks.iterator();
+ boolean found = false;
+
+ while (i.hasNext() && !found)
+ {
+ if (( (Integer) i.next()).intValue() == row)
+ {
+ found = true;
+ }
+ }
+
+ if (!found)
+ {
+ rowBreaks.add(new Integer(row));
+ }
+ }
+
+ /**
+ * Forces a page break at the specified column
+ *
+ * @param col the column to break at
+ */
+ public void addColumnPageBreak(int col)
+ {
+ // First check that the row is not already present
+ Iterator i = columnBreaks.iterator();
+ boolean found = false;
+
+ while (i.hasNext() && !found)
+ {
+ if (( (Integer) i.next()).intValue() == col)
+ {
+ found = true;
+ }
+ }
+
+ if (!found)
+ {
+ columnBreaks.add(new Integer(col));
+ }
+ }
+
+ /**
+ * Accessor for the charts. Used when copying
+ *
+ * @return the charts on this sheet
+ */
+ Chart[] getCharts()
+ {
+ return sheetWriter.getCharts();
+ }
+
+ /**
+ * Accessor for the drawings. Used when copying
+ *
+ * @return the drawings on this sheet
+ */
+ private DrawingGroupObject[] getDrawings()
+ {
+ DrawingGroupObject[] dr = new DrawingGroupObject[drawings.size()];
+ dr = (DrawingGroupObject[]) drawings.toArray(dr);
+ return dr;
+ }
+
+ /**
+ * Check all the merged cells for borders. Although in an OO sense the
+ * logic should belong in this class, in order to reduce the bloated
+ * nature of the source code for this object this logic has been delegated
+ * to the SheetWriter
+ */
+ void checkMergedBorders()
+ {
+ sheetWriter.setWriteData(rows,
+ rowBreaks,
+ columnBreaks,
+ hyperlinks,
+ mergedCells,
+ columnFormats,
+ maxRowOutlineLevel,
+ maxColumnOutlineLevel);
+ sheetWriter.setDimensions(getRows(), getColumns());
+ sheetWriter.checkMergedBorders();
+ }
+
+ /**
+ * Accessor for the workspace options
+ *
+ * @return the workspace options
+ */
+ private WorkspaceInformationRecord getWorkspaceOptions()
+ {
+ return sheetWriter.getWorkspaceOptions();
+ }
+
+ /**
+ * Rationalizes the sheets xf index mapping
+ * @param xfMapping the index mapping for XFRecords
+ * @param fontMapping the index mapping for fonts
+ * @param formatMapping the index mapping for formats
+ */
+ void rationalize(IndexMapping xfMapping,
+ IndexMapping fontMapping,
+ IndexMapping formatMapping)
+ {
+ // Rationalize the column formats
+ for (Iterator i = columnFormats.iterator() ; i.hasNext() ;)
+ {
+ ColumnInfoRecord cir = (ColumnInfoRecord) i.next();
+ cir.rationalize(xfMapping);
+ }
+
+ // Rationalize the row formats
+ for (int i = 0; i < rows.length ; i++)
+ {
+ if (rows[i] != null)
+ {
+ rows[i].rationalize(xfMapping);
+ }
+ }
+
+ // Rationalize any data that appears on the charts
+ Chart[] charts = getCharts();
+ for (int c = 0; c < charts.length; c++)
+ {
+ charts[c].rationalize(xfMapping, fontMapping, formatMapping);
+ }
+ }
+
+ /**
+ * Accessor for the workbook
+ * @return the workbook
+ */
+ WritableWorkbookImpl getWorkbook()
+ {
+ return workbook;
+ }
+
+ /**
+ * Gets the column format for the specified column
+ *
+ * @param col the column number
+ * @return the column format, or NULL if the column has no specific format
+ * @deprecated Use getColumnView instead
+ */
+ public CellFormat getColumnFormat(int col)
+ {
+ return getColumnView(col).getFormat();
+ }
+
+ /**
+ * Gets the column width for the specified column
+ *
+ * @param col the column number
+ * @return the column width, or the default width if the column has no
+ * specified format
+ * @deprecated Use getColumnView instead
+ */
+ public int getColumnWidth(int col)
+ {
+ return getColumnView(col).getDimension();
+ }
+
+ /**
+ * Gets the column width for the specified column
+ *
+ * @param row the column number
+ * @return the row height, or the default height if the column has no
+ * specified format
+ * @deprecated Use getRowView instead
+ */
+ public int getRowHeight(int row)
+ {
+ return getRowView(row).getDimension();
+ }
+
+ /**
+ * Accessor for the chart only method
+ *
+ * @return TRUE if this is a chart only, FALSE otherwise
+ */
+ boolean isChartOnly()
+ {
+ return chartOnly;
+ }
+
+ /**
+ * Gets the row view for the specified row
+ *
+ * @param col the row number
+ * @return the row format, or the default format if no override is
+ specified
+ */
+ public CellView getRowView(int row)
+ {
+ CellView cv = new CellView();
+
+ try
+ {
+ RowRecord rr = getRowRecord(row);
+
+ if (rr == null || rr.isDefaultHeight())
+ {
+ cv.setDimension(settings.getDefaultRowHeight());
+ cv.setSize(settings.getDefaultRowHeight());
+ }
+ else if (rr.isCollapsed())
+ {
+ cv.setHidden(true);
+ }
+ else
+ {
+ cv.setDimension(rr.getRowHeight());
+ cv.setSize(rr.getRowHeight());
+ }
+ return cv;
+ }
+ catch (RowsExceededException e)
+ {
+ // Simple return the default
+ cv.setDimension(settings.getDefaultRowHeight());
+ cv.setSize(settings.getDefaultRowHeight());
+ return cv;
+ }
+ }
+
+ /**
+ * Gets the column width for the specified column
+ *
+ * @param col the column number
+ * @return the column format, or the default format if no override is
+ specified
+ */
+ public CellView getColumnView(int col)
+ {
+ ColumnInfoRecord cir = getColumnInfo(col);
+ CellView cv = new CellView();
+
+ if (cir != null)
+ {
+ cv.setDimension(cir.getWidth()/256);
+ cv.setSize(cir.getWidth());
+ cv.setHidden(cir.getHidden());
+ cv.setFormat(cir.getCellFormat());
+ }
+ else
+ {
+ cv.setDimension(settings.getDefaultColumnWidth()/256);
+ cv.setSize(settings.getDefaultColumnWidth() * 256);
+ }
+
+ return cv;
+ }
+
+ /**
+ * Adds an image to this sheet
+ *
+ * @param image the image to add
+ */
+ public void addImage(WritableImage image)
+ {
+ boolean supported = false;
+ java.io.File imageFile = image.getImageFile();
+ String fileType = "?";
+
+ if (imageFile != null)
+ {
+ String fileName = imageFile.getName();
+ int fileTypeIndex = fileName.lastIndexOf('.');
+ fileType = fileTypeIndex != -1 ?
+ fileName.substring(fileTypeIndex+1) : "";
+
+ for (int i = 0 ; i < imageTypes.length && !supported ; i++)
+ {
+ if (fileType.equalsIgnoreCase(imageTypes[i]))
+ {
+ supported = true;
+ }
+ }
+ }
+ else
+ {
+ supported = true;
+ }
+
+ if (supported)
+ {
+ workbook.addDrawing(image);
+ drawings.add(image);
+ images.add(image);
+ }
+ else
+ {
+ StringBuffer message = new StringBuffer("Image type ");
+ message.append(fileType);
+ message.append(" not supported. Supported types are ");
+ message.append(imageTypes[0]);
+ for (int i = 1 ; i < imageTypes.length ; i++)
+ {
+ message.append(", ");
+ message.append(imageTypes[i]);
+ }
+ logger.warn(message.toString());
+ }
+ }
+
+ /**
+ * Gets the number of images on this sheet
+ *
+ * @return the number of images on this sheet
+ */
+ public int getNumberOfImages()
+ {
+ return images.size();
+ }
+
+ /**
+ * Accessor for a particular image on this sheet
+ *
+ * @param i the 0-based image index number
+ * @return the image with the specified index number
+ */
+ public WritableImage getImage(int i)
+ {
+ return (WritableImage) images.get(i);
+ }
+
+ /**
+ * Accessor for a particular image on this sheet
+ *
+ * @param i the 0-based image index number
+ * @return the image with the specified index number
+ */
+ public Image getDrawing(int i)
+ {
+ return (Image) images.get(i);
+ }
+
+ /**
+ * Removes the specified image from this sheet. The image passed in
+ * must be the same instance as that retrieved from a getImage call
+ *
+ * @param wi the image to remove
+ */
+ public void removeImage(WritableImage wi)
+ {
+ drawings.remove(wi);
+ images.remove(wi);
+ drawingsModified = true;
+ workbook.removeDrawing(wi);
+ }
+
+ /**
+ * Validates the sheet name
+ */
+ private String validateName(String n)
+ {
+ if (n.length() > maxSheetNameLength)
+ {
+ logger.warn("Sheet name " + n + " too long - truncating");
+ n = n.substring(0, maxSheetNameLength);
+ }
+
+ if (n.charAt(0) == '\'')
+ {
+ logger.warn("Sheet naming cannot start with \' - removing");
+ n = n.substring(1);
+ }
+
+ for (int i = 0 ; i < illegalSheetNameCharacters.length ; i++)
+ {
+ String newname = n.replace(illegalSheetNameCharacters[i], '@');
+ if (n != newname)
+ {
+ logger.warn(illegalSheetNameCharacters[i] +
+ " is not a valid character within a sheet name - replacing");
+ }
+ n = newname;
+ }
+
+ return n;
+ }
+
+ /**
+ * Adds a drawing to the list - typically used for comments
+ *
+ * @param the drawing to add
+ */
+ void addDrawing(DrawingGroupObject o)
+ {
+ drawings.add(o);
+ Assert.verify(!(o instanceof Drawing));
+ }
+
+ /**
+ * Removes a drawing to the list - typically used for comments
+ *
+ * @param the drawing to add
+ */
+ void removeDrawing(DrawingGroupObject o)
+ {
+ int origSize = drawings.size();
+ drawings.remove(o);
+ int newSize = drawings.size();
+ drawingsModified = true;
+ Assert.verify(newSize == origSize -1);
+ }
+
+ /**
+ * Removes the data validation for the specified cell. Called from
+ * CellValue in response to a cell being replaced
+ *
+ * @param cv the cell being removed
+ */
+ void removeDataValidation(CellValue cv)
+ {
+ dataValidation.removeDataValidation(cv.getColumn(), cv.getRow());
+ }
+
+ /**
+ * Accessor for the page breaks on this sheet
+ *
+ * @return the page breaks on this sheet
+ */
+ public int[] getRowPageBreaks()
+ {
+ int[] rb = new int[rowBreaks.size()];
+ int pos = 0;
+ for (Iterator i = rowBreaks.iterator(); i.hasNext() ; pos++)
+ {
+ rb[pos] = ( (Integer) i.next()).intValue();
+ }
+ return rb;
+ }
+
+ /**
+ * Accessor for the page breaks on this sheet
+ *
+ * @return the page breaks on this sheet
+ */
+ public int[] getColumnPageBreaks()
+ {
+ int[] rb = new int[columnBreaks.size()];
+ int pos = 0;
+ for (Iterator i = columnBreaks.iterator(); i.hasNext() ; pos++)
+ {
+ rb[pos] = ( (Integer) i.next()).intValue();
+ }
+ return rb;
+ }
+
+ /**
+ * Flags the added cell as having data validation
+ *
+ * @param cell the cell with data validation
+ */
+ void addValidationCell(CellValue cv)
+ {
+ validatedCells.add(cv);
+ }
+
+ /**
+ * Accessor for the combo box object used for list data validations on this
+ * sheet
+ *
+ * @return the combo box
+ */
+ ComboBox getComboBox()
+ {
+ return comboBox;
+ }
+
+ /**
+ * Sets the combo box object used for list validations on this sheet
+ *
+ * @param cb the combo box
+ */
+ void setComboBox(ComboBox cb)
+ {
+ comboBox = cb;
+ }
+
+ /**
+ * Gets the data validation. Retrieved by CellValue when copying sheets
+ */
+ public DataValidation getDataValidation()
+ {
+ return dataValidation;
+ }
+
+ /**
+ * Performs the column autosizing
+ */
+ private void autosizeColumns()
+ {
+ Iterator i = autosizedColumns.iterator();
+ while (i.hasNext())
+ {
+ Integer col = (Integer) i.next();
+ autosizeColumn(col.intValue());
+ }
+ }
+
+ /**
+ * Autosizes the specified column
+ *
+ * @param col the column to autosize
+ */
+ private void autosizeColumn(int col)
+ {
+ int maxWidth = 0;
+ ColumnInfoRecord cir = getColumnInfo(col);
+ Font columnFont = cir.getCellFormat().getFont();
+ Font defaultFont = WritableWorkbook.NORMAL_STYLE.getFont();
+
+ for (int i = 0 ; i < numRows; i++)
+ {
+ Cell cell = null;
+ if (rows[i] != null)
+ {
+ cell = rows[i].getCell(col);
+ }
+
+ if (cell != null)
+ {
+ String contents = cell.getContents();
+ Font font = cell.getCellFormat().getFont();
+
+ Font activeFont = font.equals(defaultFont) ? columnFont : font;
+
+ int pointSize = activeFont.getPointSize();
+ int numChars = contents.length();
+
+ if (activeFont.isItalic() ||
+ activeFont.getBoldWeight() > 400) // magic value for normal bold
+ {
+ numChars += 2;
+ }
+
+ int points = numChars * pointSize;
+ maxWidth = Math.max(maxWidth, points * 256);
+ }
+ }
+ cir.setWidth((int) (maxWidth / defaultFont.getPointSize()));
+ }
+
+ /**
+ * Imports a sheet from a different workbook
+ *
+ * @param s the sheet to import
+ */
+ void importSheet(Sheet s)
+ {
+ // Copy the settings
+ settings = new SheetSettings(s.getSettings(), this);
+
+ SheetCopier si = new SheetCopier(s, this);
+ si.setColumnFormats(columnFormats);
+ si.setFormatRecords(formatRecords);
+ si.setHyperlinks(hyperlinks);
+ si.setMergedCells(mergedCells);
+ si.setRowBreaks(rowBreaks);
+ si.setColumnBreaks(columnBreaks);
+ si.setSheetWriter(sheetWriter);
+ si.setDrawings(drawings);
+ si.setImages(images);
+
+ si.importSheet();
+
+ dataValidation = si.getDataValidation();
+ comboBox = si.getComboBox();
+ plsRecord = si.getPLSRecord();
+ chartOnly = si.isChartOnly();
+ buttonPropertySet = si.getButtonPropertySet();
+ numRows = si.getRows();
+ maxRowOutlineLevel = si.getMaxRowOutlineLevel();
+ maxColumnOutlineLevel = si.getMaxColumnOutlineLevel();
+ }
+}
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/WritableWorkbookImpl.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/WritableWorkbookImpl.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/WritableWorkbookImpl.java 17 Aug 2012 14:51:11 -0000 1.1
@@ -0,0 +1,1869 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import common.Assert;
+import common.Logger;
+
+import jxl.Range;
+import jxl.Sheet;
+import jxl.Workbook;
+import jxl.WorkbookSettings;
+import jxl.biff.BuiltInName;
+import jxl.biff.CellReferenceHelper;
+import jxl.biff.CountryCode;
+import jxl.biff.Fonts;
+import jxl.biff.FormattingRecords;
+import jxl.biff.IndexMapping;
+import jxl.biff.IntegerHelper;
+import jxl.biff.RangeImpl;
+import jxl.biff.WorkbookMethods;
+import jxl.biff.drawing.Drawing;
+import jxl.biff.drawing.DrawingGroup;
+import jxl.biff.drawing.DrawingGroupObject;
+import jxl.biff.drawing.Origin;
+import jxl.biff.formula.ExternalSheet;
+import jxl.format.Colour;
+import jxl.format.RGB;
+import jxl.read.biff.WorkbookParser;
+import jxl.write.WritableCell;
+import jxl.write.WritableSheet;
+import jxl.write.WritableWorkbook;
+
+
+/**
+ * A writable workbook
+ */
+public class WritableWorkbookImpl extends WritableWorkbook
+ implements ExternalSheet, WorkbookMethods
+{
+ /**
+ * The logger
+ */
+ private static Logger logger = Logger.getLogger(WritableWorkbookImpl.class);
+ /**
+ * The list of formats available within this workbook
+ */
+ private FormattingRecords formatRecords;
+ /**
+ * The output file to write the workbook to
+ */
+ private File outputFile;
+ /**
+ * The list of sheets within this workbook
+ */
+ private ArrayList sheets;
+ /**
+ * The list of fonts available within this workbook
+ */
+ private Fonts fonts;
+ /**
+ * The list of external sheets, used by cell references in formulas
+ */
+ private ExternalSheetRecord externSheet;
+
+ /**
+ * The supbook records
+ */
+ private ArrayList supbooks;
+
+ /**
+ * The name records
+ */
+ private ArrayList names;
+
+ /**
+ * A lookup hash map of the name records
+ */
+ private HashMap nameRecords;
+
+ /**
+ * The shared strings used by this workbook
+ */
+ private SharedStrings sharedStrings;
+
+ /**
+ * Indicates whether or not the output stream should be closed. This
+ * depends on whether this Workbook was created with an output stream,
+ * or a flat file (flat file closes the stream
+ */
+ private boolean closeStream;
+
+ /**
+ * The workbook protection flag
+ */
+ private boolean wbProtected;
+
+ /**
+ * The settings for the workbook
+ */
+ private WorkbookSettings settings;
+
+ /**
+ * The list of cells for the entire workbook which need to be updated
+ * following a row/column insert or remove
+ */
+ private ArrayList rcirCells;
+
+ /**
+ * The drawing group
+ */
+ private DrawingGroup drawingGroup;
+
+ /**
+ * The common workbook styles
+ */
+ private Styles styles;
+
+ /**
+ * Contains macros flag
+ */
+ private boolean containsMacros;
+
+ /**
+ * The buttons property set
+ */
+ private ButtonPropertySetRecord buttonPropertySet;
+
+ /**
+ * The country record, initialised when copying a workbook
+ */
+ private CountryRecord countryRecord;
+
+ // synchronizer object for static unitiatialization
+ private static Object SYNCHRONIZER = new Object();
+ /**
+ * The names of any add in functions
+ */
+ private String[] addInFunctionNames;
+
+ /**
+ * Constructor. Writes the workbook direct to the existing output stream
+ *
+ * @exception IOException
+ * @param os the output stream
+ * @param cs TRUE if the workbook should close the output stream, FALSE
+ * @param ws the configuration for this workbook
+ * otherwise
+ */
+ public WritableWorkbookImpl(OutputStream os, boolean cs, WorkbookSettings ws)
+ throws IOException
+ {
+ super();
+ outputFile = new File(os, ws, null);
+ sheets = new ArrayList();
+ sharedStrings = new SharedStrings();
+ nameRecords = new HashMap();
+ closeStream = cs;
+ wbProtected = false;
+ containsMacros = false;
+ settings = ws;
+ rcirCells = new ArrayList();
+ styles = new Styles();
+
+ // Reset the statically declared styles. These are no longer needed
+ // because the Styles class will intercept all calls within
+ // CellValue.setCellDetails and if it detects a standard format, then it
+ // will return a clone. In short, the static cell values will
+ // never get initialized anyway. Still, just to be extra sure...
+ synchronized(SYNCHRONIZER)
+ {
+ WritableWorkbook.ARIAL_10_PT.uninitialize();
+ WritableWorkbook.HYPERLINK_FONT.uninitialize();
+ WritableWorkbook.NORMAL_STYLE.uninitialize();
+ WritableWorkbook.HYPERLINK_STYLE.uninitialize();
+ WritableWorkbook.HIDDEN_STYLE.uninitialize();
+ DateRecord.defaultDateFormat.uninitialize();
+ }
+
+ WritableFonts wf = new WritableFonts(this);
+ fonts = wf;
+
+ WritableFormattingRecords wfr = new WritableFormattingRecords(fonts,
+ styles);
+ formatRecords = wfr;
+ }
+
+ /**
+ * A pseudo copy constructor. Takes the handles to the font and formatting
+ * records
+ *
+ * @exception IOException
+ * @param w the workbook to copy
+ * @param os the output stream to write the data to
+ * @param cs TRUE if the workbook should close the output stream, FALSE
+ * @param ws the configuration for this workbook
+ */
+ public WritableWorkbookImpl(OutputStream os,
+ Workbook w,
+ boolean cs,
+ WorkbookSettings ws) throws IOException
+ {
+ super();
+ WorkbookParser wp = (WorkbookParser) w;
+
+ // Reset the statically declared styles. These are no longer needed
+ // because the Styles class will intercept all calls within
+ // CellValue.setCellDetails and if it detects a standard format, then it
+ // will return a clone. In short, the static cell values will
+ // never get initialized anyway. Still, just to be extra sure...
+ synchronized(SYNCHRONIZER)
+ {
+ WritableWorkbook.ARIAL_10_PT.uninitialize();
+ WritableWorkbook.HYPERLINK_FONT.uninitialize();
+ WritableWorkbook.NORMAL_STYLE.uninitialize();
+ WritableWorkbook.HYPERLINK_STYLE.uninitialize();
+ WritableWorkbook.HIDDEN_STYLE.uninitialize();
+ DateRecord.defaultDateFormat.uninitialize();
+ }
+
+ closeStream = cs;
+ sheets = new ArrayList();
+ sharedStrings = new SharedStrings();
+ nameRecords = new HashMap();
+ fonts = wp.getFonts();
+ formatRecords = wp.getFormattingRecords();
+ wbProtected = false;
+ settings = ws;
+ rcirCells = new ArrayList();
+ styles = new Styles();
+ outputFile = new File(os, ws, wp.getCompoundFile());
+
+ containsMacros = false;
+ if (!ws.getPropertySetsDisabled())
+ {
+ containsMacros = wp.containsMacros();
+ }
+
+ // Copy the country settings
+ if (wp.getCountryRecord() != null)
+ {
+ countryRecord = new CountryRecord(wp.getCountryRecord());
+ }
+
+ // Copy any add in functions
+ addInFunctionNames = wp.getAddInFunctionNames();
+
+ // Copy any external sheets
+ if (wp.getExternalSheetRecord() != null)
+ {
+ externSheet = new ExternalSheetRecord(wp.getExternalSheetRecord());
+
+ // Get the associated supbooks
+ jxl.read.biff.SupbookRecord[] readsr = wp.getSupbookRecords();
+ supbooks = new ArrayList(readsr.length);
+
+ for (int i = 0; i < readsr.length; i++)
+ {
+ jxl.read.biff.SupbookRecord readSupbook = readsr[i];
+ if (readSupbook.getType() == readSupbook.INTERNAL ||
+ readSupbook.getType() == readSupbook.EXTERNAL)
+ {
+ supbooks.add(new SupbookRecord(readSupbook, settings));
+ }
+ else
+ {
+ if (readSupbook.getType() != readSupbook.ADDIN)
+ {
+ logger.warn("unsupported supbook type - ignoring");
+ }
+ }
+ }
+ }
+
+ // Copy any drawings. These must be present before we try and copy
+ // the images from the read workbook
+ if (wp.getDrawingGroup() != null)
+ {
+ drawingGroup = new DrawingGroup(wp.getDrawingGroup());
+ }
+
+ // Copy the property set references
+ if (containsMacros && wp.getButtonPropertySet() != null)
+ {
+ buttonPropertySet = new ButtonPropertySetRecord
+ (wp.getButtonPropertySet());
+ }
+
+ // Copy any names
+ if (!settings.getNamesDisabled())
+ {
+ jxl.read.biff.NameRecord[] na = wp.getNameRecords();
+ names = new ArrayList(na.length);
+
+ for (int i = 0; i < na.length; i++)
+ {
+ if (na[i].isBiff8())
+ {
+ NameRecord n = new NameRecord(na[i], i);
+ names.add(n);
+ String name = n.getName();
+ nameRecords.put(name, n);
+ }
+ else
+ {
+ logger.warn("Cannot copy Biff7 name records - ignoring");
+ }
+ }
+ }
+
+ copyWorkbook(w);
+
+ // The copy process may have caused some critical fields in the
+ // read drawing group to change. Make sure these updates are reflected
+ // in the writable drawing group
+ if (drawingGroup != null)
+ {
+ drawingGroup.updateData(wp.getDrawingGroup());
+ }
+ }
+
+ /**
+ * Gets the sheets within this workbook. Use of this method for
+ * large worksheets can cause performance problems.
+ *
+ * @return an array of the individual sheets
+ */
+ public WritableSheet[] getSheets()
+ {
+ WritableSheet[] sheetArray = new WritableSheet[getNumberOfSheets()];
+
+ for (int i = 0 ; i < getNumberOfSheets() ; i++)
+ {
+ sheetArray[i] = getSheet(i);
+ }
+ return sheetArray;
+ }
+
+ /**
+ * Gets the sheet names
+ *
+ * @return an array of strings containing the sheet names
+ */
+ public String[] getSheetNames()
+ {
+ String[] sheetNames = new String[getNumberOfSheets()];
+
+ for (int i = 0 ; i < sheetNames.length ; i++)
+ {
+ sheetNames[i] = getSheet(i).getName();
+ }
+
+ return sheetNames;
+ }
+
+ /**
+ * Interface method from WorkbookMethods - gets the specified
+ * sheet within this workbook
+ *
+ * @param index the zero based index of the required sheet
+ * @return The sheet specified by the index
+ */
+ public Sheet getReadSheet(int index)
+ {
+ return getSheet(index);
+ }
+
+ /**
+ * Gets the specified sheet within this workbook
+ *
+ * @param index the zero based index of the reQuired sheet
+ * @return The sheet specified by the index
+ */
+ public WritableSheet getSheet(int index)
+ {
+ return (WritableSheet) sheets.get(index);
+ }
+
+ /**
+ * Gets the sheet with the specified name from within this workbook
+ *
+ * @param name the sheet name
+ * @return The sheet with the specified name, or null if it is not found
+ */
+ public WritableSheet getSheet(String name)
+ {
+ // Iterate through the boundsheet records
+ boolean found = false;
+ Iterator i = sheets.iterator();
+ WritableSheet s = null;
+
+ while (i.hasNext() && !found)
+ {
+ s = (WritableSheet) i.next();
+
+ if (s.getName().equals(name))
+ {
+ found = true;
+ }
+ }
+
+ return found ? s : null;
+ }
+
+ /**
+ * Returns the number of sheets in this workbook
+ *
+ * @return the number of sheets in this workbook
+ */
+ public int getNumberOfSheets()
+ {
+ return sheets.size();
+ }
+
+ /**
+ * Closes this workbook, and frees makes any memory allocated available
+ * for garbage collection
+ *
+ * @exception IOException
+ * @exception JxlWriteException
+ */
+ public void close() throws IOException, JxlWriteException
+ {
+ outputFile.close(closeStream);
+ }
+
+ /**
+ * Sets a new output file. This allows the smae workbook to be
+ * written to various different output files without having to
+ * read in any templates again
+ *
+ * @param fileName the file name
+ * @exception IOException
+ */
+ public void setOutputFile(java.io.File fileName) throws IOException
+ {
+ FileOutputStream fos = new FileOutputStream(fileName);
+ outputFile.setOutputFile(fos);
+ }
+
+
+ /**
+ * The internal method implementation for creating new sheets
+ *
+ * @param name
+ * @param index
+ * @param handleRefs flag indicating whether or not to handle external
+ * sheet references
+ * @return
+ */
+ private WritableSheet createSheet(String name, int index,
+ boolean handleRefs)
+ {
+ WritableSheet w = new WritableSheetImpl(name,
+ outputFile,
+ formatRecords,
+ sharedStrings,
+ settings,
+ this);
+
+ int pos = index;
+
+ if (index <= 0)
+ {
+ pos = 0;
+ sheets.add(0, w);
+ }
+ else if (index > sheets.size())
+ {
+ pos = sheets.size();
+ sheets.add(w);
+ }
+ else
+ {
+ sheets.add(index, w);
+ }
+
+ if (handleRefs && externSheet != null)
+ {
+ externSheet.sheetInserted(pos);
+ }
+
+ if (supbooks != null && supbooks.size() > 0)
+ {
+ SupbookRecord supbook = (SupbookRecord) supbooks.get(0);
+ if (supbook.getType() == SupbookRecord.INTERNAL)
+ {
+ supbook.adjustInternal(sheets.size());
+ }
+ }
+
+ return w;
+ }
+
+ /**
+ * Creates a new sheet within the workbook, at the specified position.
+ * The new sheet is inserted at the specified position, or prepended/appended
+ * to the list of sheets if the index specified is somehow inappropriate
+ *
+ * @param name the name of the new sheet
+ * @param index the index at which to add the sheet
+ * @return the created sheet
+ */
+ public WritableSheet createSheet(String name, int index)
+ {
+ return createSheet(name, index, true);
+ }
+
+ /**
+ * Removes a sheet from this workbook, the other sheets indices being
+ * altered accordingly. If the sheet referenced by the index
+ * does not exist, then no action is taken.
+ *
+ * @param index the index of the sheet to remove
+ */
+ public void removeSheet(int index)
+ {
+ int pos = index;
+ if (index <= 0)
+ {
+ pos = 0;
+ sheets.remove(0);
+ }
+ else if (index >= sheets.size())
+ {
+ pos = sheets.size() - 1;
+ sheets.remove(sheets.size() - 1);
+ }
+ else
+ {
+ sheets.remove(index);
+ }
+
+ if (externSheet != null)
+ {
+ externSheet.sheetRemoved(pos);
+ }
+
+ if (supbooks != null && supbooks.size() > 0)
+ {
+ SupbookRecord supbook = (SupbookRecord) supbooks.get(0);
+ if (supbook.getType() == SupbookRecord.INTERNAL)
+ {
+ supbook.adjustInternal(sheets.size());
+ }
+ }
+
+ if (names != null && names.size() > 0)
+ {
+ for (int i=0; i< names.size();i++)
+ {
+ NameRecord n = (NameRecord) names.get(i);
+ int oldRef = n.getSheetRef();
+ if(oldRef == (pos+1))
+ {
+ n.setSheetRef(0); // make a global name reference
+ }
+ else if (oldRef > (pos+1))
+ {
+ if(oldRef < 1)
+ {
+ oldRef = 1;
+ }
+ n.setSheetRef(oldRef-1); // move one sheet
+ }
+ }
+ }
+ }
+
+ /**
+ * Moves the specified sheet within this workbook to another index
+ * position.
+ *
+ * @param fromIndex the zero based index of the reQuired sheet
+ * @param toIndex the zero based index of the reQuired sheet
+ * @return the sheet that has been moved
+ */
+ public WritableSheet moveSheet(int fromIndex, int toIndex)
+ {
+ // Handle dodgy index
+ fromIndex = Math.max(fromIndex, 0);
+ fromIndex = Math.min(fromIndex, sheets.size() - 1);
+ toIndex = Math.max(toIndex, 0);
+ toIndex = Math.min(toIndex, sheets.size() - 1);
+
+ WritableSheet sheet= (WritableSheet)sheets.remove(fromIndex);
+ sheets.add(toIndex, sheet);
+
+ return sheet;
+ }
+
+ /**
+ * Writes out this sheet to the output file. First it writes out
+ * the standard workbook information required by excel, before calling
+ * the write method on each sheet individually
+ *
+ * @exception IOException
+ */
+ public void write() throws IOException
+ {
+ // Perform some preliminary sheet check before we start writing out
+ // the workbook
+ WritableSheetImpl wsi = null;
+ for (int i = 0; i < getNumberOfSheets(); i++)
+ {
+ wsi = (WritableSheetImpl) getSheet(i);
+
+ // Check the merged records. This has to be done before the
+ // globals are written out because some more XF formats might be created
+ wsi.checkMergedBorders();
+
+ // Check to see if there are any predefined names
+ Range range = wsi.getSettings().getPrintArea();
+ if (range != null)
+ {
+ addNameArea(BuiltInName.PRINT_AREA,
+ wsi,
+ range.getTopLeft().getColumn(),
+ range.getTopLeft().getRow(),
+ range.getBottomRight().getColumn(),
+ range.getBottomRight().getRow(),
+ false);
+ }
+
+ // Check to see if print titles by row were set
+ Range rangeR = wsi.getSettings().getPrintTitlesRow();
+ Range rangeC = wsi.getSettings().getPrintTitlesCol();
+ if (rangeR != null && rangeC != null)
+ {
+ addNameArea(BuiltInName.PRINT_TITLES,
+ wsi,
+ rangeR.getTopLeft().getColumn(),
+ rangeR.getTopLeft().getRow(),
+ rangeR.getBottomRight().getColumn(),
+ rangeR.getBottomRight().getRow(),
+ rangeC.getTopLeft().getColumn(),
+ rangeC.getTopLeft().getRow(),
+ rangeC.getBottomRight().getColumn(),
+ rangeC.getBottomRight().getRow(),
+ false);
+ }
+ // Check to see if print titles by row were set
+ else if (rangeR != null)
+ {
+ addNameArea(BuiltInName.PRINT_TITLES,
+ wsi,
+ rangeR.getTopLeft().getColumn(),
+ rangeR.getTopLeft().getRow(),
+ rangeR.getBottomRight().getColumn(),
+ rangeR.getBottomRight().getRow(),
+ false);
+ }
+ // Check to see if print titles by column were set
+ else if (rangeC != null)
+ {
+ addNameArea(BuiltInName.PRINT_TITLES,
+ wsi,
+ rangeC.getTopLeft().getColumn(),
+ rangeC.getTopLeft().getRow(),
+ rangeC.getBottomRight().getColumn(),
+ rangeC.getBottomRight().getRow(),
+ false);
+ }
+ }
+
+ // Rationalize all the XF and number formats
+ if (!settings.getRationalizationDisabled())
+ {
+ rationalize();
+ }
+
+ // Write the workbook globals
+ BOFRecord bof = new BOFRecord(BOFRecord.workbookGlobals);
+ outputFile.write(bof);
+
+ InterfaceHeaderRecord ihr = new InterfaceHeaderRecord();
+ outputFile.write(ihr);
+
+ MMSRecord mms = new MMSRecord(0,0);
+ outputFile.write(mms);
+
+ InterfaceEndRecord ier = new InterfaceEndRecord();
+ outputFile.write(ier);
+
+ WriteAccessRecord wr = new WriteAccessRecord();
+ outputFile.write(wr);
+
+ CodepageRecord cp = new CodepageRecord();
+ outputFile.write(cp);
+
+ DSFRecord dsf = new DSFRecord();
+ outputFile.write(dsf);
+
+ TabIdRecord tabid = new TabIdRecord(getNumberOfSheets());
+ outputFile.write(tabid);
+
+ if (containsMacros)
+ {
+ ObjProjRecord objproj = new ObjProjRecord();
+ outputFile.write(objproj);
+ }
+
+ if (buttonPropertySet != null)
+ {
+ outputFile.write(buttonPropertySet);
+ }
+
+ FunctionGroupCountRecord fgcr = new FunctionGroupCountRecord();
+ outputFile.write(fgcr);
+
+ // do not support password protected workbooks
+ WindowProtectRecord wpr = new WindowProtectRecord(false);
+ outputFile.write(wpr);
+
+ ProtectRecord pr = new ProtectRecord(wbProtected);
+ outputFile.write(pr);
+
+ PasswordRecord pw = new PasswordRecord(null);
+ outputFile.write(pw);
+
+ Prot4RevRecord p4r = new Prot4RevRecord(false);
+ outputFile.write(p4r);
+
+ Prot4RevPassRecord p4rp = new Prot4RevPassRecord();
+ outputFile.write(p4rp);
+
+ // If no sheet is identified as being selected, then select
+ // the first one
+ boolean sheetSelected = false;
+ WritableSheetImpl wsheet = null;
+ int selectedSheetIndex = 0;
+ for (int i = 0 ; i < getNumberOfSheets() && !sheetSelected ; i++)
+ {
+ wsheet = (WritableSheetImpl) getSheet(i);
+ if (wsheet.getSettings().isSelected())
+ {
+ sheetSelected = true;
+ selectedSheetIndex = i;
+ }
+ }
+
+ if (!sheetSelected)
+ {
+ wsheet = (WritableSheetImpl) getSheet(0);
+ wsheet.getSettings().setSelected(true);
+ selectedSheetIndex = 0;
+ }
+
+ Window1Record w1r = new Window1Record(selectedSheetIndex);
+ outputFile.write(w1r);
+
+ BackupRecord bkr = new BackupRecord(false);
+ outputFile.write(bkr);
+
+ HideobjRecord ho = new HideobjRecord(false);
+ outputFile.write(ho);
+
+ NineteenFourRecord nf = new NineteenFourRecord(false);
+ outputFile.write(nf);
+
+ PrecisionRecord pc = new PrecisionRecord(false);
+ outputFile.write(pc);
+
+ RefreshAllRecord rar = new RefreshAllRecord(false);
+ outputFile.write(rar);
+
+ BookboolRecord bb = new BookboolRecord(true);
+ outputFile.write(bb);
+
+ // Write out all the fonts used
+ fonts.write(outputFile);
+
+ // Write out the cell formats used within this workbook
+ formatRecords.write(outputFile);
+
+ // Write out the palette, if it exists
+ if (formatRecords.getPalette() != null)
+ {
+ outputFile.write(formatRecords.getPalette());
+ }
+
+ // Write out the uses elfs record
+ UsesElfsRecord uer = new UsesElfsRecord();
+ outputFile.write(uer);
+
+ // Write out the boundsheet records. Keep a handle to each one's
+ // position so we can write in the stream offset later
+ int[] boundsheetPos = new int[getNumberOfSheets()];
+ Sheet sheet = null;
+
+ for (int i = 0; i < getNumberOfSheets(); i++)
+ {
+ boundsheetPos[i] = outputFile.getPos();
+ sheet = getSheet(i);
+ BoundsheetRecord br = new BoundsheetRecord(sheet.getName());
+ if (sheet.getSettings().isHidden())
+ {
+ br.setHidden();
+ }
+
+ if ( ( (WritableSheetImpl) sheets.get(i)).isChartOnly())
+ {
+ br.setChartOnly();
+ }
+
+ outputFile.write(br);
+ }
+
+ if (countryRecord == null)
+ {
+ CountryCode lang =
+ CountryCode.getCountryCode(settings.getExcelDisplayLanguage());
+ if (lang == CountryCode.UNKNOWN)
+ {
+ logger.warn("Unknown country code " +
+ settings.getExcelDisplayLanguage() +
+ " using " + CountryCode.USA.getCode());
+ lang = CountryCode.USA;
+ }
+ CountryCode region =
+ CountryCode.getCountryCode(settings.getExcelRegionalSettings());
+ countryRecord = new CountryRecord(lang, region);
+ if (region == CountryCode.UNKNOWN)
+ {
+ logger.warn("Unknown country code " +
+ settings.getExcelDisplayLanguage() +
+ " using " + CountryCode.UK.getCode());
+ region = CountryCode.UK;
+ }
+ }
+
+ outputFile.write(countryRecord);
+
+ // Write out the names of any add in functions
+ if (addInFunctionNames != null && addInFunctionNames.length > 0)
+ {
+ // Write out the supbook record
+ SupbookRecord supbook = new SupbookRecord();
+ outputFile.write(supbook);
+
+ for (int i = 0 ; i < addInFunctionNames.length; i++)
+ {
+ ExternalNameRecord enr = new ExternalNameRecord(addInFunctionNames[i]);
+ outputFile.write(enr);
+ }
+ }
+
+ // Write out the external sheet record, if it exists
+ if (externSheet != null)
+ {
+ //Write out all the supbook records
+ for (int i = 0; i < supbooks.size() ; i++)
+ {
+ SupbookRecord supbook = (SupbookRecord) supbooks.get(i);
+ outputFile.write(supbook);
+ }
+ outputFile.write(externSheet);
+ }
+
+ // Write out the names, if any exists
+ if (names != null)
+ {
+ for (int i = 0 ; i < names.size() ; i++)
+ {
+ NameRecord n = (NameRecord) names.get(i);
+ outputFile.write(n);
+ }
+ }
+
+ // Write out the mso drawing group, if it exists
+ if (drawingGroup != null)
+ {
+ drawingGroup.write(outputFile);
+ }
+
+ sharedStrings.write(outputFile);
+
+ EOFRecord eof = new EOFRecord();
+ outputFile.write(eof);
+
+
+ // Write out the sheets
+ for (int i = 0; i < getNumberOfSheets(); i++)
+ {
+ // first go back and modify the offset we wrote out for the
+ // boundsheet record
+ outputFile.setData
+ (IntegerHelper.getFourBytes(outputFile.getPos()),
+ boundsheetPos[i] + 4);
+
+ wsheet = (WritableSheetImpl) getSheet(i);
+ wsheet.write();
+ }
+ }
+
+ /**
+ * Produces a writable copy of the workbook passed in by
+ * creating copies of each sheet in the specified workbook and adding
+ * them to its own record
+ *
+ * @param w the workbook to copy
+ */
+ private void copyWorkbook(Workbook w)
+ {
+ int numSheets = w.getNumberOfSheets();
+ wbProtected = w.isProtected();
+ Sheet s = null;
+ WritableSheetImpl ws = null;
+ for (int i = 0 ; i < numSheets; i++)
+ {
+ s = w.getSheet(i);
+ ws = (WritableSheetImpl) createSheet(s.getName(),i, false);
+ ws.copy(s);
+ }
+ }
+
+ /**
+ * Copies the specified sheet and places it at the index
+ * specified by the parameter
+ *
+ * @param s the index of the sheet to copy
+ * @param name the name of the new sheet
+ * @param index the position of the new sheet
+ */
+ public void copySheet(int s, String name, int index)
+ {
+ WritableSheet sheet = getSheet(s);
+ WritableSheetImpl ws = (WritableSheetImpl) createSheet(name, index);
+ ws.copy(sheet);
+ }
+
+ /**
+ * Copies the specified sheet and places it at the index
+ * specified by the parameter
+ *
+ * @param s the name of the sheet to copy
+ * @param name the name of the new sheet
+ * @param index the position of the new sheet
+ */
+ public void copySheet(String s, String name, int index)
+ {
+ WritableSheet sheet = getSheet(s);
+ WritableSheetImpl ws = (WritableSheetImpl) createSheet(name, index);
+ ws.copy(sheet);
+ }
+
+ /**
+ * Indicates whether or not this workbook is protected
+ *
+ * @param prot protected flag
+ */
+ public void setProtected(boolean prot)
+ {
+ wbProtected = prot;
+ }
+
+ /**
+ * Rationalizes the cell formats, and then passes the resultant XF index
+ * mappings to each sheet in turn
+ */
+ private void rationalize()
+ {
+ IndexMapping fontMapping = formatRecords.rationalizeFonts();
+ IndexMapping formatMapping = formatRecords.rationalizeDisplayFormats();
+ IndexMapping xfMapping = formatRecords.rationalize(fontMapping,
+ formatMapping);
+
+ WritableSheetImpl wsi = null;
+ for (int i = 0; i < sheets.size(); i++)
+ {
+ wsi = (WritableSheetImpl) sheets.get(i);
+ wsi.rationalize(xfMapping, fontMapping, formatMapping);
+ }
+ }
+
+ /**
+ * Gets the internal sheet index for a sheet name
+ *
+ * @param name the sheet name
+ * @return the internal sheet index
+ */
+ private int getInternalSheetIndex(String name)
+ {
+ int index = -1;
+ String[] names = getSheetNames();
+ for (int i = 0 ; i < names.length; i++)
+ {
+ if (name.equals(names[i]))
+ {
+ index = i;
+ break;
+ }
+ }
+
+ return index;
+ }
+
+ /**
+ * Gets the name of the external sheet specified by the index
+ *
+ * @param index the external sheet index
+ * @return the name of the external sheet
+ */
+ public String getExternalSheetName(int index)
+ {
+ int supbookIndex = externSheet.getSupbookIndex(index);
+ SupbookRecord sr = (SupbookRecord) supbooks.get(supbookIndex);
+
+ int firstTab = externSheet.getFirstTabIndex(index);
+
+ if (sr.getType() == SupbookRecord.INTERNAL)
+ {
+ // It's an internal reference - get the name from the sheets list
+ WritableSheet ws = getSheet(firstTab);
+
+ return ws.getName();
+ }
+ else if (sr.getType() == SupbookRecord.EXTERNAL)
+ {
+ String name = sr.getFileName() + sr.getSheetName(firstTab);
+ return name;
+ }
+
+ // An unknown supbook - return unkown
+ return "[UNKNOWN]";
+ }
+
+ /**
+ * Gets the name of the last external sheet specified by the index
+ *
+ * @param index the external sheet index
+ * @return the name of the external sheet
+ */
+ public String getLastExternalSheetName(int index)
+ {
+ int supbookIndex = externSheet.getSupbookIndex(index);
+ SupbookRecord sr = (SupbookRecord) supbooks.get(supbookIndex);
+
+ int lastTab = externSheet.getLastTabIndex(index);
+
+ if (sr.getType() == SupbookRecord.INTERNAL)
+ {
+ // It's an internal reference - get the name from the sheets list
+ WritableSheet ws = getSheet(lastTab);
+
+ return ws.getName();
+ }
+ else if (sr.getType() == SupbookRecord.EXTERNAL)
+ {
+ Assert.verify(false);
+ }
+
+ // An unknown supbook - return unkown
+ return "[UNKNOWN]";
+ }
+
+ /**
+ * Parsing of formulas is only supported for a subset of the available
+ * biff version, so we need to test to see if this version is acceptable
+ *
+ * @return the BOF record, which
+ */
+ public jxl.read.biff.BOFRecord getWorkbookBof()
+ {
+ return null;
+ }
+
+
+ /**
+ * Gets the index of the external sheet for the name
+ *
+ * @param sheetName
+ * @return the sheet index of the external sheet index
+ */
+ public int getExternalSheetIndex(int index)
+ {
+ if (externSheet == null)
+ {
+ return index;
+ }
+
+ Assert.verify(externSheet != null);
+
+ int firstTab = externSheet.getFirstTabIndex(index);
+
+ return firstTab;
+ }
+
+ /**
+ * Gets the index of the external sheet for the name
+ *
+ * @param sheetName
+ * @return the sheet index of the external sheet index
+ */
+ public int getLastExternalSheetIndex(int index)
+ {
+ if (externSheet == null)
+ {
+ return index;
+ }
+
+ Assert.verify(externSheet != null);
+
+ int lastTab = externSheet.getLastTabIndex(index);
+
+ return lastTab;
+ }
+
+ /**
+ * Gets the external sheet index for the sheet name
+ *
+ * @param sheetName
+ * @return the sheet index or -1 if the sheet could not be found
+ */
+ public int getExternalSheetIndex(String sheetName)
+ {
+ if (externSheet == null)
+ {
+ externSheet = new ExternalSheetRecord();
+ supbooks = new ArrayList();
+ supbooks.add(new SupbookRecord(getNumberOfSheets(), settings));
+ }
+
+ // Iterate through the sheets records
+ boolean found = false;
+ Iterator i = sheets.iterator();
+ int sheetpos = 0;
+ WritableSheetImpl s = null;
+
+ while (i.hasNext() && !found)
+ {
+ s = (WritableSheetImpl) i.next();
+
+ if (s.getName().equals(sheetName))
+ {
+ found = true;
+ }
+ else
+ {
+ sheetpos++;
+ }
+ }
+
+ if (found)
+ {
+ // Check that the supbook record at position zero is internal and
+ // contains all the sheets
+ SupbookRecord supbook = (SupbookRecord) supbooks.get(0);
+ if (supbook.getType() != SupbookRecord.INTERNAL ||
+ supbook.getNumberOfSheets() != getNumberOfSheets())
+ {
+ logger.warn("Cannot find sheet " + sheetName + " in supbook record");
+ }
+
+ return externSheet.getIndex(0, sheetpos);
+ }
+
+ // Check for square brackets
+ int closeSquareBracketsIndex = sheetName.lastIndexOf(']');
+ int openSquareBracketsIndex = sheetName.lastIndexOf('[');
+
+ if (closeSquareBracketsIndex == -1 ||
+ openSquareBracketsIndex == -1)
+ {
+ return -1;
+ }
+
+ String worksheetName = sheetName.substring(closeSquareBracketsIndex+1);
+ String workbookName = sheetName.substring(openSquareBracketsIndex+1,
+ closeSquareBracketsIndex);
+ String path = sheetName.substring(0, openSquareBracketsIndex);
+ String fileName = path + workbookName;
+
+ boolean supbookFound = false;
+ SupbookRecord externalSupbook = null;
+ int supbookIndex = -1;
+ for (int ind = 0; ind < supbooks.size() && !supbookFound ; ind++)
+ {
+ externalSupbook = (SupbookRecord) supbooks.get(ind);
+ if (externalSupbook.getType() == SupbookRecord.EXTERNAL &&
+ externalSupbook.getFileName().equals(fileName))
+ {
+ supbookFound = true;
+ supbookIndex = ind;
+ }
+ }
+
+ if (!supbookFound)
+ {
+ externalSupbook = new SupbookRecord(fileName, settings);
+ supbookIndex = supbooks.size();
+ supbooks.add(externalSupbook);
+ }
+
+ int sheetIndex = externalSupbook.getSheetIndex(worksheetName);
+
+ return externSheet.getIndex(supbookIndex, sheetIndex);
+ }
+
+ /**
+ * Gets the last external sheet index for the sheet name
+ * @param sheetName
+ * @return the sheet index or -1 if the sheet could not be found
+ */
+ public int getLastExternalSheetIndex(String sheetName)
+ {
+ if (externSheet == null)
+ {
+ externSheet = new ExternalSheetRecord();
+ supbooks = new ArrayList();
+ supbooks.add(new SupbookRecord(getNumberOfSheets(), settings));
+ }
+
+ // Iterate through the sheets records
+ boolean found = false;
+ Iterator i = sheets.iterator();
+ int sheetpos = 0;
+ WritableSheetImpl s = null;
+
+ while (i.hasNext() && !found)
+ {
+ s = (WritableSheetImpl) i.next();
+
+ if (s.getName().equals(sheetName))
+ {
+ found = true;
+ }
+ else
+ {
+ sheetpos++;
+ }
+ }
+
+ if (!found)
+ {
+ return -1;
+ }
+
+ // Check that the supbook record at position zero is internal and contains
+ // all the sheets
+ SupbookRecord supbook = (SupbookRecord) supbooks.get(0);
+ Assert.verify(supbook.getType() == SupbookRecord.INTERNAL &&
+ supbook.getNumberOfSheets() == getNumberOfSheets());
+
+ return externSheet.getIndex(0, sheetpos);
+ }
+
+ /**
+ * Sets the RGB value for the specified colour for this workbook
+ *
+ * @param c the colour whose RGB value is to be overwritten
+ * @param r the red portion to set (0-255)
+ * @param g the green portion to set (0-255)
+ * @param b the blue portion to set (0-255)
+ */
+ public void setColourRGB(Colour c, int r, int g, int b)
+ {
+ formatRecords.setColourRGB(c,r,g,b);
+ }
+
+ /**
+ * Accessor for the RGB value for the specified colour
+ *
+ * @return the RGB for the specified colour
+ */
+ public RGB getColourRGB(Colour c)
+ {
+ return formatRecords.getColourRGB(c);
+ }
+
+ /**
+ * Gets the name at the specified index
+ *
+ * @param index the index into the name table
+ * @return the name of the cell
+ */
+ public String getName(int index)
+ {
+ Assert.verify(index >= 0 && index < names.size());
+ NameRecord n = (NameRecord) names.get(index);
+ return n.getName();
+ }
+
+ /**
+ * Gets the index of the name record for the name
+ *
+ * @param name
+ * @return the index in the name table
+ */
+ public int getNameIndex(String name)
+ {
+ NameRecord nr = (NameRecord) nameRecords.get(name);
+ return nr != null ? nr.getIndex() : -1;
+ }
+
+ /**
+ * Adds a cell to workbook wide range of cells which need adjustment
+ * following a row/column insert or remove
+ *
+ * @param f the cell to add to the list
+ */
+ void addRCIRCell(CellValue cv)
+ {
+ rcirCells.add(cv);
+ }
+
+ /**
+ * Called when a column is inserted on the specified sheet. Notifies all
+ * RCIR cells of this change
+ *
+ * @param s the sheet on which the column was inserted
+ * @param col the column number which was inserted
+ */
+ void columnInserted(WritableSheetImpl s, int col)
+ {
+ int externalSheetIndex = getExternalSheetIndex(s.getName());
+ for (Iterator i = rcirCells.iterator() ; i.hasNext() ;)
+ {
+ CellValue cv = (CellValue) i.next();
+ cv.columnInserted(s, externalSheetIndex, col);
+ }
+
+ // Adjust any named cells
+ if (names != null)
+ {
+ for (Iterator i = names.iterator(); i.hasNext() ;)
+ {
+ NameRecord nameRecord = (NameRecord) i.next();
+ nameRecord.columnInserted(externalSheetIndex, col);
+ }
+ }
+ }
+
+ /**
+ * Called when a column is removed on the specified sheet. Notifies all
+ * RCIR cells of this change
+ *
+ * @param s the sheet on which the column was removed
+ * @param col the column number which was removed
+ */
+ void columnRemoved(WritableSheetImpl s, int col)
+ {
+ int externalSheetIndex = getExternalSheetIndex(s.getName());
+ for (Iterator i = rcirCells.iterator() ; i.hasNext() ;)
+ {
+ CellValue cv = (CellValue) i.next();
+ cv.columnRemoved(s, externalSheetIndex, col);
+ }
+
+ // Adjust any named cells
+ ArrayList removedNames = new ArrayList();
+ if (names != null)
+ {
+ for (Iterator i = names.iterator(); i.hasNext() ;)
+ {
+ NameRecord nameRecord = (NameRecord) i.next();
+ boolean removeName = nameRecord.columnRemoved(externalSheetIndex,
+ col);
+
+ if (removeName)
+ {
+ removedNames.add(nameRecord);
+ }
+ }
+
+ // Remove any names which have been deleted
+ for (Iterator i = removedNames.iterator(); i.hasNext() ;)
+ {
+ NameRecord nameRecord = (NameRecord) i.next();
+ boolean removed = names.remove(nameRecord);
+ Assert.verify(removed, "Could not remove name " +
+ nameRecord.getName());
+ }
+ }
+ }
+
+ /**
+ * Called when a row is inserted on the specified sheet. Notifies all
+ * RCIR cells of this change
+ *
+ * @param s the sheet on which the row was inserted
+ * @param row the row number which was inserted
+ */
+ void rowInserted(WritableSheetImpl s, int row)
+ {
+ int externalSheetIndex = getExternalSheetIndex(s.getName());
+
+ // Adjust the row infos
+ for (Iterator i = rcirCells.iterator() ; i.hasNext() ;)
+ {
+ CellValue cv = (CellValue) i.next();
+ cv.rowInserted(s, externalSheetIndex, row);
+ }
+
+ // Adjust any named cells
+ if (names != null)
+ {
+ for (Iterator i = names.iterator(); i.hasNext() ;)
+ {
+ NameRecord nameRecord = (NameRecord) i.next();
+ nameRecord.rowInserted(externalSheetIndex, row);
+ }
+ }
+ }
+
+ /**
+ * Called when a row is removed on the specified sheet. Notifies all
+ * RCIR cells of this change
+ *
+ * @param s the sheet on which the row was removed
+ * @param row the row number which was removed
+ */
+ void rowRemoved(WritableSheetImpl s, int row)
+ {
+ int externalSheetIndex = getExternalSheetIndex(s.getName());
+ for (Iterator i = rcirCells.iterator() ; i.hasNext() ;)
+ {
+ CellValue cv = (CellValue) i.next();
+ cv.rowRemoved(s, externalSheetIndex, row);
+ }
+
+ // Adjust any named cells
+ ArrayList removedNames = new ArrayList();
+ if (names != null)
+ {
+ for (Iterator i = names.iterator(); i.hasNext() ;)
+ {
+ NameRecord nameRecord = (NameRecord) i.next();
+ boolean removeName = nameRecord.rowRemoved(externalSheetIndex, row);
+
+ if (removeName)
+ {
+ removedNames.add(nameRecord);
+ }
+ }
+
+ // Remove any names which have been deleted
+ for (Iterator i = removedNames.iterator(); i.hasNext() ;)
+ {
+ NameRecord nameRecord = (NameRecord) i.next();
+ boolean removed = names.remove(nameRecord);
+ Assert.verify(removed, "Could not remove name " +
+ nameRecord.getName());
+ }
+ }
+ }
+
+ /**
+ * Gets the named cell from this workbook. If the name refers to a
+ * range of cells, then the cell on the top left is returned. If
+ * the name cannot be found, null is returned
+ *
+ * @param the name of the cell/range to search for
+ * @return the cell in the top left of the range if found, NULL
+ * otherwise
+ */
+ public WritableCell findCellByName(String name)
+ {
+ NameRecord nr = (NameRecord) nameRecords.get(name);
+
+ if (nr == null)
+ {
+ return null;
+ }
+
+ NameRecord.NameRange[] ranges = nr.getRanges();
+
+ // Go and retrieve the first cell in the first range
+ int sheetIndex = getExternalSheetIndex(ranges[0].getExternalSheet());
+ WritableSheet s = getSheet(sheetIndex);
+ WritableCell cell = s.getWritableCell(ranges[0].getFirstColumn(),
+ ranges[0].getFirstRow());
+
+ return cell;
+ }
+
+ /**
+ * Gets the named range from this workbook. The Range object returns
+ * contains all the cells from the top left to the bottom right
+ * of the range.
+ * If the named range comprises an adjacent range,
+ * the Range[] will contain one object; for non-adjacent
+ * ranges, it is necessary to return an array of length greater than
+ * one.
+ * If the named range contains a single cell, the top left and
+ * bottom right cell will be the same cell
+ *
+ * @param the name of the cell/range to search for
+ * @return the range of cells
+ */
+ public Range[] findByName(String name)
+ {
+ NameRecord nr = (NameRecord) nameRecords.get(name);
+
+ if (nr == null)
+ {
+ return null;
+ }
+
+ NameRecord.NameRange[] ranges = nr.getRanges();
+
+ Range[] cellRanges = new Range[ranges.length];
+
+ for (int i = 0; i < ranges.length ; i++)
+ {
+ cellRanges[i] = new RangeImpl
+ (this,
+ getExternalSheetIndex(ranges[i].getExternalSheet()),
+ ranges[i].getFirstColumn(),
+ ranges[i].getFirstRow(),
+ getLastExternalSheetIndex(ranges[i].getExternalSheet()),
+ ranges[i].getLastColumn(),
+ ranges[i].getLastRow());
+ }
+
+ return cellRanges;
+ }
+
+ /**
+ * Adds a drawing to this workbook
+ *
+ * @param d the drawing to add
+ */
+ void addDrawing(DrawingGroupObject d)
+ {
+ if (drawingGroup == null)
+ {
+ drawingGroup = new DrawingGroup(Origin.WRITE);
+ }
+
+ drawingGroup.add(d);
+ }
+
+ /**
+ * Removes a drawing from this workbook
+ *
+ * @param d the drawing to remove
+ */
+ void removeDrawing(Drawing d)
+ {
+ Assert.verify(drawingGroup != null);
+
+ drawingGroup.remove(d);
+ }
+
+ /**
+ * Accessor for the drawing group
+ *
+ * @return the drawing group
+ */
+ DrawingGroup getDrawingGroup()
+ {
+ return drawingGroup;
+ }
+
+ /**
+ * Create a drawing group for this workbook - used when importing sheets
+ * which contain drawings, but this workbook doesn't.
+ * We can't subsume this into the getDrawingGroup() method because the
+ * null-ness of the return value is used elsewhere to determine the
+ * origin of the workbook
+ */
+ DrawingGroup createDrawingGroup()
+ {
+ if (drawingGroup == null)
+ {
+ drawingGroup = new DrawingGroup(Origin.WRITE);
+ }
+
+ return drawingGroup;
+ }
+
+ /**
+ * Gets the named ranges
+ *
+ * @return the list of named cells within the workbook
+ */
+ public String[] getRangeNames()
+ {
+ if (names == null)
+ {
+ return new String[0];
+ }
+
+ String[] n = new String[names.size()];
+ for (int i = 0 ; i < names.size() ; i++)
+ {
+ NameRecord nr = (NameRecord) names.get(i);
+ n[i] = nr.getName();
+ }
+
+ return n;
+ }
+
+ /**
+ * Removes the specified named range from the workbook
+ *
+ * @param name the name to remove
+ */
+ public void removeRangeName(String name)
+ {
+ int pos = 0;
+ boolean found = false;
+ for (Iterator i = names.iterator(); i.hasNext() && !found ;)
+ {
+ NameRecord nr = (NameRecord) i.next();
+ if (nr.getName().equals(name))
+ {
+ found = true;
+ }
+ else
+ {
+ pos++;
+ }
+ }
+
+ // Remove the name from the list of names and the associated hashmap
+ // of names (used to retrieve the name index). If the name cannot
+ // be found, a warning is displayed
+ if (found)
+ {
+ names.remove(pos);
+ if (nameRecords.remove(name) == null)
+ {
+ logger.warn("Could not remove " + name + " from index lookups");
+ }
+ }
+ }
+
+ /**
+ * Accessor for the common styles
+ *
+ * @return the standard styles for this workbook
+ */
+ Styles getStyles()
+ {
+ return styles;
+ }
+
+ /**
+ * Add new named area to this workbook with the given information.
+ *
+ * @param name name to be created.
+ * @param sheet sheet containing the name
+ * @param firstCol first column this name refers to.
+ * @param firstRow first row this name refers to.
+ * @param lastCol last column this name refers to.
+ * @param lastRow last row this name refers to.
+ */
+ public void addNameArea(String name,
+ WritableSheet sheet,
+ int firstCol,
+ int firstRow,
+ int lastCol,
+ int lastRow)
+ {
+ addNameArea(name, sheet, firstCol, firstRow, lastCol, lastRow, true);
+ }
+
+ /**
+ * Add new named area to this workbook with the given information.
+ *
+ * @param name name to be created.
+ * @param sheet sheet containing the name
+ * @param firstCol first column this name refers to.
+ * @param firstRow first row this name refers to.
+ * @param lastCol last column this name refers to.
+ * @param lastRow last row this name refers to.
+ * @param global TRUE if this is a global name, FALSE if this is tied to
+ * the sheet
+ */
+ void addNameArea(String name,
+ WritableSheet sheet,
+ int firstCol,
+ int firstRow,
+ int lastCol,
+ int lastRow,
+ boolean global)
+ {
+ if (names == null)
+ {
+ names = new ArrayList();
+ }
+
+ int externalSheetIndex = getExternalSheetIndex(sheet.getName());
+
+ // Create a new name record.
+ NameRecord nr =
+ new NameRecord(name,
+ names.size(),
+ externalSheetIndex,
+ firstRow, lastRow,
+ firstCol, lastCol,
+ global);
+
+ // Add new name to name array.
+ names.add(nr);
+
+ // Add new name to name hash table.
+ nameRecords.put(name, nr);
+ }
+
+ /**
+ * Add new named area to this workbook with the given information.
+ *
+ * @param name name to be created.
+ * @param sheet sheet containing the name
+ * @param firstCol first column this name refers to.
+ * @param firstRow first row this name refers to.
+ * @param lastCol last column this name refers to.
+ * @param lastRow last row this name refers to.
+ * @param global TRUE if this is a global name, FALSE if this is tied to
+ * the sheet
+ */
+ void addNameArea(BuiltInName name,
+ WritableSheet sheet,
+ int firstCol,
+ int firstRow,
+ int lastCol,
+ int lastRow,
+ boolean global)
+ {
+ if (names == null)
+ {
+ names = new ArrayList();
+ }
+
+ int index = getInternalSheetIndex(sheet.getName());
+ int externalSheetIndex = getExternalSheetIndex(sheet.getName());
+
+ // Create a new name record.
+ NameRecord nr =
+ new NameRecord(name,
+ index,
+ externalSheetIndex,
+ firstRow, lastRow,
+ firstCol, lastCol,
+ global);
+
+ // Add new name to name array.
+ names.add(nr);
+
+ // Add new name to name hash table.
+ nameRecords.put(name, nr);
+ }
+
+ /**
+ * Add new named area to this workbook with the given information.
+ *
+ * @param name name to be created.
+ * @param sheet sheet containing the name
+ * @param firstCol first column this name refers to.
+ * @param firstRow first row this name refers to.
+ * @param lastCol last column this name refers to.
+ * @param lastRow last row this name refers to.
+ * @param firstCol2 first column this name refers to.
+ * @param firstRow2 first row this name refers to.
+ * @param lastCol2 last column this name refers to.
+ * @param lastRow2 last row this name refers to.
+ * @param global TRUE if this is a global name, FALSE if this is tied to
+ * the sheet
+ */
+ void addNameArea(BuiltInName name,
+ WritableSheet sheet,
+ int firstCol,
+ int firstRow,
+ int lastCol,
+ int lastRow,
+ int firstCol2,
+ int firstRow2,
+ int lastCol2,
+ int lastRow2,
+ boolean global)
+ {
+ if (names == null)
+ {
+ names = new ArrayList();
+ }
+
+ int index = getInternalSheetIndex(sheet.getName());
+ int externalSheetIndex = getExternalSheetIndex(sheet.getName());
+
+ // Create a new name record.
+ NameRecord nr =
+ new NameRecord(name,
+ index,
+ externalSheetIndex,
+ firstRow2, lastRow2,
+ firstCol2, lastCol2,
+ firstRow, lastRow,
+ firstCol, lastCol,
+ global);
+
+ // Add new name to name array.
+ names.add(nr);
+
+ // Add new name to name hash table.
+ nameRecords.put(name, nr);
+ }
+
+ /**
+ * Accessor for the workbook settings
+ */
+ WorkbookSettings getSettings()
+ {
+ return settings;
+ }
+
+ /**
+ * Returns the cell for the specified location eg. "Sheet1!A4".
+ * This is identical to using the CellReferenceHelper with its
+ * associated performance overheads, consequently it should
+ * be use sparingly
+ *
+ * @param loc the cell to retrieve
+ * @return the cell at the specified location
+ */
+ public WritableCell getWritableCell(String loc)
+ {
+ WritableSheet s = getSheet(CellReferenceHelper.getSheet(loc));
+ return s.getWritableCell(loc);
+ }
+
+ /**
+ * Imports a sheet from a different workbook. Does a deep copy on all
+ * elements within that sheet
+ *
+ * @param name the name of the new sheet
+ * @param index the position for the new sheet within this workbook
+ * @param sheet the sheet (from another workbook) to merge into this one
+ * @return the new sheet
+ */
+ public WritableSheet importSheet(String name, int index, Sheet sheet)
+ {
+ WritableSheet ws = createSheet(name, index);
+ ((WritableSheetImpl) ws).importSheet(sheet);
+
+ return ws;
+ }
+
+}
+
+
+
+
+
Index: 3rdParty_sources/jexcelapi/jxl/write/biff/WriteAccessRecord.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jexcelapi/jxl/write/biff/WriteAccessRecord.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jexcelapi/jxl/write/biff/WriteAccessRecord.java 17 Aug 2012 14:51:10 -0000 1.1
@@ -0,0 +1,72 @@
+/*********************************************************************
+*
+* Copyright (C) 2002 Andrew Khan
+*
+* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+***************************************************************************/
+
+package jxl.write.biff;
+
+import jxl.Workbook;
+import jxl.biff.StringHelper;
+import jxl.biff.Type;
+import jxl.biff.WritableRecordData;
+
+/**
+ * The name used when Excel was installed. When writing worksheets, this
+ * is hard coded as Java Excel API
+ */
+class WriteAccessRecord extends WritableRecordData
+{
+ /**
+ * The data to output to file
+ */
+ private byte[] data;
+
+ // String of length 112 characters
+ /**
+ * The author of this workbook (ie. the Java Excel API)
+ */
+ private final static String authorString =
+ "Java Excel API";
+
+ /**
+ * Constructor
+ */
+ public WriteAccessRecord()
+ {
+ super(Type.WRITEACCESS);
+
+ data = new byte[112];
+ String astring = authorString + " v" + Workbook.getVersion();
+ StringHelper.getBytes(astring, data, 0);
+
+ // Pad out the record with space characters
+ for (int i = astring.length() ; i < data.length ;i++)
+ {
+ data[i] = 0x20;
+ }
+ }
+
+ /**
+ * Gets the data for output to file
+ *
+ * @return the binary data
+ */
+ public byte[] getData()
+ {
+ return data;
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/Address.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/Address.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/Address.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,27 @@
+// $Id: Address.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+
+package org.jgroups;
+
+import org.jgroups.util.Streamable;
+
+import java.io.Externalizable;
+
+
+
+/**
+ * Abstract address. Used to identify members on a group to send messages to.
+ * Addresses are mostly generated by the bottom-most (transport) layers (e.g. UDP, TCP, LOOPBACK).
+ * @author Bela Ban
+ */
+public interface Address extends Externalizable, Streamable, Comparable, Cloneable { // todo: remove Externalizable
+
+ /**
+ * Checks whether this is an address that represents multiple destinations;
+ * e.g., a class D address in the Internet.
+ * @return true if this is a multicast address, false if it is a unicast address
+ */
+ boolean isMulticastAddress();
+
+ /** Returns serialized size of this address */
+ int size();
+}
Index: 3rdParty_sources/jgroups/org/jgroups/BlockEvent.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/BlockEvent.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/BlockEvent.java 17 Aug 2012 14:51:03 -0000 1.1
@@ -0,0 +1,10 @@
+// $Id: BlockEvent.java,v 1.1 2012/08/17 14:51:03 marcin Exp $
+
+package org.jgroups;
+
+/**
+ * Trivial object that represents a block event.
+ */
+public class BlockEvent {
+ public String toString() {return "BlockEvent";}
+}
Index: 3rdParty_sources/jgroups/org/jgroups/Channel.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/Channel.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/Channel.java 17 Aug 2012 14:51:05 -0000 1.1
@@ -0,0 +1,567 @@
+// $Id: Channel.java,v 1.1 2012/08/17 14:51:05 marcin Exp $
+
+package org.jgroups;
+
+
+import org.apache.commons.logging.Log;
+
+import java.io.Serializable;
+import java.util.*;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+
+/**
+ A channel represents a group communication endpoint (like BSD datagram sockets). A
+ client joins a group by connecting the channel to a group address and leaves it by
+ disconnecting. Messages sent over the channel are received by all group members that
+ are connected to the same group (that is, all members that have the same group
+ address).
+
+ The FSM for a channel is roughly as follows: a channel is created
+ (unconnected ). The channel is connected to a group
+ (connected ). Messages can now be sent and received. The channel is
+ disconnected from the group (unconnected ). The channel could now be connected to a
+ different group again. The channel is closed (closed ).
+
+ Only a single sender is allowed to be connected to a channel at a time, but there can be
+ more than one channel in an application.
+
+ Messages can be sent to the group members using the send method and messages
+ can be received using receive (pull approach).
+
+ A channel instance is created using either a ChannelFactory or the public
+ constructor. Each implementation of a channel must provide a subclass of
+ Channel
and an implementation of ChannelFactory
.
+ Various degrees of sophistication in message exchange can be achieved using building
+ blocks on top of channels; e.g., light-weight groups, synchronous message invocation,
+ or remote method calls. Channels are on the same abstraction level as sockets, and
+ should really be simple to use. Higher-level abstractions are all built on top of
+ channels.
+
+ @author Bela Ban
+ @see java.net.DatagramPacket
+ @see java.net.MulticastSocket
+ */
+public abstract class Channel implements Transport {
+ public static final int BLOCK=0;
+ public static final int VIEW=1;
+ public static final int SUSPECT=2;
+ public static final int LOCAL=3;
+ public static final int GET_STATE_EVENTS=4;
+ public static final int AUTO_RECONNECT=5;
+ public static final int AUTO_GETSTATE=6;
+
+
+ protected UpHandler up_handler=null; // when set, all events are passed to it !
+ protected Set channel_listeners=null;
+ protected Receiver receiver=null;
+
+
+ protected abstract Log getLog();
+
+ /**
+ Connects the channel to a group. The client is now able to receive group
+ messages, views and block events (depending on the options set) and to send
+ messages to (all or single) group members. This is a null operation if already
+ connected.
+
+ All channels with the same name form a group, that means all messages
+ sent to the group will be received by all channels connected to the same
+ channel name.
+
+ @param cluster_name The name of the chanel to connect to.
+ @exception ChannelException The protocol stack cannot be started
+ @exception ChannelClosedException The channel is closed and therefore cannot be used any longer.
+ A new channel has to be created first.
+ @see Channel#disconnect
+ */
+ abstract public void connect(String cluster_name) throws ChannelException;
+
+
+ /**
+ * Connects the channel to a group and fetches the state
+ *
+ * @param cluster_name
+ * The name of the cluster to connect to.
+ * @param target
+ * The address of the member from which the state is to be
+ * retrieved. If it is null, the state is retrieved from coordinator is contacted.
+ * @param state_id
+ * The ID of a substate. If the full state is to be fetched, set
+ * this parameter to null
+ * @param timeout
+ * Milliseconds to wait for the state response (0 = wait indefinitely).
+ *
+ * @throws ChannelException thrown if connecting to cluster was not successful
+ * @throws StateTransferException thrown if state transfer was not successful
+ *
+ */
+ abstract public void connect(String cluster_name, Address target, String state_id, long timeout) throws ChannelException;
+
+
+ /** Disconnects the channel from the current group (if connected), leaving the group.
+ It is a null operation if not connected. It is a null operation if the channel is closed.
+
+ @see #connect(String) */
+ abstract public void disconnect();
+
+
+ /**
+ Destroys the channel and its associated resources (e.g., the protocol stack). After a channel
+ has been closed, invoking methods on it throws the ChannelClosed
exception
+ (or results in a null operation). It is a null operation if the channel is already closed.
+ If the channel is connected to a group, disconnec()t
will be called first.
+ */
+ abstract public void close();
+
+
+ /** Shuts down the channel without disconnecting if connected, stops all the threads */
+ abstract public void shutdown();
+
+
+ /**
+ Re-opens a closed channel. Throws an exception if the channel is already open. After this method
+ returns, connect() may be called to join a group. The address of this member will be different from
+ the previous incarnation.
+ */
+ public void open() throws ChannelException {
+ ;
+ }
+
+
+ /**
+ Determines whether the channel is open;
+ i.e., the protocol stack has been created (may not be connected though).
+ */
+ abstract public boolean isOpen();
+
+
+ /**
+ Determines whether the channel is connected to a group. This implies it is open. If true is returned,
+ then the channel can be used to send and receive messages.
+ */
+ abstract public boolean isConnected();
+
+
+ /**
+ * Returns the number of messages that are waiting. Those messages can be
+ * removed by {@link #receive(long)}. Note that this number could change after
+ * calling this method and before calling receive() (e.g. the latter
+ * method might be called by a different thread).
+ * @return The number of messages on the queue, or -1 if the queue/channel
+ * is closed/disconnected.
+ */
+ public int getNumMessages() {
+ return -1;
+ }
+
+ public String dumpQueue() {
+ return "";
+ }
+
+
+ /**
+ * Returns a map of statistics of the various protocols and of the channel itself.
+ * @return Map. A map where the keys are the protocols ("channel" pseudo key is
+ * used for the channel itself") and the values are property maps.
+ */
+ public abstract Map dumpStats();
+
+ /** Sends a message to a (unicast) destination. The message contains
+
+ a destination address (Address). A null
address sends the message
+ to all group members.
+ a source address. Can be left empty. Will be filled in by the protocol stack.
+ a byte buffer. The message contents.
+ several additional fields. They can be used by application programs (or patterns). E.g.
+ a message ID, a oneway
field which determines whether a response is
+ expected etc.
+
+ @param msg The message to be sent. Destination and buffer should be set. A null destination
+ means to send to all group members.
+
+ @exception ChannelNotConnectedException The channel must be connected to send messages.
+
+ @exception ChannelClosedException The channel is closed and therefore cannot be used any longer.
+ A new channel has to be created first.
+
+ */
+ abstract public void send(Message msg) throws ChannelNotConnectedException, ChannelClosedException;
+
+
+ /**
+ Helper method. Will create a Message(dst, src, obj) and use send(Message).
+ @param dst Destination address for message. If null, message will be sent to all current group members
+ @param src Source (sender's) address. If null, it will be set by the protocol's transport layer before
+ being put on the wire. Can usually be set to null.
+ @param obj Serializable object. Will be serialized into the byte buffer of the Message. If it is
+ not serializable, the byte buffer will be null.
+ */
+ abstract public void send(Address dst, Address src, Serializable obj) throws ChannelNotConnectedException,
+ ChannelClosedException;
+
+
+ /**
+ Access to event mechanism of channels. Enables to send and receive events, used by building
+ blocks to communicate with (building block) specific protocol layers. Currently useful only
+ with JChannel.
+ */
+ public void down(Event evt) {
+ }
+
+ /**
+ * Can be used instead of down() when a return value is expected. This will be removed in 3.0 when we change
+ * the signature of down() to return Object rather than void
+ * @param evt
+ * @return
+ */
+ public Object downcall(Event evt) {
+ return null;
+ }
+
+
+ /** Receives a message, a view change or a block event. By using setOpt
, the
+ type of objects to be received can be determined (e.g., not views and blocks, just
+ messages).
+
+ The possible types returned can be:
+
+ Message
. Normal message
+ Event
. All other events (used by JChannel)
+ View
. A view change.
+ BlockEvent
. A block event indicating that a flush protocol has been started, and we should not
+ send any more messages. This event should be ack'ed by calling {@link org.jgroups.Channel#blockOk()} .
+ Any messages sent after blockOk() returns might get blocked until the flush protocol has completed.
+ UnblockEvent
. An unblock event indicating that the flush protocol has completed and we can resume
+ sending messages
+ SuspectEvent
. A notification of a suspected member.
+ GetStateEvent
. The current state of the application should be
+ returned using ReturnState
.
+ SetStateEvent
. The state of a single/all members as requested previously
+ by having called Channel.getState(s).
+ ExitEvent
. Signals that this member was forced to leave the group
+ (e.g., caused by the member being suspected.) The member can rejoin the group by calling
+ open(). If the AUTO_RECONNECT is set (see setOpt()), the reconnect will be done automatically.
+
+ The instanceof
operator can be used to discriminate between different types
+ returned.
+ @param timeout Value in milliseconds. Value <= 0 means wait forever
+ @return A Message, View, BlockEvent, SuspectEvent, GetStateEvent, SetStateEvent or
+ ExitEvent, depending on what is on top of the internal queue.
+
+ @exception ChannelNotConnectedException The channel must be connected to receive messages.
+
+ @exception ChannelClosedException The channel is closed and therefore cannot be used any longer.
+ A new channel has to be created first.
+
+ @exception TimeoutException Thrown when a timeout has occurred.
+ @deprecated Use a {@link Receiver} instead
+ */
+ abstract public Object receive(long timeout) throws ChannelNotConnectedException,
+ ChannelClosedException, TimeoutException;
+
+
+ /** Returns the next message, view, block, suspect or other event without removing
+ it from the queue .
+ @param timeout Value in milliseconds. Value <= 0 means wait forever
+ @return A Message, View, BlockEvent, SuspectEvent, GetStateEvent or SetStateEvent object,
+ depending on what is on top of the internal queue.
+
+ @exception ChannelNotConnectedException The channel must be connected to receive messages.
+
+ @exception ChannelClosedException The channel is closed and therefore cannot be used any longer.
+ A new channel has to be created first.
+
+ @exception TimeoutException Thrown when a timeout has occurred.
+
+ @see #receive(long)
+ @deprecated Use a {@link Receiver} instead, this method will not be available in JGroups 3.0
+ */
+ abstract public Object peek(long timeout) throws ChannelNotConnectedException, ChannelClosedException, TimeoutException;
+
+
+ /**
+ * Gets the current view. This does not retrieve a new view, use
+ receive()
to do so. The view may only be available after a successful
+ connect()
. The result of calling this method on an unconnected channel
+ is implementation defined (may return null). Calling it on a channel that is not
+ enabled to receive view events (via setOpt
) returns
+ null
. Calling this method on a closed channel returns a null view.
+ @return The current view.
+ */
+ abstract public View getView();
+
+
+ /**
+ Returns the channel's own address. The result of calling this method on an unconnected
+ channel is implementation defined (may return null). Calling this method on a closed
+ channel returns null.
+
+ @return The channel's address. Generated by the underlying transport, and opaque.
+ Addresses can be used as destination in the Send
operation.
+ */
+ abstract public Address getLocalAddress();
+
+
+ /**
+ Returns the group address of the group of which the channel is a member. This is
+ the object that was the argument to connect()
. Calling this method on a closed
+ channel returns null
.
+ @return The group address
+ @deprecated Use {@link #getClusterName()} instead */
+ abstract public String getChannelName();
+
+ /**
+ Returns the cluster name of the group of which the channel is a member. This is
+ the object that was the argument to connect()
. Calling this method on a closed
+ channel returns null
.
+ @return The cluster name */
+ abstract public String getClusterName();
+
+
+ /**
+ When up_handler is set, all events will be passed to it directly. These will not be received
+ by the channel (except connect/disconnect, state retrieval and the like). This can be used by
+ building blocks on top of a channel; thus the channel is used as a pass-through medium, and
+ the building blocks take over some of the channel's tasks. However, tasks such as connection
+ management and state transfer is still handled by the channel.
+ */
+ public void setUpHandler(UpHandler up_handler) {
+ this.up_handler=up_handler;
+ }
+
+
+ /**
+ Allows to be notified when a channel event such as connect, disconnect or close occurs.
+ E.g. a PullPushAdapter may choose to stop when the channel is closed, or to start when
+ it is opened.
+ @deprecated Use addChannelListener() instead
+ */
+ public void setChannelListener(ChannelListener channel_listener) {
+ addChannelListener(channel_listener);
+ }
+
+ /**
+ Allows to be notified when a channel event such as connect, disconnect or close occurs.
+ E.g. a PullPushAdapter may choose to stop when the channel is closed, or to start when
+ it is opened.
+ */
+ public synchronized void addChannelListener(ChannelListener listener) {
+ if(listener == null)
+ return;
+ if(channel_listeners == null)
+ channel_listeners=new CopyOnWriteArraySet();
+ channel_listeners.add(listener);
+ }
+
+ public synchronized void removeChannelListener(ChannelListener listener) {
+ if(channel_listeners != null && listener != null)
+ channel_listeners.remove(listener);
+ }
+
+ public synchronized void clearChannelListeners() {
+ if(channel_listeners != null)
+ channel_listeners.clear();
+ }
+
+ /** Sets the receiver, which will handle all messages, view changes etc */
+ public void setReceiver(Receiver r) {
+ receiver=r;
+ }
+
+ /**
+ Sets an option. The following options are currently recognized:
+
+ BLOCK
. Turn the reception of BLOCK events on/off (value is Boolean).
+ Default is off
+ LOCAL
. Receive its own broadcast messages to the group
+ (value is Boolean). Default is on.
+ AUTO_RECONNECT
. Turn auto-reconnection on/off. If on, when a member if forced out
+ of a group (EXIT event), then we will reconnect.
+ AUTO_GETSTATE
. Turn automatic fetching of state after an auto-reconnect on/off.
+ This also sets AUTO_RECONNECT to true (if not yet set).
+
+ This method can be called on an unconnected channel. Calling this method on a
+ closed channel has no effect.
+ */
+ abstract public void setOpt(int option, Object value);
+
+
+ /**
+ Gets an option. This method can be called on an unconnected channel. Calling this
+ method on a closed channel returns null
.
+
+ @param option The option to be returned.
+ @return The object associated with an option.
+ */
+ abstract public Object getOpt(int option);
+
+ abstract public boolean flushSupported();
+
+ abstract public boolean startFlush(List flushParticipants,boolean automatic_resume);
+
+ abstract public boolean startFlush(boolean automatic_resume);
+
+ abstract public boolean startFlush(long timeout, boolean automatic_resume);
+
+ abstract public void stopFlush();
+
+ abstract public void stopFlush(List flushParticipants);
+
+
+ /** Called to acknowledge a block() (callback in MembershipListener
or
+ BlockEvent
received from call to Receive
).
+ After sending BlockOk, no messages should be sent until a new view has been received.
+ Calling this method on a closed channel has no effect.
+ */
+ abstract public void blockOk();
+
+
+ /**
+ Retrieve the state of the group. Will usually contact the oldest group member to get
+ the state. When the method returns true, a SetStateEvent
will have been
+ added to the channel's queue, causing receive()
to return the state in one of
+ the next invocations. If false, no state will be retrieved by receive()
.
+ @param target The address of the member from which the state is to be retrieved. If it is
+ null, the coordinator is contacted.
+ @param timeout Milliseconds to wait for the response (0 = wait indefinitely).
+ @return boolean True if the state was retrieved successfully, otherwise false.
+ @exception ChannelNotConnectedException The channel must be connected to receive messages.
+
+ @exception ChannelClosedException The channel is closed and therefore cannot be used
+ any longer. A new channel has to be created first.
+
+ */
+ abstract public boolean getState(Address target, long timeout)
+ throws ChannelNotConnectedException, ChannelClosedException;
+
+
+ /**
+ * Fetches a partial state identified by state_id.
+ * @param target
+ * @param state_id
+ * @param timeout
+ * @return
+ * @throws ChannelNotConnectedException
+ * @throws ChannelClosedException
+ */
+ abstract public boolean getState(Address target, String state_id, long timeout)
+ throws ChannelNotConnectedException, ChannelClosedException;
+
+ /**
+ Retrieve all states of the group members. Will contact all group members to get
+ the states. When the method returns true, a SetStateEvent
will have been
+ added to the channel's queue, causing Receive
to return the states in one of
+ the next invocations. If false, no states will be retrieved by Receive
.
+ @param targets A list of members which are contacted for states. If the list is null,
+ all the current members of the group will be contacted.
+ @param timeout Milliseconds to wait for the response (0 = wait indefinitely).
+ @return boolean True if the state was retrieved successfully, otherwise false.
+ @exception ChannelNotConnectedException The channel must be connected to
+ receive messages.
+ @exception ChannelClosedException The channel is closed and therefore cannot be used
+ any longer. A new channel has to be created first.
+ @deprecated Not really needed - we always want to get the state from a single member
+ */
+ abstract public boolean getAllStates(Vector targets, long timeout)
+ throws ChannelNotConnectedException, ChannelClosedException;
+
+
+ /**
+ * Called by the application is response to receiving a
+ * getState()
object when calling receive()
.
+ * @param state The state of the application as a byte buffer
+ * (to send over the network).
+ */
+ public abstract void returnState(byte[] state);
+
+ /** Returns a given substate (state_id of null means return entire state) */
+ public abstract void returnState(byte[] state, String state_id);
+
+ public abstract Map getInfo();
+ public abstract void setInfo(String key, Object value);
+
+
+ public static String option2String(int option) {
+ switch(option) {
+ case BLOCK:
+ return "BLOCK";
+ case VIEW:
+ return "VIEW";
+ case SUSPECT:
+ return "SUSPECT";
+ case LOCAL:
+ return "LOCAL";
+ case GET_STATE_EVENTS:
+ return "GET_STATE_EVENTS";
+ case AUTO_RECONNECT:
+ return "AUTO_RECONNECT";
+ case AUTO_GETSTATE:
+ return "AUTO_GETSTATE";
+ default:
+ return "unknown (" + option + ')';
+ }
+ }
+
+ protected void notifyChannelConnected(Channel c) {
+ if(channel_listeners == null) return;
+ for(ChannelListener channelListener: channel_listeners) {
+ try {
+ channelListener.channelConnected(c);
+ }
+ catch(Throwable t) {
+ getLog().error("exception in channelConnected() callback", t);
+ }
+ }
+ }
+
+ protected void notifyChannelDisconnected(Channel c) {
+ if(channel_listeners == null) return;
+ for(ChannelListener channelListener: channel_listeners) {
+ try {
+ channelListener.channelDisconnected(c);
+ }
+ catch(Throwable t) {
+ getLog().error("exception in channelDisonnected() callback", t);
+ }
+ }
+ }
+
+ protected void notifyChannelClosed(Channel c) {
+ if(channel_listeners == null) return;
+ for(ChannelListener channelListener: channel_listeners) {
+ try {
+ channelListener.channelClosed(c);
+ }
+ catch(Throwable t) {
+ getLog().error("exception in channelClosed() callback", t);
+ }
+ }
+ }
+
+ protected void notifyChannelShunned() {
+ if(channel_listeners == null) return;
+ for(ChannelListener channelListener: channel_listeners) {
+ try {
+ channelListener.channelShunned();
+ }
+ catch(Throwable t) {
+ getLog().error("exception in channelShunned() callback", t);
+ }
+ }
+ }
+
+ protected void notifyChannelReconnected(Address addr) {
+ if(channel_listeners == null) return;
+ for(ChannelListener channelListener: channel_listeners) {
+ try {
+ channelListener.channelReconnected(addr);
+ }
+ catch(Throwable t) {
+ getLog().error("exception in channelReconnected() callback", t);
+ }
+ }
+ }
+
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/ChannelClosedException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/ChannelClosedException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/ChannelClosedException.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,23 @@
+// $Id: ChannelClosedException.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+
+package org.jgroups;
+
+/**
+ * Thrown if an operation is attemped on a closed channel.
+ */
+public class ChannelClosedException extends ChannelException {
+
+ private static final long serialVersionUID = -5172168752255182905L;
+
+ public ChannelClosedException() {
+ super();
+ }
+
+ public ChannelClosedException(String msg) {
+ super(msg);
+ }
+
+ public String toString() {
+ return "ChannelClosedException";
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/ChannelException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/ChannelException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/ChannelException.java 17 Aug 2012 14:51:03 -0000 1.1
@@ -0,0 +1,25 @@
+// $Id: ChannelException.java,v 1.1 2012/08/17 14:51:03 marcin Exp $
+
+package org.jgroups;
+
+/**
+ * This class represents the super class for all exception types thrown by
+ * JGroups.
+ */
+public class ChannelException extends Exception {
+
+ private static final long serialVersionUID = 6041194633384856098L;
+
+ public ChannelException() {
+ super();
+ }
+
+ public ChannelException(String reason) {
+ super(reason);
+ }
+
+ public ChannelException(String reason, Throwable cause) {
+ super(reason, cause);
+ }
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/ChannelFactory.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/ChannelFactory.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/ChannelFactory.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,162 @@
+// $Id: ChannelFactory.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+
+package org.jgroups;
+
+import org.w3c.dom.Element;
+
+import java.io.File;
+import java.net.URL;
+
+/**
+ * A channel factory that removes hardwiring of calls to create JGroups
+ * channels. ChannelFactory enables client applications to use custom Channel
+ * creation methodologies.
+ *
+ * @see JChannelFactory
+ *
+ */
+public interface ChannelFactory {
+
+ /**
+ * Initializes the factory.
+ *
+ *
+ * @param properties
+ * @throws ChannelException
+ */
+ void setMultiplexerConfig(Object properties) throws Exception;
+
+ /**
+ * Initializes the factory from a file. Example: conf/stacks.xml
+ *
+ * @param properties
+ * @throws ChannelException
+ */
+ void setMultiplexerConfig(File properties) throws Exception;
+
+ void setMultiplexerConfig(Element properties) throws Exception;
+
+ void setMultiplexerConfig(URL properties) throws Exception;
+
+ void setMultiplexerConfig(String properties) throws Exception;
+
+ /**
+ * Creates an implementation of the Channel using a given stack name and
+ * registering it under a given identity.
+ *
+ *
+ * Channel has to be created with a unique application id per stack name.
+ *
+ *
+ * Provided stack name has to be one of the stacks defined in a property
+ * file that was passed to setMultiplexerConfig (e.g conf/stacks.xml). If
+ * clients attempt to create a Channel for an undefined stack name or
+ * they attempt to register a duplicate Channel per stack an Exception will be
+ * thrown.
+ *
+ *
+ *
+ * Rather than having each multiplexed channel do a separate state transfer
+ * clients can bundle state transfers for all channels created with the same
+ * ChannelFactory. First of all, clients have to create Channels with
+ * register_for_state_transfer set to true. After the last Channel that was
+ * created with register_for_state_transfer set to true connects and
+ * initiates state transfer the actual state transfer for all such channels
+ * from this ChannelFactory is executed.
+ *
+ *
+ * Using bundled state transfers is especially useful with the FLUSH
+ * protocol in a stack. Recall that each state transfer triggers a flush and
+ * thus instead of doing a separate flush for each Channel created with this
+ * ChannelFactory we execute only one flush for all state transfers.
+ *
+ *
+ * However, be aware of the implication of asynchronous nature of bundled
+ * state transfer with the respect of channel connect. Recall that each
+ * Channel after it returns from successful getState method can assume that
+ * state is available. In case of bundled state transfer, state will be set
+ * only after the last Channel registered for the bundled
+ * state transfer connects and executes getState.
+ *
+ *
+ *
+ *
+ * @param stack_name
+ * The name of the stack to be used. All stacks are defined in
+ * the configuration with which the factory is configured (see
+ * {@link #setMultiplexerConfig(Object)} for example.
+ * @param id
+ * The identifier used for multiplexing and demultiplexing
+ * (dispatching requests to one of possibly multiple receivers).
+ * Note that id needs to be a string since it will be shipped
+ * with each message. Try to pick a short string, because this is
+ * shipped with every message (overhead).
+ * @param register_for_state_transfer
+ * If set to true, after all registered listeners called
+ * either {@link Channel#connect(String, Address, String, long)} or
+ * {@link Channel#connect(String) and Channel#getState(Address, long)}
+ * successively on the returned Channel, the state for all
+ * registered listeners will be fetched and set in all listeners.
+ * @param substate_id
+ * The ID of the sub state to be retrieved. Set this to null if
+ * the entire state should be retrieved. If
+ * register_for_state_transfer is false, substate_id will be
+ * ignored
+ *
+ *
+ * @return An implementation of Channel which keeps track of the id, so that
+ * it can be attached to each message and be properly dispatched at
+ * the receiver.
+ *
+ * @see Multiplexer
+ * @see MuxChannel
+ *
+ * @throws ChannelException
+ */
+ Channel createMultiplexerChannel(String stack_name, String id, boolean register_for_state_transfer, String substate_id) throws Exception;
+
+ /**
+ * Creates an implementation of the Channel using a given stack name and
+ * registering it under a given identity.
+ *
+ *
+ * Channel has to be created with a unique application id per stack name.
+ *
+ *
+ * Provided stack name has to be one of the stacks defined in a property
+ * file that was passed to setMultiplexerConfig (e.g conf/stacks.xml). If
+ * clients attempt to create a Channel for an undefined stack name or
+ * they attempt to register a duplicate Channel per stack an Exception will be
+ * thrown.
+ *
+ *
+ *
+ * @param stack_name
+ * The name of the stack to be used. All stacks are defined in
+ * the configuration with which the factory is configured (see
+ * {@link #setMultiplexerConfig(Object)} for example.
+ * @param id
+ * The identifier used for multiplexing and demultiplexing
+ * (dispatching requests to one of possibly multiple receivers).
+ * Note that id needs to be a string since it will be shipped
+ * with each message. Try to pick a short string, because this is
+ * shipped with every message (overhead).
+ *
+ * @return An implementation of Channel which keeps track of the id, so that
+ * it can be attached to each message and be properly dispatched at
+ * the receiver.
+ *
+ * @see Multiplexer
+ * @see MuxChannel
+ *
+ * @throws ChannelException
+ */
+ Channel createMultiplexerChannel(String stack_name, String id) throws Exception;
+
+ Channel createChannel(Object props) throws ChannelException;
+
+ /** Create a new channel with the properties defined in the factory */
+ Channel createChannel() throws ChannelException;
+
+ Channel createChannel(String stack_name) throws Exception;
+}
Index: 3rdParty_sources/jgroups/org/jgroups/ChannelListener.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/ChannelListener.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/ChannelListener.java 17 Aug 2012 14:51:05 -0000 1.1
@@ -0,0 +1,16 @@
+// $Id: ChannelListener.java,v 1.1 2012/08/17 14:51:05 marcin Exp $
+
+package org.jgroups;
+
+
+/**
+ * Allows a listener to be notified when important channel events occur. For example, when
+ * a channel is closed, a PullPushAdapter can be notified, and stop accordingly.
+ */
+public interface ChannelListener {
+ void channelConnected(Channel channel);
+ void channelDisconnected(Channel channel);
+ void channelClosed(Channel channel);
+ void channelShunned();
+ void channelReconnected(Address addr);
+}
Index: 3rdParty_sources/jgroups/org/jgroups/ChannelListenerAdapter.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/ChannelListenerAdapter.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/ChannelListenerAdapter.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,23 @@
+package org.jgroups;
+
+/**
+ * Class which implements {@link org.jgroups.ChannelListener}
+ * @author Bela Ban
+ * @version $Id: ChannelListenerAdapter.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+ */
+public class ChannelListenerAdapter implements ChannelListener {
+ public void channelConnected(Channel channel) {
+ }
+
+ public void channelDisconnected(Channel channel) {
+ }
+
+ public void channelClosed(Channel channel) {
+ }
+
+ public void channelShunned() {
+ }
+
+ public void channelReconnected(Address addr) {
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/ChannelNotConnectedException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/ChannelNotConnectedException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/ChannelNotConnectedException.java 17 Aug 2012 14:51:03 -0000 1.1
@@ -0,0 +1,22 @@
+// $Id: ChannelNotConnectedException.java,v 1.1 2012/08/17 14:51:03 marcin Exp $
+
+package org.jgroups;
+
+/**
+ * Thrown if an operation is attemped on an unconnected channel.
+ */
+public class ChannelNotConnectedException extends ChannelException {
+
+ private static final long serialVersionUID = -6701630538465783064L;
+
+ public ChannelNotConnectedException() {
+ }
+
+ public ChannelNotConnectedException(String reason) {
+ super(reason);
+ }
+
+ public String toString() {
+ return "ChannelNotConnectedException";
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/Event.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/Event.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/Event.java 17 Aug 2012 14:51:03 -0000 1.1
@@ -0,0 +1,159 @@
+// $Id: Event.java,v 1.1 2012/08/17 14:51:03 marcin Exp $
+
+package org.jgroups;
+
+
+
+/**
+ * Used for inter-stack and intra-stack communication.
+ * @author Bela Ban
+ */
+public class Event {
+ public static final int MSG = 1; // arg = Message
+ public static final int CONNECT = 2; // arg = clster name (string)
+ public static final int DISCONNECT = 4; // arg = member address (Address)
+ public static final int VIEW_CHANGE = 6; // arg = View (or MergeView in case of merge)
+ public static final int SET_LOCAL_ADDRESS = 8; // arg = Address
+ public static final int SUSPECT = 9; // arg = Address of suspected member
+ public static final int BLOCK = 10; // arg = null (used by FLUSH)
+ public static final int FIND_INITIAL_MBRS = 12; // arg = JoinPromise (or null (merge2))
+ public static final int MERGE = 14; // arg = Vector of Objects
+ public static final int TMP_VIEW = 15; // arg = View
+ public static final int BECOME_SERVER = 16; // sent when client has joined group
+ public static final int GET_APPLSTATE = 17; // get state from appl (arg=StateTransferInfo)
+ public static final int GET_STATE = 19; // arg = StateTransferInfo
+ public static final int GET_STATE_OK = 20; // arg = StateTransferInfo
+ public static final int STATE_RECEIVED = 21; // arg = StateTransferInfo (with state and state_id)
+ public static final int STABLE = 30; // arg = long[] (stable seqnos for mbrs)
+ public static final int GET_DIGEST = 39; //
+ public static final int SET_DIGEST = 41; // arg = Digest
+ public static final int EXIT = 46; // received when member was forced out of the group
+ public static final int PERF = 47; // for performance measurements
+ public static final int HEARD_FROM = 50; // arg = Vector (list of Addresses)
+ public static final int UNSUSPECT = 51; // arg = Address (of unsuspected member)
+ public static final int MERGE_DIGEST = 53; // arg = Digest
+ public static final int CONFIG = 56; // arg = Map (config properties)
+ public static final int SUSPEND_STABLE = 65; // arg = Long (max_suspend_time)
+ public static final int RESUME_STABLE = 66; // arg = null
+ public static final int ENABLE_UNICASTS_TO = 67; // arg = Address (member)
+ public static final int SUSPEND = 68; // arg = HashMap (used by FLUSH)
+ public static final int RESUME = 70; // arg = null (used by FLUSH)
+ public static final int STATE_TRANSFER_INPUTSTREAM = 71; // arg=java.io.InputStream subclass
+ public static final int STATE_TRANSFER_OUTPUTSTREAM = 72; // arg=java.io.OutputStream subclass
+ public static final int STATE_TRANSFER_INPUTSTREAM_CLOSED = 73; //arg=null
+ public static final int STATE_TRANSFER_OUTPUTSTREAM_CLOSED = 74; //arg=null
+ public static final int UNBLOCK = 75; //arg=null (indicate end of flush round)
+ public static final int CLOSE_BARRIER = 76; // arg = null
+ public static final int OPEN_BARRIER = 77; // arg = null
+ public static final int REBROADCAST = 78; // arg = Digest
+ public static final int SHUTDOWN = 79; // arg = null (shutdown without closing sockets or cleaning up)
+ public static final int CONNECT_WITH_STATE_TRANSFER = 80; // arg = cluster name (string)
+ public static final int DISABLE_UNICASTS_TO = 81; // arg = Address (member)
+ public static final int START_PARTITION = 82; // arg = null;
+ public static final int STOP_PARTITION = 83; // arg = null;
+ public static final int INFO = 84; // arg = Map
+ public static final int PREPARE_VIEW = 86; // arg = View
+
+ public static final int USER_DEFINED = 1000; // arg =
+
+
+ private final int type; // type of event
+ private final Object arg; // must be serializable if used for inter-stack communication
+
+
+ public Event(int type) {
+ this.type=type;
+ this.arg=null;
+ }
+
+ public Event(int type, Object arg) {
+ this.type=type;
+ this.arg=arg;
+ }
+
+ public final int getType() {
+ return type;
+ }
+
+ /**
+ * Sets the new type
+ * @param type
+ * @deprecated in order to make an Event immutable
+ */
+ public void setType(int type) {
+ throw new IllegalAccessError("setType() has been deprecated, to make Events immutable");
+ }
+
+ public Object getArg() {
+ return arg;
+ }
+
+ public void setArg(Object arg) {
+ throw new IllegalAccessError("setArg() has been deprecated, to make Events immutable");
+ }
+
+
+
+ public static String type2String(int t) {
+ switch(t) {
+ case MSG: return "MSG";
+ case CONNECT: return "CONNECT";
+ case DISCONNECT: return "DISCONNECT";
+ case VIEW_CHANGE: return "VIEW_CHANGE";
+ case SET_LOCAL_ADDRESS: return "SET_LOCAL_ADDRESS";
+ case SUSPECT: return "SUSPECT";
+ case BLOCK: return "BLOCK";
+ case FIND_INITIAL_MBRS: return "FIND_INITIAL_MBRS";
+ case TMP_VIEW: return "TMP_VIEW";
+ case BECOME_SERVER: return "BECOME_SERVER";
+ case GET_APPLSTATE: return "GET_APPLSTATE";
+ case GET_STATE: return "GET_STATE";
+ case GET_STATE_OK: return "GET_STATE_OK";
+ case STATE_RECEIVED: return "STATE_RECEIVED";
+ case STABLE: return "STABLE";
+ case GET_DIGEST: return "GET_DIGEST";
+ case SET_DIGEST: return "SET_DIGEST";
+ case MERGE: return "MERGE"; // Added by gianlucac@tin.it to support partitions merging in GMS
+ case EXIT: return "EXIT";
+ case PERF: return "PERF";
+ case HEARD_FROM: return "HEARD_FROM";
+ case UNSUSPECT: return "UNSUSPECT";
+ case MERGE_DIGEST: return "MERGE_DIGEST";
+ case CONFIG: return "CONFIG";
+ case SUSPEND_STABLE: return "SUSPEND_STABLE";
+ case RESUME_STABLE: return "RESUME_STABLE";
+ case ENABLE_UNICASTS_TO: return "ENABLE_UNICASTS_TO";
+ case SUSPEND: return "SUSPEND";
+ case RESUME: return "RESUME";
+ case STATE_TRANSFER_INPUTSTREAM: return "STATE_TRANSFER_INPUTSTREAM";
+ case STATE_TRANSFER_OUTPUTSTREAM:return "STATE_TRANSFER_OUTPUTSTREAM";
+ case STATE_TRANSFER_INPUTSTREAM_CLOSED: return "STATE_TRANSFER_INPUTSTREAM_CLOSED";
+ case STATE_TRANSFER_OUTPUTSTREAM_CLOSED: return "STATE_TRANSFER_OUTPUTSTREAM_CLOSED";
+ case UNBLOCK: return "UNBLOCK";
+ case CLOSE_BARRIER: return "CLOSE_BARRIER";
+ case OPEN_BARRIER: return "OPEN_BARRIER";
+ case REBROADCAST: return "REBROADCAST";
+ case SHUTDOWN: return "SHUTDOWN";
+ case CONNECT_WITH_STATE_TRANSFER: return "CONNECT_WITH_STATE_TRANSFER";
+ case DISABLE_UNICASTS_TO: return "DISABLE_UNICASTS_TO";
+ case START_PARTITION: return "START_PARTITION";
+ case STOP_PARTITION: return "STOP_PARTITION";
+ case INFO: return "INFO";
+ case PREPARE_VIEW: return "PREPARE_VIEW";
+ case USER_DEFINED: return "USER_DEFINED";
+ default: return "UNDEFINED(" + t + ")";
+ }
+ }
+
+ public static final Event GET_DIGEST_EVT = new Event(Event.GET_DIGEST);
+
+ public String toString() {
+ StringBuilder ret=new StringBuilder(64);
+ ret.append("Event[type=" + type2String(type) + ", arg=" + arg + ']');
+ if(type == MSG)
+ ret.append(" (headers=").append(((Message)arg).printHeaders()).append(")");
+ return ret.toString();
+ }
+
+}
+
Index: 3rdParty_sources/jgroups/org/jgroups/ExitEvent.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/ExitEvent.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/ExitEvent.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,9 @@
+// $Id: ExitEvent.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+
+package org.jgroups;
+/**
+ * Trivial object that represents an exit event.
+ */
+public class ExitEvent {
+ public String toString() {return "ExitEvent";}
+}
Index: 3rdParty_sources/jgroups/org/jgroups/ExtendedMembershipListener.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/ExtendedMembershipListener.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/ExtendedMembershipListener.java 17 Aug 2012 14:51:03 -0000 1.1
@@ -0,0 +1,14 @@
+package org.jgroups;
+
+/**
+ * @author Bela Ban
+ * @version $Id: ExtendedMembershipListener.java,v 1.1 2012/08/17 14:51:03 marcin Exp $
+ */
+public interface ExtendedMembershipListener extends MembershipListener {
+
+ /**
+ * Called after the FLUSH protocol has unblocked previously blocked senders, and messages can be sent again. This
+ * callback only needs to be implemented if we require a notification of that.
+ */
+ void unblock();
+}
Index: 3rdParty_sources/jgroups/org/jgroups/ExtendedMessageListener.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/ExtendedMessageListener.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/ExtendedMessageListener.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,91 @@
+package org.jgroups;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ *
+ * ExtendedMessageListener
has additional callbacks for:
+ *
+ * partial state transfer - http://jira.jboss.com/jira/browse/JGRP-118
+ * streaming state transfer - http://jira.jboss.com/jira/browse/JGRP-89
+ *
+ *
+ * Application channels interested in using streaming state transfer, beside
+ * implementing this interface, have to be configured with
+ * STREAMING_STATE_TRANSFER
protocol rather than the default
+ * STATE_TRANSFER
protocol.
+ *
+ *
+ * Note:
+ *
+ * This interface will be merged with MessageListener in 3.0 (API changes)
+ *
+ * @author Bela Ban
+ * @author Vladimir Blagojevic
+ * @see org.jgroups.JChannel#getState(Address, long)
+ * @see org.jgroups.JChannel#getState(Address, String, long)
+ * @since 2.3
+ *
+ * @version $Id: ExtendedMessageListener.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+ */
+public interface ExtendedMessageListener extends MessageListener {
+
+ /**
+ * Allows an application to provide a partial state as a byte array
+ *
+ * @param state_id id of the partial state requested
+ * @return partial state for the given state_id
+ */
+ public byte[] getState(String state_id);
+
+ /**
+ * Allows an application to read a partial state indicated by state_id from
+ * a given state byte array parameter.
+ *
+ * @param state_id id of the partial state requested
+ * @param state partial state for the given state_id
+ */
+ public void setState(String state_id, byte[] state);
+
+ /**
+ * Allows an application to write a state through a provided OutputStream.
+ * An application is obligated to always close the given OutputStream reference.
+ *
+ * @param ostream the OutputStream
+ * @see OutputStream#close()
+ */
+ public void getState(OutputStream ostream);
+
+ /**
+ * Allows an application to write a partial state through a provided OutputStream.
+ * An application is obligated to always close the given OutputStream reference.
+ *
+ * @param state_id id of the partial state requested
+ * @param ostream the OutputStream
+ *
+ * @see OutputStream#close()
+ */
+ public void getState(String state_id, OutputStream ostream);
+
+
+ /**
+ * Allows an application to read a state through a provided InputStream.
+ * An application is obligated to always close the given InputStream reference.
+ *
+ * @param istream the InputStream
+ * @see InputStream#close()
+ */
+ public void setState(InputStream istream);
+
+ /**
+ * Allows an application to read a partial state through a provided InputStream.
+ * An application is obligated to always close the given InputStream reference.
+ *
+ * @param state_id id of the partial state requested
+ * @param istream the InputStream
+ *
+ * @see InputStream#close()
+ */
+ public void setState(String state_id, InputStream istream);
+}
Index: 3rdParty_sources/jgroups/org/jgroups/ExtendedReceiver.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/ExtendedReceiver.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/ExtendedReceiver.java 17 Aug 2012 14:51:05 -0000 1.1
@@ -0,0 +1,10 @@
+package org.jgroups;
+
+/**
+ * Extends Receiver, plus the partial state transfer methods.
+ * This interface will disappear (be merged with Receiver) in 3.0.
+ * @author Bela Ban
+ * @version $Id: ExtendedReceiver.java,v 1.1 2012/08/17 14:51:05 marcin Exp $
+ */
+public interface ExtendedReceiver extends Receiver, ExtendedMessageListener, ExtendedMembershipListener {
+}
Index: 3rdParty_sources/jgroups/org/jgroups/ExtendedReceiverAdapter.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/ExtendedReceiverAdapter.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/ExtendedReceiverAdapter.java 17 Aug 2012 14:51:05 -0000 1.1
@@ -0,0 +1,57 @@
+package org.jgroups;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.jgroups.util.Util;
+
+/**
+ * @author Bela Ban
+ * @version $Id: ExtendedReceiverAdapter.java,v 1.1 2012/08/17 14:51:05 marcin Exp $
+ */
+public class ExtendedReceiverAdapter implements ExtendedReceiver {
+ public byte[] getState(String state_id) {
+ return null;
+ }
+
+ public void setState(String state_id, byte[] state) {
+ }
+
+ public void receive(Message msg) {
+ }
+
+ public byte[] getState() {
+ return null;
+ }
+
+ public void setState(byte[] state) {
+ }
+
+ public void viewAccepted(View new_view) {
+ }
+
+ public void suspect(Address suspected_mbr) {
+ }
+
+ public void block() {
+ }
+
+ public void unblock() {
+ }
+
+ public void getState(OutputStream ostream) {
+ Util.close(ostream);
+ }
+
+ public void getState(String state_id, OutputStream ostream) {
+ Util.close(ostream);
+ }
+
+ public void setState(InputStream istream) {
+ Util.close(istream);
+ }
+
+ public void setState(String state_id, InputStream istream) {
+ Util.close(istream);
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/GetStateEvent.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/GetStateEvent.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/GetStateEvent.java 17 Aug 2012 14:51:03 -0000 1.1
@@ -0,0 +1,23 @@
+// $Id: GetStateEvent.java,v 1.1 2012/08/17 14:51:03 marcin Exp $
+
+package org.jgroups;
+
+/**
+ * Represents a GetState event.
+ * Gives access to the requestor.
+ */
+public class GetStateEvent {
+ Object requestor=null;
+ String state_id=null;
+
+ public GetStateEvent(Object requestor, String state_id) {
+ this.requestor=requestor;
+ this.state_id=state_id;
+ }
+
+ public Object getRequestor() {return requestor;}
+
+ public String getStateId() {return state_id;}
+
+ public String toString() {return "GetStateEvent[requestor=" + requestor + ", state_id=" + state_id + ']';}
+}
Index: 3rdParty_sources/jgroups/org/jgroups/Global.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/Global.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/Global.java 17 Aug 2012 14:51:03 -0000 1.1
@@ -0,0 +1,102 @@
+package org.jgroups;
+
+/**
+ * Globals used by JGroups packages.
+ *
+ * @author Bela Ban Mar 29, 2004
+ * @version $Id: Global.java,v 1.1 2012/08/17 14:51:03 marcin Exp $
+ */
+public class Global {
+ /** Allows for conditional compilation; e.g., if(log.isTraceEnabled()) if(log.isInfoEnabled()) log.info(...) would be removed from the code
+ (if recompiled) when this flag is set to false. Therefore, code that should be removed from the final
+ product should use if(log.isTraceEnabled()) rather than .
+ */
+ public static final boolean debug=false;
+
+ public static final String THREAD_PREFIX=" (channel=";
+
+ public static final int BYTE_SIZE = Byte.SIZE / 8; // 1
+ public static final int SHORT_SIZE = Short.SIZE / 8; // 2
+ public static final int INT_SIZE = Integer.SIZE / 8; // 4
+ public static final int LONG_SIZE = Long.SIZE / 8; // 8
+
+ public static final Object NULL=new Object();
+
+ public static final String BIND_ADDR="jgroups.bind_addr";
+ public static final String BIND_ADDR_OLD="bind.address";
+ public static final String BIND_INTERFACE="jgroups.bind_interface";
+ public static final String IGNORE_BIND_ADDRESS_PROPERTY="jgroups.ignore.bind_addr";
+ public static final String IGNORE_BIND_ADDRESS_PROPERTY_OLD="ignore.bind.address";
+ public static final String MARSHALLING_COMPAT="jgroups.marshalling.compatible";
+
+ public static final String TCPPING_INITIAL_HOSTS="jgroups.tcpping.initial_hosts";
+
+ public static final String UDP_MCAST_ADDR="jgroups.udp.mcast_addr";
+ public static final String UDP_MCAST_PORT="jgroups.udp.mcast_port";
+ public static final String UDP_IP_TTL="jgroups.udp.ip_ttl";
+
+ public static final String MPING_MCAST_ADDR="jgroups.mping.mcast_addr";
+ public static final String MPING_MCAST_PORT="jgroups.mping.mcast_port";
+ public static final String MPING_IP_TTL="jgroups.mping.ip_ttl";
+
+ public static final String MAGIC_NUMBER_FILE="jgroups.conf.magic_number_file";
+ public static final String RESOLVE_DNS="jgroups.resolve_dns";
+
+ public static final String CHANNEL_LOCAL_ADDR_TIMEOUT="jgroups.channel.local_addr_timeout";
+
+ public static final String SCHEDULER_MAX_THREADS="jgroups.scheduler.max_threads";
+
+ public static final String TIMER_NUM_THREADS="jgroups.timer.num_threads";
+
+ public static final String MUX_ENABLED="jgroups.mux.enabled";
+ public static final String MUX_MIN_THREADS="jgroups.mux.min_threads";
+ public static final String MUX_MAX_THREADS="jgroups.mux.max_threads";
+ public static final String MUX_KEEPALIVE="jgroups.mux.keepalive_time";
+
+
+ public static final String SINGLETON_NAME="singleton_name";
+
+ public static final long THREADPOOL_SHUTDOWN_WAIT_TIME=3000;
+ public static final long THREAD_SHUTDOWN_WAIT_TIME=300;
+ public static final String DUMMY="dummy-";
+
+
+ public static final int IPV4_SIZE=4;
+ public static final int IPV6_SIZE=16;
+
+ public static boolean getPropertyAsBoolean(String property, boolean defaultValue) {
+ boolean result=defaultValue;
+ try {
+ String tmp=System.getProperty(property);
+ if(tmp != null)
+ result=Boolean.parseBoolean(tmp);
+ }
+ catch(Throwable t) {
+ }
+ return result;
+ }
+
+ public static long getPropertyAsLong(String property, long defaultValue) {
+ long result=defaultValue;
+ try {
+ String tmp=System.getProperty(property);
+ if(tmp != null)
+ result=Long.parseLong(tmp);
+ }
+ catch(Throwable t) {
+ }
+ return result;
+ }
+
+ public static int getPropertyAsInteger(String property, int defaultValue) {
+ int result=defaultValue;
+ try {
+ String tmp=System.getProperty(property);
+ if(tmp != null)
+ result=Integer.parseInt(tmp);
+ }
+ catch(Throwable t) {
+ }
+ return result;
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/Header.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/Header.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/Header.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,45 @@
+// $Id: Header.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+
+package org.jgroups;
+
+import java.io.Externalizable;
+
+
+/**
+ Abstract base class for all headers to be added to a Message.
+ @author Bela Ban
+ */
+public abstract class Header implements Externalizable {
+ public static final int HDR_OVERHEAD=100; // estimated size of a header (used to estimate the size of the entire msg)
+
+
+ public Header() {
+
+ }
+
+
+ /**
+ * To be implemented by subclasses. Return the size of this object for the serialized version of it.
+ * I.e. how many bytes this object takes when flattened into a buffer. This may be different for each instance,
+ * or can be the same. This may also just be an estimation. E.g. FRAG uses it on Message to determine whether
+ * or not to fragment the message. Fragmentation itself will be accurate, because the entire message will actually
+ * be serialized into a byte buffer, so we can determine the exact size.
+ */
+ public int size() {
+ return HDR_OVERHEAD;
+ }
+
+// public void writeTo(DataOutputStream out) throws IOException {
+// ;
+// }
+//
+// public void readFrom(DataInputStream in) throws IOException, IllegalAccessException, InstantiationException {
+// ;
+// }
+
+
+ public String toString() {
+ return '[' + getClass().getName() + " Header]";
+ }
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/JChannel.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/JChannel.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/JChannel.java 17 Aug 2012 14:51:03 -0000 1.1
@@ -0,0 +1,2078 @@
+package org.jgroups;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jgroups.conf.ConfiguratorFactory;
+import org.jgroups.conf.ProtocolStackConfigurator;
+import org.jgroups.stack.IpAddress;
+import org.jgroups.stack.ProtocolStack;
+import org.jgroups.stack.StateTransferInfo;
+import org.jgroups.util.*;
+import org.jgroups.protocols.TP;
+import org.w3c.dom.Element;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Exchanger;
+
+/**
+ * JChannel is a pure Java implementation of Channel.
+ * When a JChannel object is instantiated it automatically sets up the
+ * protocol stack.
+ *
+ * Properties
+ *
+ * Properties are used to configure a channel, and are accepted in
+ * several forms; the String form is described here.
+ * A property string consists of a number of properties separated by
+ * colons. For example:
+ *
+ *
"<prop1>(arg1=val1):<prop2>(arg1=val1;arg2=val2):<prop3>:<propn>"
+ *
+ * Each property relates directly to a protocol layer, which is
+ * implemented as a Java class. When a protocol stack is to be created
+ * based on the above property string, the first property becomes the
+ * bottom-most layer, the second one will be placed on the first, etc.:
+ * the stack is created from the bottom to the top, as the string is
+ * parsed from left to right. Each property has to be the name of a
+ * Java class that resides in the
+ * {@link org.jgroups.protocols} package.
+ *
+ * Note that only the base name has to be given, not the fully specified
+ * class name (e.g., UDP instead of org.jgroups.protocols.UDP).
+ *
+ * Each layer may have 0 or more arguments, which are specified as a
+ * list of name/value pairs in parentheses directly after the property.
+ * In the example above, the first protocol layer has 1 argument,
+ * the second 2, the third none. When a layer is created, these
+ * properties (if there are any) will be set in a layer by invoking
+ * the layer's setProperties() method
+ *
+ * As an example the property string below instructs JGroups to create
+ * a JChannel with protocols UDP, PING, FD and GMS:
+ *
"UDP(mcast_addr=228.10.9.8;mcast_port=5678):PING:FD:GMS"
+ *
+ * The UDP protocol layer is at the bottom of the stack, and it
+ * should use mcast address 228.10.9.8. and port 5678 rather than
+ * the default IP multicast address and port. The only other argument
+ * instructs FD to output debug information while executing.
+ * Property UDP refers to a class {@link org.jgroups.protocols.UDP},
+ * which is subsequently loaded and an instance of which is created as protocol layer.
+ * If any of these classes are not found, an exception will be thrown and
+ * the construction of the stack will be aborted.
+ *
+ * @author Bela Ban
+ * @version $Id: JChannel.java,v 1.1 2012/08/17 14:51:03 marcin Exp $
+ */
+public class JChannel extends Channel {
+
+ /**
+ * The default protocol stack used by the default constructor.
+ */
+ public static final String DEFAULT_PROTOCOL_STACK="udp.xml";
+
+ static final String FORCE_PROPS="force.properties";
+
+ /* the protocol stack configuration string */
+ private String props=null;
+
+ /*the address of this JChannel instance*/
+ private Address local_addr=null;
+ /*the channel (also know as group) name*/
+ private String cluster_name=null; // group name
+ /*the latest view of the group membership*/
+ private View my_view=null;
+ /*the queue that is used to receive messages (events) from the protocol stack*/
+ private final Queue mq=new Queue();
+ /*the protocol stack, used to send and receive messages from the protocol stack*/
+ private ProtocolStack prot_stack=null;
+
+ /** Thread responsible for closing a channel and potentially reconnecting to it (e.g., when shunned). */
+ protected CloserThread closer=null;
+
+ /** To wait until a local address has been assigned */
+ private final Promise
local_addr_promise=new Promise();
+
+ private final Promise state_promise=new Promise();
+
+ private final Exchanger applstate_exchanger=new Exchanger();
+
+ private final Promise flush_unblock_promise=new Promise();
+
+ /** wait until we have a non-null local_addr */
+ private long LOCAL_ADDR_TIMEOUT=30000; //=Long.parseLong(System.getProperty("local_addr.timeout", "30000"));
+ /*if the states is fetched automatically, this is the default timeout, 5 secs*/
+ private static final long GET_STATE_DEFAULT_TIMEOUT=5000;
+ /*if FLUSH is used channel waits for UNBLOCK event, this is the default timeout, 5 secs*/
+ private static final long FLUSH_UNBLOCK_TIMEOUT=5000;
+ /*flag to indicate whether to receive blocks, if this is set to true, receive_views is set to true*/
+ private boolean receive_blocks=false;
+ /*flag to indicate whether to receive local messages
+ *if this is set to false, the JChannel will not receive messages sent by itself*/
+ private boolean receive_local_msgs=true;
+ /*flag to indicate whether the channel will reconnect (reopen) when the exit message is received*/
+ private boolean auto_reconnect=true;
+ /*flag t indicate whether the state is supposed to be retrieved after the channel is reconnected
+ *setting this to true, automatically forces auto_reconnect to true*/
+ private boolean auto_getstate=false;
+ /*channel connected flag*/
+ protected volatile boolean connected=false;
+
+ /*channel closed flag*/
+ protected volatile boolean closed=false; // close() has been called, channel is unusable
+
+ /** True if a state transfer protocol is available, false otherwise */
+ private boolean state_transfer_supported=false; // set by CONFIG event from STATE_TRANSFER protocol
+
+ /** True if a flush protocol is available, false otherwise */
+ private volatile boolean flush_supported=false; // set by CONFIG event from FLUSH protocol
+
+ /** Provides storage for arbitrary objects. Protocols can send up CONFIG events, and all key-value pairs of
+ * a CONFIG event will be added to additional_data. On reconnect, a CONFIG event will be sent down by the channel,
+ * containing all key-value pairs of additional_data
+ */
+ protected final Map additional_data=new HashMap();
+
+ protected final ConcurrentMap info=new ConcurrentHashMap();
+
+ protected final Log log=LogFactory.getLog(getClass());
+
+ /** Collect statistics */
+ protected boolean stats=true;
+
+ protected long sent_msgs=0, received_msgs=0, sent_bytes=0, received_bytes=0;
+
+ private final TP.ProbeHandler probe_handler=new MyProbeHandler();
+
+
+
+ /** Used by subclass to create a JChannel without a protocol stack, don't use as application programmer */
+ protected JChannel(boolean no_op) {
+ ;
+ }
+
+ /**
+ * Constructs a JChannel
instance with the protocol stack
+ * specified by the DEFAULT_PROTOCOL_STACK
member.
+ *
+ * @throws ChannelException if problems occur during the initialization of
+ * the protocol stack.
+ */
+ public JChannel() throws ChannelException {
+ this(DEFAULT_PROTOCOL_STACK);
+ }
+
+ /**
+ * Constructs a JChannel
instance with the protocol stack
+ * configuration contained by the specified file.
+ *
+ * @param properties a file containing a JGroups XML protocol stack
+ * configuration.
+ *
+ * @throws ChannelException if problems occur during the configuration or
+ * initialization of the protocol stack.
+ */
+ public JChannel(File properties) throws ChannelException {
+ this(ConfiguratorFactory.getStackConfigurator(properties));
+ }
+
+ /**
+ * Constructs a JChannel
instance with the protocol stack
+ * configuration contained by the specified XML element.
+ *
+ * @param properties a XML element containing a JGroups XML protocol stack
+ * configuration.
+ *
+ * @throws ChannelException if problems occur during the configuration or
+ * initialization of the protocol stack.
+ */
+ public JChannel(Element properties) throws ChannelException {
+ this(ConfiguratorFactory.getStackConfigurator(properties));
+ }
+
+ /**
+ * Constructs a JChannel
instance with the protocol stack
+ * configuration indicated by the specified URL.
+ *
+ * @param properties a URL pointing to a JGroups XML protocol stack
+ * configuration.
+ *
+ * @throws ChannelException if problems occur during the configuration or
+ * initialization of the protocol stack.
+ */
+ public JChannel(URL properties) throws ChannelException {
+ this(ConfiguratorFactory.getStackConfigurator(properties));
+ }
+
+ /**
+ * Constructs a JChannel
instance with the protocol stack
+ * configuration based upon the specified properties parameter.
+ *
+ * @param properties an old style property string, a string representing a
+ * system resource containing a JGroups XML configuration,
+ * a string representing a URL pointing to a JGroups XML
+ * XML configuration, or a string representing a file name
+ * that contains a JGroups XML configuration.
+ *
+ * @throws ChannelException if problems occur during the configuration and
+ * initialization of the protocol stack.
+ */
+ public JChannel(String properties) throws ChannelException {
+ this(ConfiguratorFactory.getStackConfigurator(properties));
+ }
+
+ /**
+ * Constructs a JChannel
instance with the protocol stack
+ * configuration contained by the protocol stack configurator parameter.
+ *
+ * All of the public constructors of this class eventually delegate to this
+ * method.
+ *
+ * @param configurator a protocol stack configurator containing a JGroups
+ * protocol stack configuration.
+ *
+ * @throws ChannelException if problems occur during the initialization of
+ * the protocol stack.
+ */
+ public JChannel(ProtocolStackConfigurator configurator) throws ChannelException {
+ init(configurator);
+ }
+
+
+
+
+ /**
+ * Creates a new JChannel with the protocol stack as defined in the properties
+ * parameter. an example of this parameter is
+ * "UDP:PING:FD:STABLE:NAKACK:UNICAST:FRAG:FLUSH:GMS:VIEW_ENFORCER:STATE_TRANSFER:QUEUE"
+ * Other examples can be found in the ./conf directory
+ * @param properties the protocol stack setup; if null, the default protocol stack will be used.
+ * The properties can also be a java.net.URL object or a string that is a URL spec.
+ * The JChannel will validate any URL object and String object to see if they are a URL.
+ * In case of the parameter being a url, the JChannel will try to load the xml from there.
+ * In case properties is a org.w3c.dom.Element, the ConfiguratorFactory will parse the
+ * DOM tree with the element as its root element.
+ * @deprecated Use the constructors with specific parameter types instead.
+ */
+ public JChannel(Object properties) throws ChannelException {
+ if (properties == null)
+ properties = DEFAULT_PROTOCOL_STACK;
+
+ ProtocolStackConfigurator c=null;
+
+ try {
+ c=ConfiguratorFactory.getStackConfigurator(properties);
+ }
+ catch(Exception x) {
+ throw new ChannelException("unable to load protocol stack", x);
+ }
+ init(c);
+ }
+
+
+ /**
+ * Returns the protocol stack.
+ * Currently used by Debugger.
+ * Specific to JChannel, therefore
+ * not visible in Channel
+ */
+ public ProtocolStack getProtocolStack() {
+ return prot_stack;
+ }
+
+ protected Log getLog() {
+ return log;
+ }
+
+ /**
+ * returns the protocol stack configuration in string format.
+ * an example of this property is
+ * "UDP:PING:FD:STABLE:NAKACK:UNICAST:FRAG:FLUSH:GMS:VIEW_ENFORCER:STATE_TRANSFER:QUEUE"
+ */
+ public String getProperties() {
+ return props;
+ }
+
+ public boolean statsEnabled() {
+ return stats;
+ }
+
+ public void enableStats(boolean stats) {
+ this.stats=stats;
+ }
+
+ public void resetStats() {
+ sent_msgs=received_msgs=sent_bytes=received_bytes=0;
+ }
+
+ public long getSentMessages() {return sent_msgs;}
+ public long getSentBytes() {return sent_bytes;}
+ public long getReceivedMessages() {return received_msgs;}
+ public long getReceivedBytes() {return received_bytes;}
+ public int getNumberOfTasksInTimer() {
+ TimeScheduler timer=getTimer();
+ return timer != null? timer.size() : -1;
+ }
+
+ public int getTimerThreads() {
+ TimeScheduler timer=getTimer();
+ return timer != null? timer.getCorePoolSize() : -1;
+ }
+
+ public String dumpTimerQueue() {
+ TimeScheduler timer=getTimer();
+ return timer != null? timer.dumpTaskQueue() : "String denoting the group name. Cannot be null.
+ * @exception ChannelException The protocol stack cannot be started
+ * @exception ChannelClosedException The channel is closed and therefore cannot be used any longer.
+ * A new channel has to be created first.
+ */
+ public synchronized void connect(String cluster_name) throws ChannelException {
+ if(connected) {
+ if(log.isTraceEnabled()) log.trace("already connected to " + cluster_name);
+ return;
+ }
+
+ startStack(cluster_name);
+
+ if(cluster_name != null) { // only connect if we are not a unicast channel
+
+ Event connect_event=new Event(Event.CONNECT, cluster_name);
+ Object res=downcall(connect_event); // waits forever until connected (or channel is closed)
+ if(res != null && res instanceof Exception) { // the JOIN was rejected by the coordinator
+ stopStack(true, false);
+ init();
+ throw new ChannelException("connect() failed", (Throwable)res);
+ }
+
+ //if FLUSH is used do not return from connect() until UNBLOCK event is received
+ if(flushSupported()) {
+ try {
+ flush_unblock_promise.getResultWithTimeout(FLUSH_UNBLOCK_TIMEOUT);
+ }
+ catch (TimeoutException timeout) {
+ if(log.isWarnEnabled())
+ log.warn(local_addr + " waiting on UNBLOCK after connect() timed out");
+ }
+ }
+ }
+ connected=true;
+ notifyChannelConnected(this);
+ }
+
+
+ /**
+ * Connects this channel to a group and gets a state from a specified state
+ * provider.
+ *
+ *
+ * This method essentially invokes
+ * connect and getState methods successively.
+ * If FLUSH protocol is in channel's stack definition only one flush is executed for both connecting and
+ * fetching state rather than two flushes if we invoke connect and getState in succesion.
+ *
+ * If the channel is already connected, an error message will be printed to the error log.
+ * If the channel is closed a ChannelClosed exception will be thrown.
+ *
+ *
+ * @param cluster_name the cluster name to connect to. Cannot be null.
+ * @param target the state provider. If null state will be fetched from coordinator, unless this channel is coordinator.
+ * @param state_id the substate id for partial state transfer. If null entire state will be transferred.
+ * @param timeout the timeout for state transfer.
+ *
+ * @exception ChannelException The protocol stack cannot be started
+ * @exception ChannelException Connecting to cluster was not successful
+ * @exception ChannelClosedException The channel is closed and therefore cannot be used any longer.
+ * A new channel has to be created first.
+ * @exception StateTransferException State transfer was not successful
+ *
+ */
+ public synchronized void connect(String cluster_name,
+ Address target,
+ String state_id,
+ long timeout) throws ChannelException {
+
+ if(connected) {
+ if(log.isTraceEnabled()) log.trace("already connected to " + cluster_name);
+ return;
+ }
+
+ startStack(cluster_name);
+
+ boolean stateTransferOk=false;
+ boolean joinSuccessful=false;
+ boolean canFetchState=false;
+ // only connect if we are not a unicast channel
+ if(cluster_name != null) {
+
+ try {
+ Event connect_event=new Event(Event.CONNECT_WITH_STATE_TRANSFER, cluster_name);
+ Object res=downcall(connect_event); // waits forever until
+ // connected (or channel is
+ // closed)
+ joinSuccessful=!(res != null && res instanceof Exception);
+ if(!joinSuccessful) {
+ stopStack(true, false);
+ init();
+ throw new ChannelException("connect() failed", (Throwable)res);
+ }
+
+ connected=true;
+ notifyChannelConnected(this);
+ canFetchState=getView() != null && getView().size() > 1;
+
+ // if I am not the only member in cluster then
+ if(canFetchState) {
+ try {
+ // fetch state from target
+ stateTransferOk=getState(target, state_id, timeout, false);
+ if(!stateTransferOk) {
+ throw new StateTransferException(getLocalAddress() + " could not fetch state "
+ + state_id
+ + " from "
+ + target);
+ }
+ }
+ catch(Exception e) {
+ throw new StateTransferException(getLocalAddress() + " could not fetch state "
+ + state_id
+ + " from "
+ + target, e);
+ }
+ }
+
+ }
+ finally {
+ if(flushSupported() && canFetchState)
+ stopFlush();
+ }
+ }
+ }
+
+
+ /**
+ * Disconnects the channel if it is connected. If the channel is closed,
+ * this operation is ignored
+ * Otherwise the following actions happen in the listed order
+ *
+ * The JChannel sends a DISCONNECT event down the protocol stack
+ * Blocks until the event has returned
+ * Sends a STOP_QUEING event down the stack
+ * Stops the protocol stack by calling ProtocolStack.stop()
+ * Notifies the listener, if the listener is available
+ *
+ */
+ public synchronized void disconnect() {
+ if(closed) return;
+
+ if(connected) {
+
+ if(cluster_name != null) {
+ // Send down a DISCONNECT event, which travels down to the GMS, where a response is returned
+ Event disconnect_event=new Event(Event.DISCONNECT, local_addr);
+ down(disconnect_event); // DISCONNECT is handled by each layer
+ }
+ connected=false;
+ stopStack(true, false);
+ notifyChannelDisconnected(this);
+ init(); // sets local_addr=null; changed March 18 2003 (bela) -- prevented successful rejoining
+ }
+ }
+
+
+ /**
+ * Destroys the channel.
+ * After this method has been called, the channel us unusable.
+ * This operation will disconnect the channel and close the channel receive queue immediately
+ */
+ public synchronized void close() {
+ _close(true, true); // by default disconnect before closing channel and close mq
+ }
+
+
+ /** Shuts down the channel without disconnecting */
+ public synchronized void shutdown() {
+ down(new Event(Event.SHUTDOWN));
+ _close(false, true); // by default disconnect before closing channel and close mq
+ }
+
+ /**
+ * Opens the channel. Note that the channel is only open, but not connected .
+ * This does the following actions:
+ *
+ * Resets the receiver queue by calling Queue.reset
+ * Sets up the protocol stack by calling ProtocolStack.setup
+ * Sets the closed flag to false
+ *
+ */
+ public synchronized void open() throws ChannelException {
+ if(!closed)
+ throw new ChannelException("channel is already open");
+
+ try {
+ mq.reset();
+
+ // new stack is created on open() - bela June 12 2003
+ prot_stack=new ProtocolStack(this, props);
+ prot_stack.setup();
+ closed=false;
+ }
+ catch(Exception e) {
+ throw new ChannelException("failed to open channel" , e);
+ }
+ }
+
+ /**
+ * returns true if the Open operation has been called successfully
+ */
+ public boolean isOpen() {
+ return !closed;
+ }
+
+
+ /**
+ * returns true if the Connect operation has been called successfully
+ */
+ public boolean isConnected() {
+ return connected;
+ }
+
+ public int getNumMessages() {
+ return mq != null? mq.size() : -1;
+ }
+
+
+ public String dumpQueue() {
+ return Util.dumpQueue(mq);
+ }
+
+ /**
+ * Returns a map of statistics of the various protocols and of the channel itself.
+ * @return Map. A map where the keys are the protocols ("channel" pseudo key is
+ * used for the channel itself") and the values are property maps.
+ */
+ public Map dumpStats() {
+ Map retval=prot_stack.dumpStats();
+ if(retval != null) {
+ Map tmp=dumpChannelStats();
+ if(tmp != null)
+ retval.put("channel", tmp);
+ }
+ return retval;
+ }
+
+ public Map dumpStats(String protocol_name) {
+ return prot_stack.dumpStats(protocol_name);
+ }
+
+ protected Map dumpChannelStats() {
+ Map retval=new HashMap();
+ retval.put("sent_msgs", new Long(sent_msgs));
+ retval.put("sent_bytes", new Long(sent_bytes));
+ retval.put("received_msgs", new Long(received_msgs));
+ retval.put("received_bytes", new Long(received_bytes));
+ return retval;
+ }
+
+
+ /**
+ * Sends a message through the protocol stack.
+ * Implements the Transport interface.
+ *
+ * @param msg the message to be sent through the protocol stack,
+ * the destination of the message is specified inside the message itself
+ * @exception ChannelNotConnectedException
+ * @exception ChannelClosedException
+ */
+ public void send(Message msg) throws ChannelNotConnectedException, ChannelClosedException {
+ checkClosedOrNotConnected();
+ if(msg == null)
+ throw new NullPointerException("msg is null");
+ if(stats) {
+ sent_msgs++;
+ sent_bytes+=msg.getLength();
+ }
+
+ down(new Event(Event.MSG, msg));
+ }
+
+
+ /**
+ * creates a new message with the destination address, and the source address
+ * and the object as the message value
+ * @param dst - the destination address of the message, null for all members
+ * @param src - the source address of the message
+ * @param obj - the value of the message
+ * @exception ChannelNotConnectedException
+ * @exception ChannelClosedException
+ * @see JChannel#send
+ */
+ public void send(Address dst, Address src, Serializable obj) throws ChannelNotConnectedException, ChannelClosedException {
+ send(new Message(dst, src, obj));
+ }
+
+
+ /**
+ * Blocking receive method.
+ * This method returns the object that was first received by this JChannel and that has not been
+ * received before. After the object is received, it is removed from the receive queue.
+ * If you only want to inspect the object received without removing it from the queue call
+ * JChannel.peek
+ * If no messages are in the receive queue, this method blocks until a message is added or the operation times out
+ * By specifying a timeout of 0, the operation blocks forever, or until a message has been received.
+ * @param timeout the number of milliseconds to wait if the receive queue is empty. 0 means wait forever
+ * @exception TimeoutException if a timeout occured prior to a new message was received
+ * @exception ChannelNotConnectedException
+ * @exception ChannelClosedException
+ * @see JChannel#peek
+ * @deprecated Use a {@link Receiver} instead
+ */
+ public Object receive(long timeout) throws ChannelNotConnectedException, ChannelClosedException, TimeoutException {
+
+ checkClosedOrNotConnected();
+
+ try {
+ Event evt=(timeout <= 0)? (Event)mq.remove() : (Event)mq.remove(timeout);
+ Object retval=getEvent(evt);
+ evt=null;
+ return retval;
+ }
+ catch(QueueClosedException queue_closed) {
+ throw new ChannelClosedException();
+ }
+ catch(TimeoutException t) {
+ throw t;
+ }
+ catch(Exception e) {
+ if(log.isErrorEnabled()) log.error("exception: " + e);
+ return null;
+ }
+ }
+
+
+ /**
+ * Just peeks at the next message, view or block. Does not install
+ * new view if view is received
+ * Does the same thing as JChannel.receive but doesn't remove the object from the
+ * receiver queue
+ */
+ public Object peek(long timeout) throws ChannelNotConnectedException, ChannelClosedException, TimeoutException {
+
+ checkClosedOrNotConnected();
+
+ try {
+ Event evt=(timeout <= 0)? (Event)mq.peek() : (Event)mq.peek(timeout);
+ Object retval=getEvent(evt);
+ evt=null;
+ return retval;
+ }
+ catch(QueueClosedException queue_closed) {
+ if(log.isErrorEnabled()) log.error("exception: " + queue_closed);
+ return null;
+ }
+ catch(TimeoutException t) {
+ return null;
+ }
+ catch(Exception e) {
+ if(log.isErrorEnabled()) log.error("exception: " + e);
+ return null;
+ }
+ }
+
+
+
+
+ /**
+ * Returns the current view.
+ *
+ * If the channel is not connected or if it is closed it will return null.
+ *
+ * @return returns the current group view, or null if the channel is closed or disconnected
+ */
+ public View getView() {
+ return closed || !connected ? null : my_view;
+ }
+
+
+ /**
+ * returns the local address of the channel
+ * returns null if the channel is closed
+ */
+ public Address getLocalAddress() {
+ return closed ? null : local_addr;
+ }
+
+ public String getLocalAddressAsString() {
+ return local_addr != null? local_addr.toString() : "n/a";
+ }
+
+
+ /**
+ * returns the name of the channel
+ * if the channel is not connected or if it is closed it will return null
+ * @deprecated Use {@link #getClusterName()} instead
+ */
+ public String getChannelName() {
+ return closed ? null : !connected ? null : cluster_name;
+ }
+
+ public String getClusterName() {
+ return closed ? null : !connected ? null : cluster_name;
+ }
+
+
+ /**
+ * Sets a channel option. The options can be one of the following:
+ *
+ * Channel.BLOCK
+ * Channel.LOCAL
+ * Channel.AUTO_RECONNECT
+ * Channel.AUTO_GETSTATE
+ *
+ *
+ * There are certain dependencies between the options that you can set,
+ * I will try to describe them here.
+ *
+ * Option: Channel.BLOCK
+ * Value: java.lang.Boolean
+ * Result: set to true will set setOpt(VIEW, true) and the JChannel will receive BLOCKS and VIEW events
+ *
+ * Option: LOCAL
+ * Value: java.lang.Boolean
+ * Result: set to true the JChannel will receive messages that it self sent out.
+ *
+ * Option: AUTO_RECONNECT
+ * Value: java.lang.Boolean
+ * Result: set to true and the JChannel will try to reconnect when it is being closed
+ *
+ * Option: AUTO_GETSTATE
+ * Value: java.lang.Boolean
+ * Result: set to true, the AUTO_RECONNECT will be set to true and the JChannel will try to get the state after a close and reconnect happens
+ *
+ *
+ * @param option the parameter option Channel.VIEW, Channel.SUSPECT, etc
+ * @param value the value to set for this option
+ *
+ */
+ public void setOpt(int option, Object value) {
+ if(closed) {
+ if(log.isWarnEnabled()) log.warn("channel is closed; option not set !");
+ return;
+ }
+
+ switch(option) {
+ case VIEW:
+ if(log.isWarnEnabled())
+ log.warn("option VIEW has been deprecated (it is always true now); this option is ignored");
+ break;
+ case SUSPECT:
+ if(log.isWarnEnabled())
+ log.warn("option SUSPECT has been deprecated (it is always true now); this option is ignored");
+ break;
+ case BLOCK:
+ if(value instanceof Boolean)
+ receive_blocks=((Boolean)value).booleanValue();
+ else
+ if(log.isErrorEnabled()) log.error("option " + Channel.option2String(option) +
+ " (" + value + "): value has to be Boolean");
+ break;
+
+ case GET_STATE_EVENTS:
+ if(log.isWarnEnabled())
+ log.warn("option GET_STATE_EVENTS has been deprecated (it is always true now); this option is ignored");
+ break;
+
+ case LOCAL:
+ if(value instanceof Boolean)
+ receive_local_msgs=((Boolean)value).booleanValue();
+ else
+ if(log.isErrorEnabled()) log.error("option " + Channel.option2String(option) +
+ " (" + value + "): value has to be Boolean");
+ break;
+
+ case AUTO_RECONNECT:
+ if(value instanceof Boolean)
+ auto_reconnect=((Boolean)value).booleanValue();
+ else
+ if(log.isErrorEnabled()) log.error("option " + Channel.option2String(option) +
+ " (" + value + "): value has to be Boolean");
+ break;
+
+ case AUTO_GETSTATE:
+ if(value instanceof Boolean) {
+ auto_getstate=((Boolean)value).booleanValue();
+ if(auto_getstate)
+ auto_reconnect=true;
+ }
+ else
+ if(log.isErrorEnabled()) log.error("option " + Channel.option2String(option) +
+ " (" + value + "): value has to be Boolean");
+ break;
+
+ default:
+ if(log.isErrorEnabled()) log.error("option " + Channel.option2String(option) + " not known");
+ break;
+ }
+ }
+
+
+ /**
+ * returns the value of an option.
+ * @param option the option you want to see the value for
+ * @return the object value, in most cases java.lang.Boolean
+ * @see JChannel#setOpt
+ */
+ public Object getOpt(int option) {
+ switch(option) {
+ case VIEW:
+ return Boolean.TRUE;
+ case BLOCK:
+ return receive_blocks ? Boolean.TRUE : Boolean.FALSE;
+ case SUSPECT:
+ return Boolean.TRUE;
+ case AUTO_RECONNECT:
+ return auto_reconnect ? Boolean.TRUE : Boolean.FALSE;
+ case AUTO_GETSTATE:
+ return auto_getstate ? Boolean.TRUE : Boolean.FALSE;
+ case GET_STATE_EVENTS:
+ return Boolean.TRUE;
+ case LOCAL:
+ return receive_local_msgs ? Boolean.TRUE : Boolean.FALSE;
+ default:
+ if(log.isErrorEnabled()) log.error("option " + Channel.option2String(option) + " not known");
+ return null;
+ }
+ }
+
+
+ /**
+ * Called to acknowledge a block() (callback in MembershipListener
or
+ * BlockEvent
received from call to receive()
).
+ * After sending blockOk(), no messages should be sent until a new view has been received.
+ * Calling this method on a closed channel has no effect.
+ */
+ public void blockOk() {
+
+ }
+
+
+ /**
+ * Retrieves a full state from the target member.
+ *
+ *
+ * State transfer is initiated by invoking getState on this channel, state
+ * receiver, and sending a GET_STATE message to a target member - state
+ * provider. State provider passes GET_STATE message to application that is
+ * using the state provider channel which in turn provides an application
+ * state to a state receiver. Upon successful installation of a state at
+ * state receiver this method returns true.
+ *
+ *
+ * @param target
+ * State provider. If null, coordinator is used
+ * @param state_id
+ * The ID of the substate. If null, the entire state will be
+ * transferred
+ * @param timeout
+ * the number of milliseconds to wait for the operation to
+ * complete successfully. 0 waits until the state has been
+ * received
+ *
+ * @see ExtendedMessageListener#getState(OutputStream)
+ * @see ExtendedMessageListener#setState(InputStream)
+ * @see MessageListener#getState()
+ * @see MessageListener#setState(byte[])
+ *
+ *
+ * @return true if state transfer was successful, false otherwise
+ * @throws ChannelNotConnectedException
+ * if channel was not connected at the time state retrieval
+ * was initiated
+ * @throws ChannelClosedException
+ * if channel was closed at the time state retrieval was
+ * initiated
+ * @throws IllegalStateException
+ * if one of state transfer protocols is not present in this
+ * channel
+ * @throws IllegalStateException
+ * if flush is used in this channel and cluster could not be
+ * flushed
+ */
+ public boolean getState(Address target, long timeout) throws ChannelNotConnectedException, ChannelClosedException {
+ return getState(target,null,timeout);
+ }
+
+ /**
+ * Retrieves a substate (or partial state) indicated by state_id from the target member.
+ *
+ *
+ * State transfer is initiated by invoking getState on this channel, state
+ * receiver, and sending a GET_STATE message to a target member - state
+ * provider. State provider passes GET_STATE message to application that is
+ * using the state provider channel which in turn provides an application
+ * state to a state receiver. Upon successful installation of a state at
+ * state receiver this method returns true.
+ *
+ *
+ * @param target
+ * State provider. If null, coordinator is used
+ * @param state_id
+ * The ID of the substate. If null, the entire state will be
+ * transferred
+ * @param timeout
+ * the number of milliseconds to wait for the operation to
+ * complete successfully. 0 waits until the state has been
+ * received
+ *
+ * @see ExtendedMessageListener#getState(OutputStream)
+ * @see ExtendedMessageListener#setState(InputStream)
+ * @see MessageListener#getState()
+ * @see MessageListener#setState(byte[])
+ *
+ *
+ * @return true if state transfer was successful, false otherwise
+ * @throws ChannelNotConnectedException
+ * if channel was not connected at the time state retrieval
+ * was initiated
+ * @throws ChannelClosedException
+ * if channel was closed at the time state retrieval was
+ * initiated
+ * @throws IllegalStateException
+ * if one of state transfer protocols is not present in this
+ * channel
+ * @throws IllegalStateException
+ * if flush is used in this channel and cluster could not be
+ * flushed
+ */
+ public boolean getState(Address target, String state_id, long timeout) throws ChannelNotConnectedException, ChannelClosedException {
+ return getState(target, state_id, timeout, true);
+ }
+
+ /**
+ * Retrieves a substate (or partial state) indicated by state_id from the target member.
+ *
+ *
+ * State transfer is initiated by invoking getState on this channel, state
+ * receiver, and sending a GET_STATE message to a target member - state
+ * provider. State provider passes GET_STATE message to application that is
+ * using the state provider channel which in turn provides an application
+ * state to a state receiver. Upon successful installation of a state at
+ * state receiver this method returns true.
+ *
+ *
+ * @param target
+ * State provider. If null, coordinator is used
+ * @param state_id
+ * The ID of the substate. If null, the entire state will be
+ * transferred
+ * @param timeout
+ * the number of milliseconds to wait for the operation to
+ * complete successfully. 0 waits until the state has been
+ * received
+ * @param useFlushIfPresent
+ * whether channel should be flushed prior to state retrieval
+ *
+ * @see ExtendedMessageListener#getState(OutputStream)
+ * @see ExtendedMessageListener#setState(InputStream)
+ * @see MessageListener#getState()
+ * @see MessageListener#setState(byte[])
+ *
+ *
+ * @return true if state transfer was successful, false otherwise
+ * @throws ChannelNotConnectedException
+ * if channel was not connected at the time state retrieval
+ * was initiated
+ * @throws ChannelClosedException
+ * if channel was closed at the time state retrieval was
+ * initiated
+ * @throws IllegalStateException
+ * if one of state transfer protocols is not present in this
+ * channel
+ * @throws IllegalStateException
+ * if flush is used in this channel and cluster could not be
+ * flushed
+ */
+ public boolean getState(Address target, String state_id, long timeout,
+ boolean useFlushIfPresent) throws ChannelNotConnectedException,
+ ChannelClosedException {
+
+ Callable flusher = new Callable() {
+ public Boolean call() throws Exception {
+ return Util.startFlush(JChannel.this);
+ }
+ };
+ return getState(target, state_id, timeout, useFlushIfPresent?flusher:null);
+ }
+
+ /**
+ * Retrieves a substate (or partial state) indicated by state_id from the target member.
+ *
+ *
+ * State transfer is initiated by invoking getState on this channel, state
+ * receiver, and sending a GET_STATE message to a target member - state
+ * provider. State provider passes GET_STATE message to application that is
+ * using the state provider channel which in turn provides an application
+ * state to a state receiver. Upon successful installation of a state at
+ * state receiver this method returns true.
+ *
+ *
+ * @param target
+ * State provider. If null, coordinator is used
+ * @param state_id
+ * The ID of the substate. If null, the entire state will be
+ * transferred
+ * @param timeout
+ * the number of milliseconds to wait for the operation to
+ * complete successfully. 0 waits until the state has been
+ * received
+ * @param flushInvoker
+ * algorithm invoking flush
+ *
+ * @see ExtendedMessageListener#getState(OutputStream)
+ * @see ExtendedMessageListener#setState(InputStream)
+ * @see MessageListener#getState()
+ * @see MessageListener#setState(byte[])
+ *
+ *
+ * @return true if state transfer was successful, false otherwise
+ * @throws ChannelNotConnectedException
+ * if channel was not connected at the time state retrieval
+ * was initiated
+ * @throws ChannelClosedException
+ * if channel was closed at the time state retrieval was
+ * initiated
+ * @throws IllegalStateException
+ * if one of state transfer protocols is not present in this
+ * channel
+ * @throws IllegalStateException
+ * if flush is used in this channel and cluster could not be
+ * flushed
+ */
+ protected boolean getState(Address target, String state_id, long timeout,Callable flushInvoker) throws ChannelNotConnectedException, ChannelClosedException {
+ checkClosedOrNotConnected();
+ if(!state_transfer_supported) {
+ throw new IllegalStateException("fetching state will fail as state transfer is not supported. "
+ + "Add one of the STATE_TRANSFER protocols to your protocol configuration");
+ }
+
+ if(target == null)
+ target=determineCoordinator();
+ if(target != null && local_addr != null && target.equals(local_addr)) {
+ if(log.isTraceEnabled())
+ log.trace("cannot get state from myself (" + target + "): probably the first member");
+ return false;
+ }
+
+ boolean initiateFlush = flushSupported() && flushInvoker!=null;
+
+ if (initiateFlush) {
+ boolean successfulFlush = false;
+ try {
+ successfulFlush = flushInvoker.call();
+ }
+ catch (Exception e) {
+ successfulFlush = false;
+ // http://jira.jboss.com/jira/browse/JGRP-759
+ }
+ finally {
+ if (!successfulFlush) {
+ throw new IllegalStateException("Node "+ local_addr+ " could not flush the cluster for state retrieval");
+ }
+ }
+ }
+
+ state_promise.reset();
+ StateTransferInfo state_info=new StateTransferInfo(target, state_id, timeout);
+ down(new Event(Event.GET_STATE, state_info));
+ Boolean b=state_promise.getResult(state_info.timeout);
+
+ if(initiateFlush)
+ stopFlush();
+
+ boolean state_transfer_successfull = b != null && b.booleanValue();
+ if(!state_transfer_successfull)
+ down(new Event(Event.RESUME_STABLE));
+ return state_transfer_successfull;
+ }
+
+
+ /**
+ * Retrieves the current group state. Sends GET_STATE event down to STATE_TRANSFER layer.
+ * Blocks until STATE_TRANSFER sends up a GET_STATE_OK event or until timeout
+ * milliseconds have elapsed. The argument of GET_STATE_OK should be a vector of objects.
+ * @param targets - the target members to receive the state from ( an Address list )
+ * @param timeout - the number of milliseconds to wait for the operation to complete successfully
+ * @return true of the state was received, false if the operation timed out
+ * @deprecated Not really needed - we always want to get the state from a single member,
+ * use {@link #getState(org.jgroups.Address, long)} instead
+ */
+ public boolean getAllStates(Vector targets, long timeout) throws ChannelNotConnectedException, ChannelClosedException {
+ throw new UnsupportedOperationException("use getState() instead");
+ }
+
+
+ /**
+ * Called by the application is response to receiving a getState()
object when
+ * calling receive()
.
+ * When the application receives a getState() message on the receive() method,
+ * it should call returnState() to reply with the state of the application
+ * @param state The state of the application as a byte buffer
+ * (to send over the network).
+ */
+ public void returnState(byte[] state) {
+ try {
+ StateTransferInfo state_info=new StateTransferInfo(null, null, 0L, state);
+ applstate_exchanger.exchange(state_info);
+ }
+ catch(InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ /**
+ * Returns a substate as indicated by state_id
+ * @param state
+ * @param state_id
+ */
+ public void returnState(byte[] state, String state_id) {
+ try {
+ StateTransferInfo state_info=new StateTransferInfo(null, state_id, 0L, state);
+ applstate_exchanger.exchange(state_info);
+ }
+ catch(InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+
+
+
+
+ /**
+ * Callback method
+ * Called by the ProtocolStack when a message is received.
+ * It will be added to the message queue from which subsequent
+ * Receive
s will dequeue it.
+ * @param evt the event carrying the message from the protocol stack
+ */
+ public Object up(Event evt) {
+ int type=evt.getType();
+ Message msg;
+
+
+ switch(type) {
+
+ case Event.MSG:
+ msg=(Message)evt.getArg();
+ if(stats) {
+ received_msgs++;
+ received_bytes+=msg.getLength();
+ }
+
+ if(!receive_local_msgs) { // discard local messages (sent by myself to me)
+ if(local_addr != null && msg.getSrc() != null)
+ if(local_addr.equals(msg.getSrc()))
+ return null;
+ }
+ break;
+
+ case Event.VIEW_CHANGE:
+ View tmp=(View)evt.getArg();
+ if(tmp instanceof MergeView)
+ my_view=new View(tmp.getVid(), tmp.getMembers());
+ else
+ my_view=tmp;
+
+ /*
+ * Bela&Vladimir Oct 27th,2006 (JGroups 2.4)- we need to switch to
+ * connected=true because client can invoke channel.getView() in
+ * viewAccepted() callback invoked on this thread
+ * (see Event.VIEW_CHANGE handling below)
+ */
+
+ // not good: we are only connected when we returned from connect() - bela June 22 2007
+ // if(connected == false) {
+ // connected=true;
+ // }
+ break;
+
+ case Event.CONFIG:
+ Map config=(Map)evt.getArg();
+ if(config != null) {
+ if(config.containsKey("state_transfer")) {
+ state_transfer_supported=((Boolean)config.get("state_transfer")).booleanValue();
+ }
+ if(config.containsKey("flush_supported")) {
+ flush_supported=((Boolean)config.get("flush_supported")).booleanValue();
+ }
+ }
+ break;
+
+ case Event.INFO:
+ Map m = (Map) evt.getArg();
+ info.putAll(m);
+ break;
+
+ case Event.GET_STATE_OK:
+ StateTransferInfo state_info = (StateTransferInfo) evt.getArg();
+ byte[] state = state_info.state;
+
+ try{
+ if(up_handler != null){
+ return up_handler.up(evt);
+ }
+
+ if(state != null){
+ String state_id = state_info.state_id;
+ if(receiver != null){
+ try{
+ if(receiver instanceof ExtendedReceiver && state_id != null)
+ ((ExtendedReceiver) receiver).setState(state_id, state);
+ else
+ receiver.setState(state);
+ }catch(Throwable t){
+ if(log.isWarnEnabled())
+ log.warn("failed calling setState() in receiver", t);
+ }
+ }else{
+ try{
+ mq.add(new Event(Event.STATE_RECEIVED, state_info));
+ }
+ catch(Exception e) {
+ }
+ }
+ }
+ }
+ finally {
+ state_promise.setResult(state != null ? Boolean.TRUE : Boolean.FALSE);
+ }
+ break;
+ case Event.STATE_TRANSFER_INPUTSTREAM_CLOSED:
+ state_promise.setResult(Boolean.TRUE);
+ break;
+
+ case Event.STATE_TRANSFER_INPUTSTREAM:
+ StateTransferInfo sti=(StateTransferInfo)evt.getArg();
+ InputStream is=sti.inputStream;
+ //Oct 13,2006 moved to down() when Event.STATE_TRANSFER_INPUTSTREAM_CLOSED is received
+ //state_promise.setResult(is != null? Boolean.TRUE : Boolean.FALSE);
+
+ if(up_handler != null) {
+ return up_handler.up(evt);
+ }
+
+ if(is != null) {
+ if(receiver instanceof ExtendedReceiver) {
+ try {
+ if(sti.state_id == null)
+ ((ExtendedReceiver)receiver).setState(is);
+ else
+ ((ExtendedReceiver)receiver).setState(sti.state_id, is);
+ }
+ catch(Throwable t) {
+ if(log.isWarnEnabled())
+ log.warn("failed calling setState() in receiver", t);
+ }
+ }
+ else if(receiver instanceof Receiver){
+ if(log.isWarnEnabled()){
+ log.warn("Channel has STREAMING_STATE_TRANSFER, however," +
+ " application does not implement ExtendedMessageListener. State is not transfered");
+ Util.close(is);
+ }
+ }
+ else {
+ try {
+ mq.add(new Event(Event.STATE_TRANSFER_INPUTSTREAM, sti));
+ }
+ catch(Exception e) {
+ }
+ }
+ }
+ break;
+
+ case Event.SET_LOCAL_ADDRESS:
+ local_addr_promise.setResult((Address)evt.getArg());
+ break;
+
+ case Event.EXIT:
+ handleExit(evt);
+ return null; // no need to pass event up; already done in handleExit()
+
+ default:
+ break;
+ }
+
+
+ // If UpHandler is installed, pass all events to it and return (UpHandler is e.g. a building block)
+ if(up_handler != null) {
+ Object ret=up_handler.up(evt);
+
+ if(type == Event.UNBLOCK){
+ flush_unblock_promise.setResult(Boolean.TRUE);
+ }
+ return ret;
+ }
+
+ switch(type) {
+ case Event.MSG:
+ if(receiver != null) {
+ try {
+ receiver.receive((Message)evt.getArg());
+ }
+ catch(Throwable t) {
+ if(log.isWarnEnabled())
+ log.warn("failed calling receive() in receiver", t);
+ }
+ return null;
+ }
+ break;
+ case Event.VIEW_CHANGE:
+ if(receiver != null) {
+ try {
+ receiver.viewAccepted((View)evt.getArg());
+ }
+ catch(Throwable t) {
+ if(log.isWarnEnabled())
+ log.warn("failed calling viewAccepted() in receiver", t);
+ }
+ return null;
+ }
+ break;
+ case Event.SUSPECT:
+ if(receiver != null) {
+ try {
+ receiver.suspect((Address)evt.getArg());
+ }
+ catch(Throwable t) {
+ if(log.isWarnEnabled())
+ log.warn("failed calling suspect() in receiver", t);
+ }
+ return null;
+ }
+ break;
+ case Event.GET_APPLSTATE:
+ if(receiver != null) {
+ StateTransferInfo state_info=(StateTransferInfo)evt.getArg();
+ byte[] tmp_state=null;
+ String state_id=state_info.state_id;
+ try {
+ if(receiver instanceof ExtendedReceiver && state_id!=null) {
+ tmp_state=((ExtendedReceiver)receiver).getState(state_id);
+ }
+ else {
+ tmp_state=receiver.getState();
+ }
+ }
+ catch(Throwable t) {
+ if(log.isWarnEnabled())
+ log.warn("failed calling getState() in receiver", t);
+ }
+ return new StateTransferInfo(null, state_id, 0L, tmp_state);
+ }
+ break;
+ case Event.STATE_TRANSFER_OUTPUTSTREAM:
+ StateTransferInfo sti=(StateTransferInfo)evt.getArg();
+ OutputStream os=sti.outputStream;
+ if(receiver instanceof ExtendedReceiver) {
+ if(os != null) {
+ try {
+ if(sti.state_id == null)
+ ((ExtendedReceiver)receiver).getState(os);
+ else
+ ((ExtendedReceiver)receiver).getState(sti.state_id, os);
+ }
+ catch(Throwable t) {
+ if(log.isWarnEnabled())
+ log.warn("failed calling getState() in receiver", t);
+ }
+ }
+ }
+ else if(receiver instanceof Receiver){
+ if(log.isWarnEnabled()){
+ log.warn("Channel has STREAMING_STATE_TRANSFER, however," +
+ " application does not implement ExtendedMessageListener. State is not transfered");
+ Util.close(os);
+ }
+ }
+ break;
+
+ case Event.BLOCK:
+ if(!receive_blocks) { // discard if client has not set 'receiving blocks' to 'on'
+ return Boolean.TRUE;
+ }
+
+ if(receiver != null) {
+ try {
+ receiver.block();
+ }
+ catch(Throwable t) {
+ if(log.isErrorEnabled())
+ log.error("failed calling block() in receiver", t);
+ }
+ return Boolean.TRUE;
+ }
+ break;
+ case Event.UNBLOCK:
+ //invoke receiver if block receiving is on
+ if(receive_blocks && receiver instanceof ExtendedReceiver) {
+ try {
+ ((ExtendedReceiver)receiver).unblock();
+ }
+ catch(Throwable t) {
+ if(log.isErrorEnabled())
+ log.error("failed calling unblock() in receiver", t);
+ }
+ }
+ //flip promise
+ flush_unblock_promise.setResult(Boolean.TRUE);
+ return null;
+ default:
+ break;
+ }
+
+ if(type == Event.MSG || type == Event.VIEW_CHANGE || type == Event.SUSPECT ||
+ type == Event.GET_APPLSTATE || type== Event.STATE_TRANSFER_OUTPUTSTREAM
+ || type == Event.BLOCK || type == Event.UNBLOCK) {
+ try {
+ mq.add(evt);
+ }
+ catch(QueueClosedException queue_closed) {
+ ; // ignore
+ }
+ catch(Exception e) {
+ if(log.isWarnEnabled()) log.warn("exception adding event " + evt + " to message queue", e);
+ }
+ }
+
+ if(type == Event.GET_APPLSTATE) {
+ try {
+ return applstate_exchanger.exchange(null);
+ }
+ catch(InterruptedException e) {
+ Thread.currentThread().interrupt();
+ return null;
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Sends a message through the protocol stack if the stack is available
+ * @param evt the message to send down, encapsulated in an event
+ */
+ public void down(Event evt) {
+ if(evt == null) return;
+
+ switch(evt.getType()) {
+ case Event.CONFIG:
+ try {
+ Map m=(Map)evt.getArg();
+ if(m != null) {
+ additional_data.putAll(m);
+ if(m.containsKey("additional_data")) {
+ byte[] tmp=(byte[])m.get("additional_data");
+ if(local_addr instanceof IpAddress)
+ ((IpAddress)local_addr).setAdditionalData(tmp);
+ }
+ }
+ }
+ catch(Throwable t) {
+ if(log.isErrorEnabled()) log.error("CONFIG event did not contain a hashmap: " + t);
+ }
+ break;
+ }
+
+ prot_stack.down(evt);
+ }
+
+
+ public Object downcall(Event evt) {
+ if(evt == null) return null;
+
+ switch(evt.getType()) {
+ case Event.CONFIG:
+ try {
+ Map m=(Map)evt.getArg();
+ if(m != null) {
+ additional_data.putAll(m);
+ if(m.containsKey("additional_data")) {
+ byte[] tmp=(byte[])m.get("additional_data");
+ if(local_addr instanceof IpAddress)
+ ((IpAddress)local_addr).setAdditionalData(tmp);
+ }
+ }
+ }
+ catch(Throwable t) {
+ if(log.isErrorEnabled()) log.error("CONFIG event did not contain a hashmap: " + t);
+ }
+ break;
+ }
+
+ return prot_stack.down(evt);
+ }
+
+
+
+ public String toString(boolean details) {
+ StringBuilder sb=new StringBuilder();
+ sb.append("local_addr=").append(local_addr).append('\n');
+ sb.append("cluster_name=").append(cluster_name).append('\n');
+ sb.append("my_view=").append(my_view).append('\n');
+ sb.append("connected=").append(connected).append('\n');
+ sb.append("closed=").append(closed).append('\n');
+ if(mq != null)
+ sb.append("incoming queue size=").append(mq.size()).append('\n');
+ if(details) {
+ sb.append("receive_blocks=").append(receive_blocks).append('\n');
+ sb.append("receive_local_msgs=").append(receive_local_msgs).append('\n');
+ sb.append("auto_reconnect=").append(auto_reconnect).append('\n');
+ sb.append("auto_getstate=").append(auto_getstate).append('\n');
+ sb.append("state_transfer_supported=").append(state_transfer_supported).append('\n');
+ sb.append("props=").append(props).append('\n');
+ }
+
+ return sb.toString();
+ }
+
+
+ /* ----------------------------------- Private Methods ------------------------------------- */
+
+
+ protected final void init(ProtocolStackConfigurator configurator) throws ChannelException {
+ if(log.isInfoEnabled())
+ log.info("JGroups version: " + Version.description);
+ // ConfiguratorFactory.substituteVariables(configurator); // replace vars with system props
+ props=configurator.getProtocolStackString();
+ props=Util.substituteVariable(props);
+ prot_stack=new ProtocolStack(this, props);
+ try {
+ prot_stack.setup(); // Setup protocol stack (creates protocol, calls init() on them)
+ }
+ catch(Throwable e) {
+ throw new ChannelException("unable to setup the protocol stack: " + e.getMessage(), e);
+ }
+ }
+
+
+ /**
+ * Initializes all variables. Used after close() or disconnect() ,
+ * to be ready for new connect()
+ */
+ private void init() {
+ local_addr=null;
+ cluster_name=null;
+ my_view=null;
+
+ // changed by Bela Sept 25 2003
+ //if(mq != null && mq.closed())
+ // mq.reset();
+ connected=false;
+ }
+
+
+ private void startStack(String cluster_name) throws ChannelException {
+ /*make sure the channel is not closed*/
+ checkClosed();
+
+ /*make sure we have a valid channel name*/
+ if(cluster_name == null) {
+ if(log.isDebugEnabled()) log.debug("cluster_name is null, assuming unicast channel");
+ }
+ else
+ this.cluster_name=cluster_name;
+
+ try {
+ prot_stack.startStack(cluster_name); // calls start() in all protocols, from top to bottom
+ }
+ catch(Throwable e) {
+ throw new ChannelException("failed to start protocol stack", e);
+ }
+
+ String tmp=Util.getProperty(new String[]{Global.CHANNEL_LOCAL_ADDR_TIMEOUT, "local_addr.timeout"},
+ null, null, false, "30000");
+ LOCAL_ADDR_TIMEOUT=Long.parseLong(tmp);
+
+ /* Wait LOCAL_ADDR_TIMEOUT milliseconds for local_addr to have a non-null value (set by SET_LOCAL_ADDRESS) */
+ local_addr=local_addr_promise.getResult(LOCAL_ADDR_TIMEOUT);
+ if(local_addr == null) {
+ log.fatal("local_addr is null; cannot connect");
+ throw new ChannelException("local_addr is null");
+ }
+
+ /*create a temporary view, assume this channel is the only member and is the coordinator*/
+ Vector t=new Vector(1);
+ t.addElement(local_addr);
+ my_view=new View(local_addr, 0, t); // create a dummy view
+
+ TP transport=prot_stack.getTransport();
+ transport.registerProbeHandler(probe_handler);
+ }
+
+
+
+ /**
+ * health check
+ * throws a ChannelClosed exception if the channel is closed
+ */
+ protected void checkClosed() throws ChannelClosedException {
+ if(closed)
+ throw new ChannelClosedException();
+ }
+
+
+ protected void checkClosedOrNotConnected() throws ChannelNotConnectedException, ChannelClosedException {
+ if(closed)
+ throw new ChannelClosedException();
+ if(!connected)
+ throw new ChannelNotConnectedException();
+ }
+
+
+ /**
+ * returns the value of the event
+ * These objects will be returned
+ *
+ * Event Type - Return Type
+ * Event.MSG - returns a Message object
+ * Event.VIEW_CHANGE - returns a View object
+ * Event.SUSPECT - returns a SuspectEvent object
+ * Event.BLOCK - returns a new BlockEvent object
+ * Event.GET_APPLSTATE - returns a GetStateEvent object
+ * Event.STATE_RECEIVED- returns a SetStateEvent object
+ * Event.Exit - returns an ExitEvent object
+ * All other - return the actual Event object
+ *
+ * @param evt - the event of which you want to extract the value
+ * @return the event value if it matches the select list,
+ * returns null if the event is null
+ * returns the event itself if a match (See above) can not be made of the event type
+ */
+ static Object getEvent(Event evt) {
+ if(evt == null)
+ return null; // correct ?
+
+ switch(evt.getType()) {
+ case Event.MSG:
+ return evt.getArg();
+ case Event.VIEW_CHANGE:
+ return evt.getArg();
+ case Event.SUSPECT:
+ return new SuspectEvent(evt.getArg());
+ case Event.BLOCK:
+ return new BlockEvent();
+ case Event.UNBLOCK:
+ return new UnblockEvent();
+ case Event.GET_APPLSTATE:
+ StateTransferInfo info=(StateTransferInfo)evt.getArg();
+ return new GetStateEvent(info.target, info.state_id);
+ case Event.STATE_RECEIVED:
+ info=(StateTransferInfo)evt.getArg();
+ return new SetStateEvent(info.state, info.state_id);
+ case Event.STATE_TRANSFER_OUTPUTSTREAM:
+ info = (StateTransferInfo)evt.getArg();
+ return new StreamingGetStateEvent(info.outputStream,info.state_id);
+ case Event.STATE_TRANSFER_INPUTSTREAM:
+ info = (StateTransferInfo)evt.getArg();
+ return new StreamingSetStateEvent(info.inputStream,info.state_id);
+ case Event.EXIT:
+ return new ExitEvent();
+ default:
+ return evt;
+ }
+ }
+
+ /**
+ * Disconnects and closes the channel.
+ * This method does the following things
+ *
+ * Calls this.disconnect
if the disconnect parameter is true
+ * Calls Queue.close
on mq if the close_mq parameter is true
+ * Calls ProtocolStack.stop
on the protocol stack
+ * Calls ProtocolStack.destroy
on the protocol stack
+ * Sets the channel closed and channel connected flags to true and false
+ * Notifies any channel listener of the channel close operation
+ *
+ */
+ protected void _close(boolean disconnect, boolean close_mq) {
+ if(closed)
+ return;
+
+ if(disconnect)
+ disconnect(); // leave group if connected
+
+ if(close_mq)
+ closeMessageQueue(false);
+
+ stopStack(true, true);
+ closed=true;
+ connected=false;
+ notifyChannelClosed(this);
+ init(); // sets local_addr=null; changed March 18 2003 (bela) -- prevented successful rejoining
+ }
+
+ protected void stopStack(boolean disconnect, boolean destroy) {
+ if(prot_stack != null) {
+ try {
+ if(disconnect)
+ prot_stack.stopStack(cluster_name);
+
+ if(destroy)
+ prot_stack.destroy();
+ }
+ catch(Exception e) {
+ if(log.isErrorEnabled())
+ log.error("failed destroying the protocol stack", e);
+ }
+
+ TP transport=prot_stack.getTransport();
+ if(transport != null)
+ transport.unregisterProbeHandler(probe_handler);
+ }
+ }
+
+
+ public final void closeMessageQueue(boolean flush_entries) {
+ if(mq != null)
+ mq.close(flush_entries);
+ }
+
+
+ /**
+ * Creates a separate thread to close the protocol stack.
+ * This is needed because the thread that called JChannel.up() with the EXIT event would
+ * hang waiting for up() to return, while up() actually tries to kill that very thread.
+ * This way, we return immediately and allow the thread to terminate.
+ */
+ private synchronized void handleExit(Event evt) {
+ notifyChannelShunned();
+ if(!auto_reconnect)
+ return;
+
+ if(closer != null && !closer.isAlive())
+ closer=null;
+ if(closer == null) {
+ if(log.isDebugEnabled())
+ log.debug("received an EXIT event, will leave the channel");
+ closer=new CloserThread(evt);
+ closer.start();
+ }
+ }
+
+ public boolean flushSupported() {
+ return flush_supported;
+ }
+
+ /**
+ * Will perform a flush of the system, ie. all pending messages are flushed out of the
+ * system and all members ack their reception. After this call returns, no member will
+ * be sending any messages until {@link #stopFlush()} is called.
+ *
+ * In case of flush collisions, random sleep time backoff algorithm is employed and
+ * flush is reattempted for numberOfAttempts. Therefore this method is guaranteed
+ * to return after timeout x numberOfAttempts miliseconds.
+ *
+ * @param automatic_resume Call {@link #stopFlush()} after the flush
+ * @return true if FLUSH completed within the timeout
+ */
+ public boolean startFlush(boolean automatic_resume) {
+ if(!flushSupported()) {
+ throw new IllegalStateException("Flush is not supported, add pbcast.FLUSH protocol to your configuration");
+ }
+ boolean successfulFlush = (Boolean) downcall(new Event(Event.SUSPEND));
+
+ if(automatic_resume)
+ stopFlush();
+
+ return successfulFlush;
+ }
+
+ /**
+ * Performs a partial flush in a cluster for flush participants.
+ *
+ * All pending messages are flushed out only for flush participants.
+ * Remaining members in a cluster are not included in flush.
+ * Flush participants should be a proper subset of a current view.
+ *
+ *
+ * In case of flush collisions, random sleep time backoff algorithm is employed and
+ * flush is reattempted for numberOfAttempts. Therefore this method is guaranteed
+ * to return after timeout x numberOfAttempts miliseconds.
+ *
+ * @param automatic_resume Call {@link #stopFlush()} after the flush
+ * @return true if FLUSH completed within the timeout
+ */
+ public boolean startFlush(List
flushParticipants,boolean automatic_resume) {
+ boolean successfulFlush = false;
+ if(!flushSupported()){
+ throw new IllegalStateException("Flush is not supported, add pbcast.FLUSH protocol to your configuration");
+ }
+ View v = getView();
+ if(v != null && v.getMembers().containsAll(flushParticipants)){
+ successfulFlush = (Boolean) downcall(new Event(Event.SUSPEND, flushParticipants));
+ }else{
+ throw new IllegalArgumentException("Current view " + v
+ + " does not contain all flush participants "
+ + flushParticipants);
+ }
+
+ if(automatic_resume)
+ stopFlush(flushParticipants);
+
+ return successfulFlush;
+ }
+
+ /**
+ * Will perform a flush of the system, ie. all pending messages are flushed out of the
+ * system and all members ack their reception. After this call returns, no member will
+ * be sending any messages until {@link #stopFlush()} is called.
+ *
+ * In case of flush collisions, random sleep time backoff algorithm is employed and
+ * flush is reattempted for numberOfAttempts. Therefore this method is guaranteed
+ * to return after timeout x numberOfAttempts miliseconds.
+ * @param timeout
+ * @param automatic_resume Call {@link #stopFlush()} after the flush
+ * @return true if FLUSH completed within the timeout
+ */
+ public boolean startFlush(long timeout, boolean automatic_resume) {
+ return startFlush(automatic_resume);
+ }
+
+ public void stopFlush() {
+ if(!flushSupported()) {
+ throw new IllegalStateException("Flush is not supported, add pbcast.FLUSH protocol to your configuration");
+ }
+ flush_unblock_promise.reset();
+ down(new Event(Event.RESUME));
+
+ //do not return until UNBLOCK event is received
+ try {
+ flush_unblock_promise.getResultWithTimeout(FLUSH_UNBLOCK_TIMEOUT);
+ }
+ catch(TimeoutException te) {
+ log.warn("Timeout waiting for UNBLOCK event at " + getLocalAddress());
+ }
+ }
+
+ public void stopFlush(List
flushParticipants) {
+ if(!flushSupported()) {
+ throw new IllegalStateException("Flush is not supported, add pbcast.FLUSH protocol to your configuration");
+ }
+ flush_unblock_promise.reset();
+ down(new Event(Event.RESUME, flushParticipants));
+
+ // do not return until UNBLOCK event is received
+ try {
+ flush_unblock_promise.getResultWithTimeout(FLUSH_UNBLOCK_TIMEOUT);
+ }
+ catch(TimeoutException te) {
+ log.warn("Timeout waiting for UNBLOCK event at " + getLocalAddress());
+ }
+ }
+
+ @Override
+ public Map getInfo(){
+ return new HashMap(info);
+ }
+
+ public void setInfo(String key, Object value) {
+ if(key != null)
+ info.put(key, value);
+ }
+
+ Address determineCoordinator() {
+ Vector mbrs=my_view != null? my_view.getMembers() : null;
+ if(mbrs == null)
+ return null;
+ if(!mbrs.isEmpty())
+ return mbrs.firstElement();
+ return null;
+ }
+
+ private TimeScheduler getTimer() {
+ if(prot_stack != null) {
+ TP transport=prot_stack.getTransport();
+ if(transport != null) {
+ return transport.getTimer();
+ }
+ }
+ return null;
+ }
+
+ /* ------------------------------- End of Private Methods ---------------------------------- */
+
+ class MyProbeHandler implements TP.ProbeHandler {
+
+ public Map handleProbe(String... keys) {
+ HashMap map=new HashMap(2);
+ for(String key: keys) {
+ if(key.startsWith("jmx")) {
+ Map tmp_stats;
+ int index=key.indexOf("=");
+ if(index > -1) {
+ String value=key.substring(index +1);
+ tmp_stats=dumpStats(value);
+ }
+ else
+ tmp_stats=dumpStats();
+
+ map.put("jmx", tmp_stats != null? Util.mapToString(tmp_stats) : "null");
+ continue;
+ }
+ if(key.equals("info")) {
+ Map tmp_info=getInfo();
+ map.put("info", tmp_info != null? Util.mapToString(tmp_info) : "null");
+ }
+ }
+
+ map.put("version", Version.description + ", cvs=\"" + Version.cvs + "\"");
+ if(my_view != null && !map.containsKey("view"))
+ map.put("view", my_view.toString());
+ map.put("local_addr", local_addr != null? local_addr.toString() : "null");
+ map.put("cluster", getClusterName());
+ map.put("member", getLocalAddressAsString() + " (" + getClusterName() + ")");
+ return map;
+ }
+
+ public String[] supportedKeys() {
+ return new String[]{"jmx", "info"};
+ }
+ }
+
+ /**
+ * Closes, reopens and reconnects to the cluster
+ */
+ class CloserThread extends Thread {
+ final Event evt;
+ final Thread t=null;
+
+
+ CloserThread(Event evt) {
+ super(Util.getGlobalThreadGroup(), "CloserThread");
+ this.evt=evt;
+ setDaemon(true);
+ }
+
+
+ public void run() {
+ String old_cluster_name=cluster_name; // remember because close() will null it
+ try {
+ if(log.isDebugEnabled())
+ log.debug("closing the channel");
+ _close(false, false); // do not disconnect before closing channel, do not close mq (yet !)
+ }
+ catch(Throwable ex1) {
+ if(log.isErrorEnabled())
+ log.error("failed closing the channel", ex1);
+ }
+
+ try {
+ if(up_handler != null)
+ up_handler.up(this.evt);
+ else {
+ if(receiver == null)
+ mq.add(this.evt);
+ }
+ }
+ catch(Throwable ex2) {
+ if(log.isErrorEnabled())
+ log.error("failed passing up EXIT event", ex2);
+ }
+
+
+ if(mq != null) {
+ Util.sleep(500); // give the mq thread a bit of time to deliver EXIT to the application
+ try { mq.close(false); } catch(Throwable ex3) {}
+ }
+
+ for(int i=0; i < 5; i++) {
+ try {
+ if(closed == false)
+ break;
+ if(log.isDebugEnabled()) log.debug("reconnecting to cluster " + old_cluster_name);
+ open();
+ if(additional_data != null) {
+ // send previously set additional_data down the stack - other protocols (e.g. TP) use it
+ Map m=new HashMap(additional_data);
+ down(new Event(Event.CONFIG, m));
+ }
+ }
+ catch(Throwable ex4) {
+ if(log.isErrorEnabled()) log.error("failure reopening channel: " + ex4);
+ Util.sleep(500);
+ }
+ }
+
+ if(closed) { // still closed; reopening failed above
+ if(log.isErrorEnabled())
+ log.error("failed reopening channel, terminating closer thread");
+ closer=null;
+ return;
+ }
+
+ while(!connected) {
+ try {
+ connect(old_cluster_name);
+ notifyChannelReconnected(local_addr);
+ }
+ catch(Throwable ex5) {
+ if(log.isErrorEnabled()) log.error("failure reconnecting to channel, retrying", ex5);
+ Util.sleep(1000); // sleep 1 sec between reconnect attempts
+ }
+ }
+
+ if(auto_getstate && state_transfer_supported) {
+ if(log.isDebugEnabled())
+ log.debug("fetching the state (auto_getstate=true)");
+ boolean rc=false;
+ try {
+ rc=JChannel.this.getState(null, GET_STATE_DEFAULT_TIMEOUT);
+ if(log.isDebugEnabled()) {
+ if(rc)
+ log.debug("state was retrieved successfully");
+ else
+ log.debug("state transfer failed");
+ }
+ }
+ catch(Throwable ex6) {
+ if(log.isErrorEnabled())
+ log.error("failed auto-fetching state", ex6);
+ }
+
+ }
+
+ }
+ }
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/JChannelFactory.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/JChannelFactory.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/JChannelFactory.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,545 @@
+// $Id: JChannelFactory.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+
+package org.jgroups;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jgroups.conf.ConfiguratorFactory;
+import org.jgroups.conf.ProtocolStackConfigurator;
+import org.jgroups.conf.XmlConfigurator;
+import org.jgroups.jmx.JmxConfigurator;
+import org.jgroups.mux.Multiplexer;
+import org.jgroups.mux.MuxChannel;
+import org.jgroups.util.Util;
+import org.w3c.dom.*;
+
+import javax.management.MBeanServer;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * JChannelFactory creates pure Java implementations of the Channel
+ * interface.
+ * See {@link JChannel} for a discussion of channel properties.
+ */
+public class JChannelFactory implements ChannelFactory {
+ private ProtocolStackConfigurator configurator;
+
+ private Log log=LogFactory.getLog(getClass());
+
+ /**
+ * Map. Hashmap which maps stack names to JGroups
+ * configurations. Keys are stack names, values are plain JGroups stack
+ * configs. This is (re-)populated whenever a setMultiplexerConfig() method
+ * is called
+ */
+ private final Map stacks = Collections.synchronizedMap(new HashMap());
+
+ /**
+ * Map, maintains mapping between stack names (e.g. "udp") and Multiplexer(es)
+ *
+ */
+ private final Map channels = Collections.synchronizedMap(new HashMap());
+
+
+ /**
+ * The MBeanServer to expose JMX management data with (no management data
+ * will be available if null)
+ */
+ private MBeanServer server = null;
+
+ /** To expose the channels and protocols */
+ private String domain = "jgroups";
+
+ /** Whether or not to expose channels via JMX */
+ private boolean expose_channels=true;
+
+ /** Whether to expose the factory only, or all protocols as well */
+ private boolean expose_protocols=true;
+
+
+ private final static String PROTOCOL_STACKS="protocol_stacks";
+ private final static String STACK="stack";
+ private static final String NAME="name";
+ private static final String CONFIG="config";
+
+ /**
+ * Constructs a JChannelFactory
instance that contains no
+ * protocol stack configuration.
+ */
+ public JChannelFactory() {
+ }
+
+ /**
+ * Constructs a JChannelFactory
instance that utilizes the
+ * specified file for protocl stack configuration.
+ *
+ * @param properties a file containing a JGroups XML protocol stack
+ * configuration.
+ *
+ * @throws ChannelException if problems occur during the interpretation of
+ * the protocol stack configuration.
+ */
+ public JChannelFactory(File properties) throws ChannelException {
+ configurator=ConfiguratorFactory.getStackConfigurator(properties);
+ }
+
+ /**
+ * Constructs a JChannelFactory
instance that utilizes the
+ * specified file for protocl stack configuration.
+ *
+ * @param properties a XML element containing a JGroups XML protocol stack
+ * configuration.
+ *
+ * @throws ChannelException if problems occur during the interpretation of
+ * the protocol stack configuration.
+ */
+ public JChannelFactory(Element properties) throws ChannelException {
+ configurator=ConfiguratorFactory.getStackConfigurator(properties);
+ }
+
+ /**
+ * Constructs a JChannelFactory
instance that utilizes the
+ * specified file for protocl stack configuration.
+ *
+ * @param properties a URL pointing to a JGroups XML protocol stack
+ * configuration.
+ *
+ * @throws ChannelException if problems occur during the interpretation of
+ * the protocol stack configuration.
+ */
+ public JChannelFactory(URL properties) throws ChannelException {
+ configurator=ConfiguratorFactory.getStackConfigurator(properties);
+ }
+
+ /**
+ * Constructs a JChannel
instance with the protocol stack
+ * configuration based upon the specified properties parameter.
+ *
+ * @param properties an old style property string, a string representing a
+ * system resource containing a JGroups XML configuration,
+ * a string representing a URL pointing to a JGroups XML
+ * XML configuration, or a string representing a file name
+ * that contains a JGroups XML configuration.
+ *
+ * @throws ChannelException if problems occur during the interpretation of
+ * the protocol stack configuration.
+ */
+ public JChannelFactory(String properties) throws ChannelException {
+ configurator=ConfiguratorFactory.getStackConfigurator(properties);
+ }
+
+
+ public void setMultiplexerConfig(Object properties) throws Exception {
+ setMultiplexerConfig(properties, true);
+ }
+
+ public void setMultiplexerConfig(Object properties, boolean replace) throws Exception {
+ InputStream input=ConfiguratorFactory.getConfigStream(properties);
+ if(input == null)
+ throw new FileNotFoundException(properties.toString());
+ try {
+ parse(input, replace);
+ }
+ catch(Exception ex) {
+ throw new Exception("failed parsing " + properties, ex);
+ }
+ finally {
+ Util.close(input);
+ }
+ }
+
+ public void setMultiplexerConfig(File file) throws Exception {
+ setMultiplexerConfig(file, true);
+ }
+
+ public void setMultiplexerConfig(File file, boolean replace) throws Exception {
+ InputStream input=ConfiguratorFactory.getConfigStream(file);
+ if(input == null)
+ throw new FileNotFoundException(file.toString());
+ try {
+ parse(input, replace);
+ }
+ catch(Exception ex) {
+ throw new Exception("failed parsing " + file.toString(), ex);
+ }
+ finally {
+ Util.close(input);
+ }
+ }
+
+ public void setMultiplexerConfig(Element properties) throws Exception {
+ parse(properties, true);
+ }
+
+ public void setMultiplexerConfig(Element properties, boolean replace) throws Exception {
+ parse(properties, replace);
+ }
+
+ public void setMultiplexerConfig(URL url) throws Exception {
+ setMultiplexerConfig(url, true);
+ }
+
+ public void setMultiplexerConfig(URL url, boolean replace) throws Exception {
+ InputStream input=ConfiguratorFactory.getConfigStream(url);
+ if(input == null)
+ throw new FileNotFoundException(url.toString());
+ try {
+ parse(input, replace);
+ }
+ catch(Exception ex) {
+ throw new Exception("failed parsing " + url.toString(), ex);
+ }
+ finally {
+ Util.close(input);
+ }
+ }
+
+ public void setMultiplexerConfig(String properties) throws Exception {
+ setMultiplexerConfig(properties, true);
+ }
+
+ public void setMultiplexerConfig(String properties, boolean replace) throws Exception {
+ InputStream input=ConfiguratorFactory.getConfigStream(properties);
+ if(input == null)
+ throw new FileNotFoundException(properties);
+ try {
+ parse(input, replace);
+ }
+ catch(Exception ex) {
+ throw new Exception("failed parsing " + properties, ex);
+ }
+ finally {
+ Util.close(input);
+ }
+ }
+
+ /**
+ * Returns the stack configuration as a string (to be fed into new JChannel()). Throws an exception
+ * if the stack_name is not found. One of the setMultiplexerConfig() methods had to be called beforehand
+ * @return The protocol stack config as a plain string
+ */
+ public String getConfig(String stack_name) throws Exception {
+ String cfg=stacks.get(stack_name);
+ if(cfg == null)
+ throw new Exception("stack \"" + stack_name + "\" not found in " + stacks.keySet());
+ return cfg;
+ }
+
+ /**
+ * @return Returns all configurations
+ */
+ public String getMultiplexerConfig() {
+ StringBuilder sb=new StringBuilder();
+ for(Map.Entry entry: stacks.entrySet()) {
+ sb.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n");
+ }
+ return sb.toString();
+ }
+
+ /** Removes all configurations */
+ public void clearConfigurations() {
+ stacks.clear();
+ }
+
+ public boolean removeConfig(String stack_name) {
+ return stack_name != null && stacks.remove(stack_name) != null;
+ }
+
+ public MBeanServer getServer() {
+ return server;
+ }
+
+ public void setServer(MBeanServer server) {
+ this.server=server;
+ }
+
+ public String getDomain() {
+ return domain;
+ }
+
+ public void setDomain(String domain) {
+ this.domain=domain;
+ }
+
+ public boolean isExposeChannels() {
+ return expose_channels;
+ }
+
+ public void setExposeChannels(boolean expose_channels) {
+ this.expose_channels=expose_channels;
+ }
+
+ public boolean isExposeProtocols() {
+ return expose_protocols;
+ }
+
+ public void setExposeProtocols(boolean expose_protocols) {
+ this.expose_protocols=expose_protocols;
+ if (expose_protocols)
+ this.expose_channels=true;
+ }
+
+
+ /**
+ * Creates a JChannel
implementation of the
+ * Channel
interface.
+ *
+ * @param properties the protocol stack configuration information; a
+ * null
value means use the default protocol
+ * stack configuration.
+ *
+ * @throws ChannelException if the creation of the channel failed.
+ *
+ * @deprecated JChannel
's conversion to type-specific
+ * construction, and the subsequent deprecation of its
+ * JChannel(Object)
constructor, necessitate the
+ * deprecation of this factory method as well. Type-specific
+ * protocol stack configuration should be specfied during
+ * construction of an instance of this factory.
+ */
+ public Channel createChannel(Object properties) throws ChannelException {
+ return new JChannel(properties);
+ }
+
+ /**
+ * Creates a JChannel
implementation of the
+ * Channel interface using the protocol stack configuration
+ * information specfied during construction of an instance of this factory.
+ *
+ * @throws ChannelException if the creation of the channel failed.
+ */
+ public Channel createChannel() throws ChannelException {
+ return new JChannel(configurator);
+ }
+
+ public Channel createChannel(String stack_name) throws Exception {
+ String props=stack_name != null? getConfig(stack_name) : null;
+ return new JChannel(props);
+ }
+
+ public Channel createMultiplexerChannel(String stack_name, String id) throws Exception {
+ return createMultiplexerChannel(stack_name, id, false, null);
+ }
+
+ public Channel createMultiplexerChannel(final String stack_name,
+ String id,
+ boolean register_for_state_transfer,
+ String substate_id) throws Exception {
+ if(stack_name == null || id == null)
+ throw new IllegalArgumentException("stack name and service ID have to be non null");
+
+ if(stack_name.length()==0 || id.length() == 0)
+ throw new IllegalArgumentException("stack name and service ID have to non empty strings");
+
+ Multiplexer mux = null;
+ synchronized (channels) {
+ if (!channels.containsKey(stack_name)) {
+ JChannel ch = new JChannel(getConfig(stack_name));
+ registerChannel(ch, stack_name);
+ mux = new Multiplexer(ch);
+ channels.put(stack_name, mux);
+ } else {
+ mux = channels.get(stack_name);
+ }
+ }
+ if(register_for_state_transfer)
+ mux.registerForStateTransfer(id, substate_id);
+
+ Channel c = mux.createMuxChannel(id, stack_name);
+ c.addChannelListener(new MuxFactoryChannelListener());
+ return c;
+ }
+
+ /**
+ * Returns true if this factory has already registered MuxChannel with given
+ * stack_name and an id, false otherwise.
+ *
+ * @param stack_name
+ * name of the stack used
+ * @param id
+ * service id
+ * @return true if such MuxChannel exists, false otherwise
+ */
+ public boolean hasMuxChannel(String stack_name, String id) {
+ Multiplexer entry = channels.get(stack_name);
+ if (entry != null) {
+ Set services = entry.getServiceIds();
+ return (services != null && services.contains(id));
+ }
+ return false;
+ }
+
+ public void create() throws Exception{
+ if(expose_channels) {
+ if(server == null)
+ server=Util.getMBeanServer();
+ if(server == null)
+ throw new Exception("No MBeanServer found; JChannelFactory needs to be run with an MBeanServer present, " +
+ "e.g. inside JBoss or JDK 5, or with ExposeChannel set to false");
+ if(domain == null)
+ domain="jgroups";
+ }
+ }
+
+ public void start() throws Exception {
+
+ }
+
+ public void stop() {
+
+ }
+
+ public void destroy() {
+ synchronized (channels) {
+ for(Map.Entry entry: channels.entrySet()){
+ Multiplexer m = entry.getValue();
+ if(m != null){
+ m.closeAll();
+ m.close();
+ }
+ }
+ }
+ unregister(domain + ":*");
+ channels.clear();
+ }
+
+
+ public String dumpConfiguration() {
+ return stacks.keySet().toString();
+ }
+
+ public String dumpChannels() {
+ StringBuilder sb = new StringBuilder();
+ synchronized (channels) {
+ for (Map.Entry entry : channels.entrySet()) {
+ Multiplexer m = entry.getValue();
+ sb.append(entry.getKey()).append(": ").append(m.getServiceIds()).append("\n");
+ }
+ }
+ return sb.toString();
+ }
+
+ private void registerChannel(JChannel ch, String stack_name) throws Exception {
+ if(expose_channels && server != null)
+ JmxConfigurator.registerChannel(ch, server, domain, stack_name, expose_protocols);
+ }
+
+
+ private void unregister(String name) {
+ if(expose_channels && server != null){
+ try{
+ JmxConfigurator.unregister(server, name);
+ }catch(Exception e){
+ log.error("failed unregistering " + name, e);
+ }
+ }
+ }
+
+
+
+ private void parse(InputStream input, boolean replace) throws Exception {
+ /**
+ * CAUTION: crappy code ahead ! I (bela) am not an XML expert, so the code below is pretty amateurish...
+ * But it seems to work, and it is executed only on startup, so no perf loss on the critical path.
+ * If somebody wants to improve this, please be my guest.
+ */
+ DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
+ factory.setValidating(false); //for now
+ DocumentBuilder builder=factory.newDocumentBuilder();
+ Document document=builder.parse(input);
+
+ // The root element of the document should be the "config" element,
+ // but the parser(Element) method checks this so a check is not
+ // needed here.
+ Element configElement = document.getDocumentElement();
+ parse(configElement, replace);
+ }
+
+ private void parse(Element root, boolean replace) throws Exception {
+ /**
+ * CAUTION: crappy code ahead ! I (bela) am not an XML expert, so the code below is pretty amateurish...
+ * But it seems to work, and it is executed only on startup, so no perf loss on the critical path.
+ * If somebody wants to improve this, please be my guest.
+ */
+ String root_name=root.getNodeName();
+ if(!PROTOCOL_STACKS.equals(root_name.trim().toLowerCase())) {
+ String error="XML protocol stack configuration does not start with a '' element; " +
+ "maybe the XML configuration needs to be converted to the new format ?\n" +
+ "use 'java org.jgroups.conf.XmlConfigurator -new_format' to do so";
+ throw new IOException("invalid XML configuration: " + error);
+ }
+
+ NodeList tmp_stacks=root.getChildNodes();
+ for(int i=0; i < tmp_stacks.getLength(); i++) {
+ Node node = tmp_stacks.item(i);
+ if(node.getNodeType() != Node.ELEMENT_NODE )
+ continue;
+
+ Element stack=(Element) node;
+ String tmp=stack.getNodeName();
+ if(!STACK.equals(tmp.trim().toLowerCase())) {
+ throw new IOException("invalid configuration: didn't find a \"" + STACK + "\" element under \"" + PROTOCOL_STACKS + "\"");
+ }
+
+ NamedNodeMap attrs = stack.getAttributes();
+ Node name=attrs.getNamedItem(NAME);
+ // Node descr=attrs.getNamedItem(DESCR);
+ String st_name=name.getNodeValue();
+ // String stack_descr=descr.getNodeValue();
+ // System.out.print("Parsing \"" + st_name + "\" (" + stack_descr + ")");
+ NodeList configs=stack.getChildNodes();
+ for(int j=0; j < configs.getLength(); j++) {
+ Node tmp_config=configs.item(j);
+ if(tmp_config.getNodeType() != Node.ELEMENT_NODE )
+ continue;
+ Element cfg = (Element) tmp_config;
+ tmp=cfg.getNodeName();
+ if(!CONFIG.equals(tmp))
+ throw new IOException("invalid configuration: didn't find a \"" + CONFIG + "\" element under \"" + STACK + "\"");
+
+ XmlConfigurator conf=XmlConfigurator.getInstance(cfg);
+ // fixes http://jira.jboss.com/jira/browse/JGRP-290
+ ConfiguratorFactory.substituteVariables(conf); // replace vars with system props
+ String val=conf.getProtocolStackString();
+ if(replace) {
+ stacks.put(st_name, val);
+ if(log.isTraceEnabled())
+ log.trace("added config '" + st_name + "'");
+ }
+ else {
+ if(!stacks.containsKey(st_name)) {
+ stacks.put(st_name, val);
+ if(log.isTraceEnabled())
+ log.trace("added config '" + st_name + "'");
+ }
+ else {
+ if(log.isTraceEnabled())
+ log.trace("didn't add config '" + st_name + " because one of the same name already existed");
+ }
+ }
+ }
+ }
+ }
+
+
+
+ private class MuxFactoryChannelListener extends ChannelListenerAdapter{
+
+ public void channelClosed(Channel channel) {
+ MuxChannel mch = (MuxChannel)channel;
+ Multiplexer multiplexer = mch.getMultiplexer();
+ boolean all_closed = multiplexer.close();
+ if(all_closed) {
+ channels.remove(mch.getStackName());
+ unregister(domain + ":*,cluster=" + mch.getStackName());
+ }
+ }
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/Membership.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/Membership.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/Membership.java 17 Aug 2012 14:51:05 -0000 1.1
@@ -0,0 +1,256 @@
+// $Id: Membership.java,v 1.1 2012/08/17 14:51:05 marcin Exp $
+
+package org.jgroups;
+
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.*;
+
+
+/**
+ * Class to keep track of Addresses.
+ * The membership object holds a vector of Address objects that are in the same membership.
+ * Each unique address can only exist once; i.e., doing Membership.add(existing_address)
+ * will be ignored.
+ */
+public class Membership implements Cloneable {
+ /* private vector to hold all the addresses */
+ private final List members=new LinkedList();
+ protected static final Log log=LogFactory.getLog(Membership.class);
+
+ /**
+ * Public constructor
+ * Creates a member ship object with zero members
+ */
+ public Membership() {
+ }
+
+
+ /**
+ * Creates a member ship object with the initial members.
+ * The Address references are copied out of the vector, so that the
+ * vector passed in as parameters is not the same reference as the vector
+ * that the membership class is using
+ *
+ * @param initial_members - a list of members that belong to this membership
+ */
+ public Membership(Collection initial_members) {
+ if(initial_members != null)
+ add(initial_members);
+ }
+
+
+
+ /**
+ * returns a copy (clone) of the members in this membership.
+ * the vector returned is immutable in reference to this object.
+ * ie, modifying the vector that is being returned in this method
+ * will not modify this membership object.
+ *
+ * @return a list of members,
+ */
+ public Vector getMembers() {
+ /*clone so that this objects members can not be manipulated from the outside*/
+ synchronized(members) {
+ return new Vector(members);
+ }
+ }
+
+
+ /**
+ * Adds a new member to this membership.
+ * If the member already exist (Address.equals(Object) returns true then the member will
+ * not be added to the membership
+ */
+ public void add(Address new_member) {
+ synchronized(members) {
+ if(new_member != null && !members.contains(new_member)) {
+ members.add(new_member);
+ }
+ }
+ }
+
+
+ /**
+ * Adds a list of members to this membership
+ *
+ * @param v - a vector containing Address objects
+ * @throws ClassCastException if v contains objects that don't implement the Address interface
+ * @see #add
+ */
+ public final void add(Collection v) {
+ if(v != null) {
+ for(Iterator it=v.iterator(); it.hasNext();) {
+ Address addr=it.next();
+ add(addr);
+ }
+ }
+ }
+
+
+ /**
+ * removes an member from the membership.
+ * If this member doesn't exist, no action will be performed on the existing membership
+ *
+ * @param old_member - the member to be removed
+ */
+ public void remove(Address old_member) {
+ if(old_member != null) {
+ synchronized(members) {
+ members.remove(old_member);
+ }
+ }
+ }
+
+
+ /**
+ * removes all the members contained in v from this membership
+ *
+ * @param v - a vector containing all the members to be removed
+ */
+ public void remove(Collection v) {
+ if(v != null) {
+ synchronized(members) {
+ members.removeAll(v);
+ }
+ }
+ }
+
+
+ /**
+ * removes all the members from this membership
+ */
+ public void clear() {
+ synchronized(members) {
+ members.clear();
+ }
+ }
+
+ /**
+ * Clear the membership and adds all members of v
+ * This method will clear out all the old members of this membership by
+ * invoking the Clear
method.
+ * Then it will add all the all members provided in the vector v
+ *
+ * @param v - a vector containing all the members this membership will contain
+ */
+ public void set(Collection v) {
+ clear();
+ if(v != null) {
+ add(v);
+ }
+ }
+
+
+ /**
+ * Clear the membership and adds all members of v
+ * This method will clear out all the old members of this membership by
+ * invoking the Clear
method.
+ * Then it will add all the all members provided in the vector v
+ *
+ * @param m - a membership containing all the members this membership will contain
+ */
+ public void set(Membership m) {
+ clear();
+ if(m != null) {
+ add(m.getMembers());
+ }
+ }
+
+
+ /**
+ * merges membership with the new members and removes suspects
+ * The Merge method will remove all the suspects and add in the new members.
+ * It will do it in the order
+ * 1. Remove suspects
+ * 2. Add new members
+ * the order is very important to notice.
+ *
+ * @param new_mems - a vector containing a list of members (Address) to be added to this membership
+ * @param suspects - a vector containing a list of members (Address) to be removed from this membership
+ */
+ public void merge(Collection new_mems, Collection suspects) {
+ remove(suspects);
+ add(new_mems);
+ }
+
+
+ /**
+ * Returns true if the provided member belongs to this membership
+ *
+ * @param member
+ * @return true if the member belongs to this membership
+ */
+ public boolean contains(Address member) {
+ if(member == null) return false;
+ synchronized(members) {
+ return members.contains(member);
+ }
+ }
+
+
+ /* Simple inefficient bubble sort, but not used very often (only when merging) */
+ public void sort() {
+ synchronized(members) {
+ Collections.sort(members);
+ }
+ }
+
+
+
+
+ /**
+ * returns a copy of this membership
+ *
+ * @return an exact copy of this membership
+ */
+ public Membership copy() {
+ return ((Membership)clone());
+ }
+
+
+ /**
+ * @return a clone of this object. The list of members is copied to a new
+ * container
+ */
+ public Object clone() {
+ return new Membership(this.members);
+ }
+
+
+ /**
+ * Returns the number of addresses in this membership
+ *
+ * @return the number of addresses in this membership
+ */
+ public int size() {
+ synchronized(members) {
+ return members.size();
+ }
+ }
+
+ /**
+ * Returns the component at the specified index
+ *
+ * @param index - 0..size()-1
+ * @throws ArrayIndexOutOfBoundsException - if the index is negative or not less than the current size of this Membership object.
+ * @see java.util.Vector#elementAt
+ */
+
+ public Address elementAt(int index) {
+ synchronized(members) {
+ return members.get(index);
+ }
+ }
+
+
+ public String toString() {
+ synchronized(members) {
+ return members.toString();
+ }
+ }
+
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/MembershipListener.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/MembershipListener.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/MembershipListener.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,45 @@
+// $Id: MembershipListener.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+
+package org.jgroups;
+
+
+
+/**
+ * Allows a listener to be notified when group membership changes.
+ * These callbacks are used in {@link org.jgroups.blocks.PullPushAdapter}.
+ *
+ * The MembershipListener interface is similar to the {@link MessageListener}
+ * interface: every time a new view, a suspicion message, or a
+ * block event is received, the corresponding method of the class implementing
+ * MembershipListener will be called.
+ * Oftentimes the only method containing any functionality will be viewAccepted()
+ * which notifies the receiver that a new member has joined the group or that an
+ * existing member has left or crashed.
+ */
+public interface MembershipListener {
+
+ /**
+ * Called when a change in membership has occurred.
+ * No long running actions or sending of messages should be done in this callback.
+ * If some long running action needs to be performed, it should be done in a separate thread.
+ * Note that on reception of the first view (a new member just joined), the channel will not yet be
+ * in the connected state. This only happens when {@link Channel#connect(String)} returns.
+ */
+ void viewAccepted(View new_view);
+
+ /**
+ * Called whenever a member is suspected of having crashed,
+ * but has not yet been excluded.
+ */
+ void suspect(Address suspected_mbr);
+
+ /**
+ * Called (usually by the FLUSH protocol), as an indication that the member should stop sending messages.
+ * Any messages sent after returning from this callback might get blocked by the FLUSH protocol. When the FLUSH
+ * protocol is done, and messages can be sent again, the FLUSH protocol will simply unblock all pending messages.
+ * If a callback for unblocking is desired, implement {@link org.jgroups.ExtendedMembershipListener#unblock()}.
+ * Note that block() is the equivalent of reception of a BlockEvent in the pull mode.
+ */
+ void block();
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/MergeView.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/MergeView.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/MergeView.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,142 @@
+// $Id: MergeView.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+
+
+package org.jgroups;
+
+import java.io.*;
+import java.util.Vector;
+
+
+/**
+ * A view that is sent as a result of a merge.
+ * Whenever a group splits into subgroups, e.g., due to a network partition,
+ * and later the subgroups merge back together, a MergeView instead of a View
+ * will be received by the application. The MergeView class is a subclass of
+ * View and contains as additional instance variable: the list of views that
+ * were merged. For example, if the group denoted by view V1:(p,q,r,s,t)
+ * splits into subgroups V2:(p,q,r) and V2:(s,t), the merged view might be
+ * V3:(p,q,r,s,t). In this case the MergeView would contain a list of 2 views:
+ * V2:(p,q,r) and V2:(s,t).
+ */
+public class MergeView extends View {
+ protected Vector subgroups=null; // subgroups that merged into this single view (a list of Views)
+
+
+ /**
+ * Used by externalization
+ */
+ public MergeView() {
+ }
+
+
+ /**
+ * Creates a new view
+ *
+ * @param vid The view id of this view (can not be null)
+ * @param members Contains a list of all the members in the view, can be empty but not null.
+ * @param subgroups A list of Views representing the former subgroups
+ */
+ public MergeView(ViewId vid, Vector members, Vector subgroups) {
+ super(vid, members);
+ this.subgroups=subgroups;
+ }
+
+
+ /**
+ * Creates a new view
+ *
+ * @param creator The creator of this view (can not be null)
+ * @param id The lamport timestamp of this view
+ * @param members Contains a list of all the members in the view, can be empty but not null.
+ * @param subgroups A list of Views representing the former subgroups
+ */
+ public MergeView(Address creator, long id, Vector members, Vector subgroups) {
+ super(creator, id, members);
+ this.subgroups=subgroups;
+ }
+
+
+ public Vector getSubgroups() {
+ return subgroups;
+ }
+
+
+ /**
+ * creates a copy of this view
+ *
+ * @return a copy of this view
+ */
+ public Object clone() {
+ ViewId vid2=vid != null ? (ViewId)vid.clone() : null;
+ Vector members2=members != null ? (Vector)members.clone() : null;
+ Vector subgroups2=subgroups != null ? (Vector)subgroups.clone() : null;
+ return new MergeView(vid2, members2, subgroups2);
+ }
+
+
+ public String toString() {
+ StringBuilder sb=new StringBuilder();
+ sb.append("MergeView::").append(super.toString()).append(", subgroups=").append(subgroups);
+ return sb.toString();
+ }
+
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+ out.writeObject(subgroups);
+ }
+
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+ subgroups=(Vector)in.readObject();
+ }
+
+
+ public void writeTo(DataOutputStream out) throws IOException {
+ super.writeTo(out);
+
+ // write subgroups
+ int len=subgroups != null? subgroups.size() : 0;
+ out.writeShort(len);
+ if(len == 0)
+ return;
+ for(View v: subgroups) {
+ if(v instanceof MergeView)
+ out.writeBoolean(true);
+ else
+ out.writeBoolean(false);
+ v.writeTo(out);
+ }
+ }
+
+ public void readFrom(DataInputStream in) throws IOException, IllegalAccessException, InstantiationException {
+ super.readFrom(in);
+ short len=in.readShort();
+ if(len > 0) {
+ View v;
+ subgroups=new Vector();
+ for(int i=0; i < len; i++) {
+ boolean is_merge_view=in.readBoolean();
+ v=is_merge_view? new MergeView() : new View();
+ v.readFrom(in);
+ subgroups.add(v);
+ }
+ }
+ }
+
+ public int serializedSize() {
+ int retval=super.serializedSize();
+ retval+=Global.SHORT_SIZE; // for size of subgroups vector
+
+ if(subgroups == null)
+ return retval;
+ for(View v: subgroups) {
+ retval+=Global.BYTE_SIZE; // boolean for View or MergeView
+ retval+=v.serializedSize();
+ }
+ return retval;
+ }
+
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/Message.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/Message.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/Message.java 17 Aug 2012 14:51:03 -0000 1.1
@@ -0,0 +1,829 @@
+
+package org.jgroups;
+
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jgroups.conf.ClassConfigurator;
+import org.jgroups.stack.IpAddress;
+import org.jgroups.util.*;
+
+import java.io.*;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+
+/**
+ * A Message encapsulates data sent to members of a group. It contains among other things the
+ * address of the sender, the destination address, a payload (byte buffer) and a list of
+ * headers. Headers are added by protocols on the sender side and removed by protocols
+ * on the receiver's side.
+ *
+ * The byte buffer can point to a reference, and we can subset it using index and length. However,
+ * when the message is serialized, we only write the bytes between index and length.
+ * @author Bela Ban
+ * @version $Id: Message.java,v 1.1 2012/08/17 14:51:03 marcin Exp $
+ */
+public class Message implements Externalizable, Streamable {
+ protected Address dest_addr=null;
+ protected Address src_addr=null;
+
+ /** The payload */
+ private byte[] buf=null;
+
+ /** The index into the payload (usually 0) */
+ protected transient int offset=0;
+
+ /** The number of bytes in the buffer (usually buf.length is buf not equal to null). */
+ protected transient int length=0;
+
+ /** All headers are placed here */
+ protected Headers headers;
+
+ protected static final Log log=LogFactory.getLog(Message.class);
+
+ private static final long serialVersionUID=7966206671974139740L;
+
+ static final byte DEST_SET = 1;
+ static final byte SRC_SET = 2;
+ static final byte BUF_SET = 4;
+ // static final byte HDRS_SET=8; // bela July 15 2005: not needed, we always create headers
+ static final byte IPADDR_DEST =16;
+ static final byte IPADDR_SRC =32;
+ static final byte SRC_HOST_NULL =64;
+
+
+ // =========================== Flags ==============================
+ public static final byte OOB = 1;
+ public static final byte LOW_PRIO = 2; // not yet sure if we want this flag...
+ public static final byte HIGH_PRIO = 4; // not yet sure if we want this flag...
+
+ private byte flags=0;
+
+ static final Set nonStreamableHeaders=new HashSet();
+
+ /** Map. Maintains mappings to canonical addresses */
+ private static final ConcurrentHashMap canonicalAddresses=new ConcurrentHashMap();
+ private static final boolean DISABLE_CANONICALIZATION;
+
+ static {
+ boolean b;
+ try {
+ b=Boolean.getBoolean("disable_canonicalization");
+ }
+ catch (java.security.AccessControlException e) {
+ // this will happen in an applet context
+ b=true;
+ }
+ DISABLE_CANONICALIZATION=b;
+ }
+
+
+ /** Public constructor
+ * @param dest Address of receiver. If it is null then the message sent to the group.
+ * Otherwise, it contains a single destination and is sent to that member.
+ */
+ public Message(Address dest) {
+ setDest(dest);
+ headers=createHeaders(3);
+ }
+
+ /** Public constructor
+ * @param dest Address of receiver. If it is null then the message sent to the group.
+ * Otherwise, it contains a single destination and is sent to that member.
+ * @param src Address of sender
+ * @param buf Message to be sent. Note that this buffer must not be modified (e.g. buf[0]=0 is
+ * not allowed), since we don't copy the contents on clopy() or clone().
+ */
+ public Message(Address dest, Address src, byte[] buf) {
+ this(dest);
+ setSrc(src);
+ setBuffer(buf);
+ }
+
+
+ /**
+ * Constructs a message. The index and length parameters allow to provide a reference to
+ * a byte buffer, rather than a copy, and refer to a subset of the buffer. This is important when
+ * we want to avoid copying. When the message is serialized, only the subset is serialized.
+ *
+ * Note that the byte[] buffer passed as argument must not be modified. Reason: if we retransmit the
+ * message, it would still have a ref to the original byte[] buffer passed in as argument, and so we would
+ * retransmit a changed byte[] buffer !
+ *
+ * @param dest Address of receiver. If it is null then the message sent to the group.
+ * Otherwise, it contains a single destination and is sent to that member.
+ * @param src Address of sender
+ * @param buf A reference to a byte buffer
+ * @param offset The index into the byte buffer
+ * @param length The number of bytes to be used from buf . Both index and length are checked for
+ * array index violations and an ArrayIndexOutOfBoundsException will be thrown if invalid
+ */
+ public Message(Address dest, Address src, byte[] buf, int offset, int length) {
+ this(dest);
+ setSrc(src);
+ setBuffer(buf, offset, length);
+ }
+
+
+ /** Public constructor
+ * @param dest Address of receiver. If it is null then the message sent to the group.
+ * Otherwise, it contains a single destination and is sent to that member.
+ * @param src Address of sender
+ * @param obj The object will be serialized into the byte buffer. Object
+ * has to be serializable ! The resulting buffer must not be modified
+ * (e.g. buf[0]=0 is not allowed), since we don't copy the contents on clopy() or clone().
+ * Note that this is a convenience method and JGroups will use default Java serialization to
+ * serialize obj
into a byte buffer.
+ */
+ public Message(Address dest, Address src, Serializable obj) {
+ this(dest);
+ setSrc(src);
+ setObject(obj);
+ }
+
+
+ public Message() {
+ headers=createHeaders(3);
+ }
+
+
+ public Message(boolean create_headers) {
+ if(create_headers)
+ headers=createHeaders(3);
+ }
+
+ public Address getDest() {
+ return dest_addr;
+ }
+
+ public void setDest(Address new_dest) {
+ if(DISABLE_CANONICALIZATION)
+ dest_addr=new_dest;
+ else
+ dest_addr=canonicalAddress(new_dest);
+ }
+
+ public Address getSrc() {
+ return src_addr;
+ }
+
+ public void setSrc(Address new_src) {
+ if(DISABLE_CANONICALIZATION)
+ src_addr=new_src;
+ else
+ src_addr=canonicalAddress(new_src);
+ }
+
+ /**
+ * Returns a reference to the payload (byte buffer). Note that this buffer should not be modified as
+ * we do not copy the buffer on copy() or clone(): the buffer of the copied message is simply a reference to
+ * the old buffer.
+ * Even if offset and length are used: we return the entire buffer, not a subset.
+ */
+ public byte[] getRawBuffer() {
+ return buf;
+ }
+
+ /**
+ * Returns a copy of the buffer if offset and length are used, otherwise a reference.
+ * @return byte array with a copy of the buffer.
+ */
+ final public byte[] getBuffer() {
+ if(buf == null)
+ return null;
+ if(offset == 0 && length == buf.length)
+ return buf;
+ else {
+ byte[] retval=new byte[length];
+ System.arraycopy(buf, offset, retval, 0, length);
+ return retval;
+ }
+ }
+
+ final public void setBuffer(byte[] b) {
+ buf=b;
+ if(buf != null) {
+ offset=0;
+ length=buf.length;
+ }
+ else {
+ offset=length=0;
+ }
+ }
+
+ /**
+ * Set the internal buffer to point to a subset of a given buffer
+ * @param b The reference to a given buffer. If null, we'll reset the buffer to null
+ * @param offset The initial position
+ * @param length The number of bytes
+ */
+ final public void setBuffer(byte[] b, int offset, int length) {
+ buf=b;
+ if(buf != null) {
+ if(offset < 0 || offset > buf.length)
+ throw new ArrayIndexOutOfBoundsException(offset);
+ if((offset + length) > buf.length)
+ throw new ArrayIndexOutOfBoundsException((offset+length));
+ this.offset=offset;
+ this.length=length;
+ }
+ else {
+ this.offset=this.length=0;
+ }
+ }
+
+ /**
+
+ * Note that the byte[] buffer passed as argument must not be modified. Reason: if we retransmit the
+ * message, it would still have a ref to the original byte[] buffer passed in as argument, and so we would
+ * retransmit a changed byte[] buffer !
+ *
+ */
+ public final void setBuffer(Buffer buf) {
+ if(buf != null) {
+ this.buf=buf.getBuf();
+ this.offset=buf.getOffset();
+ this.length=buf.getLength();
+ }
+ }
+
+
+ /** Returns the offset into the buffer at which the data starts */
+ public int getOffset() {
+ return offset;
+ }
+
+ /** Returns the number of bytes in the buffer */
+ public int getLength() {
+ return length;
+ }
+
+ /** Returns a reference to the headers hashmap, which is immutable . Any attempt to
+ * modify the returned map will cause a runtime exception */
+ public Map getHeaders() {
+ return headers.getHeaders();
+ }
+
+ public String printHeaders() {
+ return headers.printHeaders();
+ }
+
+ public int getNumHeaders() {
+ return headers.size();
+ }
+
+ /**
+ * Takes an object and uses Java serialization to generate the byte[] buffer which is set in the message.
+ */
+ final public void setObject(Serializable obj) {
+ if(obj == null) return;
+ try {
+ byte[] tmp=Util.objectToByteBuffer(obj);
+ setBuffer(tmp);
+ }
+ catch(Exception ex) {
+ throw new IllegalArgumentException(ex);
+ }
+ }
+
+ /**
+ * Uses Java serialization to create an object from the buffer of the message. Note that this is dangerous when
+ * using your own classloader, e.g. inside of an application server ! Most likely, JGroups will use the system
+ * classloader to deserialize the buffer into an object, whereas (for example) a web application will want to
+ * use the webapp's classloader, resulting in a ClassCastException. The recommended way is for the application to
+ * use their own serialization and only pass byte[] buffer to JGroups.
+ * @return
+ */
+ final public Object getObject() {
+ try {
+ return Util.objectFromByteBuffer(buf, offset, length);
+ }
+ catch(Exception ex) {
+ throw new IllegalArgumentException(ex);
+ }
+ }
+
+
+ public void setFlag(byte flag) {
+ if(flag > Byte.MAX_VALUE || flag < 0)
+ throw new IllegalArgumentException("flag has to be >= 0 and <= " + Byte.MAX_VALUE);
+ flags |= flag;
+ }
+
+ public void clearFlag(byte flag) {
+ if(flag > Byte.MAX_VALUE || flag < 0)
+ throw new IllegalArgumentException("flag has to be >= 0 and <= " + Byte.MAX_VALUE);
+// if(isFlagSet(flag)) {
+// flags ^= flag;
+// }
+ flags &= ~flag;
+ }
+
+ public boolean isFlagSet(byte flag) {
+ return (flags & flag) == flag;
+ }
+
+ public byte getFlags() {
+ return flags;
+ }
+
+
+ /*---------------------- Used by protocol layers ----------------------*/
+
+ /** Puts a header given a key into the hashmap. Overwrites potential existing entry. */
+ public void putHeader(String key, Header hdr) {
+ headers.putHeader(key, hdr);
+ }
+
+ /**
+ * Puts a header given a key into the map, only if the key doesn't exist yet
+ * @param key
+ * @param hdr
+ * @return the previous value associated with the specified key, or
+ * null if there was no mapping for the key.
+ * (A null return can also indicate that the map
+ * previously associated null with the key,
+ * if the implementation supports null values.)
+ */
+ public Header putHeaderIfAbsent(String key, Header hdr) {
+ return headers.putHeaderIfAbsent(key, hdr);
+ }
+
+ /**
+ *
+ * @param key
+ * @return the header assoaicted with key
+ * @deprecated Use getHeader() instead. The issue with removing a header is described in
+ * http://jira.jboss.com/jira/browse/JGRP-393
+ */
+ public Header removeHeader(String key) {
+ return getHeader(key);
+ }
+
+ public Header getHeader(String key) {
+ return headers.getHeader(key);
+ }
+ /*---------------------------------------------------------------------*/
+
+
+ public Message copy() {
+ return copy(true);
+ }
+
+ /**
+ * Create a copy of the message. If offset and length are used (to refer to another buffer), the copy will
+ * contain only the subset offset and length point to, copying the subset into the new copy.
+ * @param copy_buffer
+ * @return Message with specified data
+ */
+ public Message copy(boolean copy_buffer) {
+ Message retval=new Message(false);
+ retval.dest_addr=dest_addr;
+ retval.src_addr=src_addr;
+ retval.flags=flags;
+
+ if(copy_buffer && buf != null) {
+
+ // change bela Feb 26 2004: we don't resolve the reference
+ retval.setBuffer(buf, offset, length);
+ }
+
+ retval.headers=createHeaders(headers);
+ return retval;
+ }
+
+
+ protected Object clone() throws CloneNotSupportedException {
+ return copy();
+ }
+
+ public Message makeReply() {
+ return new Message(src_addr);
+ }
+
+
+ public String toString() {
+ StringBuilder ret=new StringBuilder(64);
+ ret.append("[dst: ");
+ if(dest_addr == null)
+ ret.append("");
+ else
+ ret.append(dest_addr);
+ ret.append(", src: ");
+ if(src_addr == null)
+ ret.append("");
+ else
+ ret.append(src_addr);
+
+ int size;
+ if((size=getNumHeaders()) > 0)
+ ret.append(" (").append(size).append(" headers)");
+
+ ret.append(", size=");
+ if(buf != null && length > 0)
+ ret.append(length);
+ else
+ ret.append('0');
+ ret.append(" bytes");
+ if(flags > 0)
+ ret.append(", flags=").append(flagsToString());
+ ret.append(']');
+ return ret.toString();
+ }
+
+
+
+
+ /** Tries to read an object from the message's buffer and prints it */
+ public String toStringAsObject() {
+
+ if(buf == null) return null;
+ try {
+ Object obj=getObject();
+ return obj != null ? obj.toString() : "";
+ }
+ catch(Exception e) { // it is not an object
+ return "";
+ }
+ }
+
+
+ /**
+ * Returns size of buffer, plus some constant overhead for src and dest, plus number of headers time
+ * some estimated size/header. The latter is needed because we don't want to marshal all headers just
+ * to find out their size requirements. If a header implements Sizeable, the we can get the correct
+ * size. Size estimations don't have to be very accurate since this is mainly used by FRAG to
+ * determine whether to fragment a message or not. Fragmentation will then serialize the message,
+ * therefore getting the correct value.
+ */
+
+
+ /**
+ * Returns the exact size of the marshalled message. Uses method size() of each header to compute the size, so if
+ * a Header subclass doesn't implement size() we will use an approximation. However, most relevant header subclasses
+ * have size() implemented correctly. (See org.jgroups.tests.SizeTest).
+ * @return The number of bytes for the marshalled message
+ */
+ public long size() {
+ long retval=Global.BYTE_SIZE // leading byte
+ + Global.BYTE_SIZE // flags
+ + length // buffer
+ + (buf != null? Global.INT_SIZE : 0); // if buf != null 4 bytes for length
+
+ // if(dest_addr != null)
+ // retval+=dest_addr.size();
+ if(src_addr != null)
+ retval+=(src_addr).size();
+
+ retval+=Global.SHORT_SIZE; // size (short)
+ retval+=headers.marshalledSize();
+ return retval;
+ }
+
+
+ public String printObjectHeaders() {
+ return headers.printObjectHeaders();
+ }
+
+
+
+ /* ----------------------------------- Interface Externalizable ------------------------------- */
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ int len;
+ Externalizable hdr;
+ Map.Entry entry;
+
+ if(dest_addr != null) {
+ out.writeBoolean(true);
+ Marshaller.write(dest_addr, out);
+ }
+ else {
+ out.writeBoolean(false);
+ }
+
+ if(src_addr != null) {
+ out.writeBoolean(true);
+ Marshaller.write(src_addr, out);
+ }
+ else {
+ out.writeBoolean(false);
+ }
+
+ out.write(flags);
+
+ if(buf == null)
+ out.writeInt(0);
+ else {
+ out.writeInt(length);
+ out.write(buf, offset, length);
+ }
+
+ len=headers.size();
+ out.writeInt(len);
+ final Object[] data=headers.getRawData();
+
+ for(int i=0; i < data.length; i+=2) {
+ if(data[i] != null) {
+ out.writeUTF((String)data[i]);
+ hdr=(Externalizable)data[i+1];
+ Marshaller.write(hdr, out);
+ }
+ }
+ }
+
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ boolean destAddressExist=in.readBoolean();
+
+ if(destAddressExist) {
+ dest_addr=(Address)Marshaller.read(in);
+ if(!DISABLE_CANONICALIZATION)
+ dest_addr=canonicalAddress(dest_addr);
+ }
+
+ boolean srcAddressExist=in.readBoolean();
+ if(srcAddressExist) {
+ src_addr=(Address)Marshaller.read(in);
+ if(!DISABLE_CANONICALIZATION)
+ src_addr=canonicalAddress(src_addr);
+ }
+
+ flags=in.readByte();
+
+ int i=in.readInt();
+ if(i != 0) {
+ buf=new byte[i];
+ in.readFully(buf);
+ offset=0;
+ length=buf.length;
+ }
+
+ int len=in.readInt();
+ while(len-- > 0) {
+ String key=in.readUTF();
+ Header value=(Header)Marshaller.read(in);
+ headers.putHeader(key, value);
+ }
+ }
+
+ /* --------------------------------- End of Interface Externalizable ----------------------------- */
+
+
+ /* ----------------------------------- Interface Streamable ------------------------------- */
+
+ /**
+ * Streams all members (dest and src addresses, buffer and headers) to the output stream.
+ * @param out
+ * @throws IOException
+ */
+ public void writeTo(DataOutputStream out) throws IOException {
+ byte leading=0;
+
+ if(src_addr != null) {
+ leading+=SRC_SET;
+ if(src_addr instanceof IpAddress) {
+ leading+=IPADDR_SRC;
+ if(((IpAddress)src_addr).getIpAddress() == null) {
+ leading+=SRC_HOST_NULL;
+ }
+ }
+ }
+ if(buf != null)
+ leading+=BUF_SET;
+
+ // 1. write the leading byte first
+ out.write(leading);
+
+ // the flags (e.g. OOB, LOW_PRIO)
+ out.write(flags);
+
+ // 3. src_addr
+ if(src_addr != null) {
+ if(src_addr instanceof IpAddress) {
+ src_addr.writeTo(out);
+ }
+ else {
+ Util.writeAddress(src_addr, out);
+ }
+ }
+
+ // 4. buf
+ if(buf != null) {
+ out.writeInt(length);
+ out.write(buf, offset, length);
+ }
+
+ // 5. headers
+ int size=headers.size();
+ out.writeShort(size);
+ final Object[] data=headers.getRawData();
+ for(int i=0; i < data.length; i+=2) {
+ if(data[i] != null) {
+ out.writeUTF((String)data[i]);
+ writeHeader((Header)data[i+1], out);
+ }
+ }
+ }
+
+
+ public void readFrom(DataInputStream in) throws IOException, IllegalAccessException, InstantiationException {
+ int len, leading;
+ String hdr_name;
+ Header hdr;
+
+
+ // 1. read the leading byte first
+ leading=in.readByte();
+
+ flags=in.readByte();
+
+ // 2. src_addr
+ if((leading & SRC_SET) == SRC_SET) {
+ if((leading & IPADDR_SRC) == IPADDR_SRC) {
+ src_addr=new IpAddress();
+ src_addr.readFrom(in);
+ }
+ else {
+ src_addr=Util.readAddress(in);
+ }
+ if(!DISABLE_CANONICALIZATION)
+ src_addr=canonicalAddress(src_addr);
+ }
+
+ // 3. buf
+ if((leading & BUF_SET) == BUF_SET) {
+ len=in.readInt();
+ buf=new byte[len];
+ in.read(buf, 0, len);
+ length=len;
+ }
+
+ // 4. headers
+ len=in.readShort();
+ headers=createHeaders(len);
+ Object[] data=headers.getRawData();
+ int index=0;
+ for(int i=0; i < len; i++) {
+ hdr_name=in.readUTF();
+ data[index++]=hdr_name;
+ hdr=readHeader(in);
+ data[index++]=hdr;
+ // headers.putHeader(hdr_name, hdr);
+ }
+ }
+
+
+
+ /* --------------------------------- End of Interface Streamable ----------------------------- */
+
+
+
+ /* ----------------------------------- Private methods ------------------------------- */
+
+ private String flagsToString() {
+ StringBuilder sb=new StringBuilder();
+ boolean first=true;
+ if(isFlagSet(OOB)) {
+ first=false;
+ sb.append("OOB");
+ }
+ if(isFlagSet(LOW_PRIO)) {
+ if(!first)
+ sb.append("|");
+ else
+ first=false;
+ sb.append("LOW_PRIO");
+ }
+ if(isFlagSet(HIGH_PRIO)) {
+ if(!first)
+ sb.append("|");
+ else
+ first=false;
+ sb.append("HIGH_PRIO");
+ }
+ return sb.toString();
+ }
+
+ private static void writeHeader(Header value, DataOutputStream out) throws IOException {
+ short magic_number;
+ String classname;
+ ObjectOutputStream oos=null;
+ int size=value.size();
+ try {
+ magic_number=ClassConfigurator.getInstance(false).getMagicNumber(value.getClass());
+ // write the magic number or the class name
+ out.writeShort(magic_number);
+ if(magic_number == -1) {
+ classname=value.getClass().getName();
+ out.writeUTF(classname);
+ if(log.isWarnEnabled())
+ log.warn("magic number for " + classname + " not found, make sure you add your header to " +
+ "jg-magic-map.xml, or register it programmatically with the ClassConfigurator");
+ }
+
+ out.writeShort(size);
+
+ // write the contents
+ if(value instanceof Streamable) {
+ ((Streamable)value).writeTo(out);
+ }
+ else {
+ oos=new ObjectOutputStream(out);
+ value.writeExternal(oos);
+ if(!nonStreamableHeaders.contains(value.getClass())) {
+ nonStreamableHeaders.add(value.getClass());
+ if(log.isTraceEnabled())
+ log.trace("encountered non-Streamable header: " + value.getClass());
+ }
+ }
+ }
+ catch(ChannelException e) {
+ IOException io_ex=new IOException("failed writing header");
+ io_ex.initCause(e);
+ throw io_ex;
+ }
+ finally {
+ if(oos != null)
+ oos.close(); // this is a no-op on ByteArrayOutputStream
+ }
+ }
+
+
+ private static Header readHeader(DataInputStream in) throws IOException {
+ Header hdr;
+ short magic_number;
+ String classname;
+ Class clazz;
+ ObjectInputStream ois=null;
+
+ try {
+ magic_number=in.readShort();
+ if(magic_number != -1) {
+ clazz=ClassConfigurator.getInstance(false).get(magic_number);
+ if(clazz == null)
+ throw new IllegalArgumentException("magic number " + magic_number + " is not available in magic map");
+ }
+ else {
+ classname=in.readUTF();
+ clazz=ClassConfigurator.getInstance(false).get(classname);
+ }
+
+ in.readShort(); // we discard the size since we don't use it
+
+ hdr=(Header)clazz.newInstance();
+ if(hdr instanceof Streamable) {
+ ((Streamable)hdr).readFrom(in);
+ }
+ else {
+ ois=new ObjectInputStream(in);
+ hdr.readExternal(ois);
+ }
+ }
+ catch(Exception ex) {
+ IOException io_ex=new IOException("failed reading header");
+ io_ex.initCause(ex);
+ throw io_ex;
+ }
+ return hdr;
+ }
+
+ private static Headers createHeaders(int size) {
+ return size > 0? new Headers(size) : new Headers(3);
+ }
+
+
+ private static Headers createHeaders(Headers m) {
+ return new Headers(m);
+ }
+
+ /** canonicalize addresses to some extent. There are race conditions
+ * allowed in this method, so it may not fully canonicalize an address
+ * @param nonCanonicalAddress
+ * @return canonical representation of the address
+ */
+ private static Address canonicalAddress(Address nonCanonicalAddress) {
+ Address result=null;
+ if(nonCanonicalAddress == null) {
+ return null;
+ }
+ // do not synchronize between get/put on the canonical map to avoid cost of contention
+ // this can allow multiple equivalent addresses to leak out, but it's worth the cost savings
+ try {
+ result=canonicalAddresses.putIfAbsent(nonCanonicalAddress, nonCanonicalAddress);
+ return result != null? result : nonCanonicalAddress;
+ }
+ catch(NullPointerException npe) {
+ // no action needed
+ }
+ return result;
+ }
+
+ /* ------------------------------- End of Private methods ---------------------------- */
+
+
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/MessageListener.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/MessageListener.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/MessageListener.java 17 Aug 2012 14:51:05 -0000 1.1
@@ -0,0 +1,30 @@
+// $Id: MessageListener.java,v 1.1 2012/08/17 14:51:05 marcin Exp $
+
+package org.jgroups;
+
+/**
+ * Allows a listener to be notified when a message arrives.
+ * Contrary to the pull-style of channels, some building blocks
+ * (e.g., {@link org.jgroups.blocks.PullPushAdapter}) provide an
+ * event-like, push-style message delivery model.
+ * In this case, the entity to be notified of message reception needs to
+ * provide a callback to be invoked whenever a message has been received.
+ * The MessageListener interface provides a method to do so.
+ */
+public interface MessageListener {
+ /**
+ * Called when a message is received.
+ * @param msg
+ */
+ void receive(Message msg);
+ /**
+ * Answers the group state; e.g., when joining.
+ * @return byte[]
+ */
+ byte[] getState();
+ /**
+ * Sets the group state; e.g., when joining.
+ * @param state
+ */
+ void setState(byte[] state);
+}
Index: 3rdParty_sources/jgroups/org/jgroups/Receiver.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/Receiver.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/Receiver.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,9 @@
+package org.jgroups;
+
+/**
+ * Defines the callbacks that are invoked when messages, views etc are received on a channel
+ * @author Bela Ban
+ * @version $Id: Receiver.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+ */
+public interface Receiver extends MessageListener, MembershipListener {
+}
Index: 3rdParty_sources/jgroups/org/jgroups/ReceiverAdapter.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/ReceiverAdapter.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/ReceiverAdapter.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,27 @@
+package org.jgroups;
+
+/**
+ * @author Bela Ban
+ * @version $Id: ReceiverAdapter.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+ */
+public class ReceiverAdapter implements Receiver {
+
+ public void receive(Message msg) {
+ }
+
+ public byte[] getState() {
+ return null;
+ }
+
+ public void setState(byte[] state) {
+ }
+
+ public void viewAccepted(View new_view) {
+ }
+
+ public void suspect(Address suspected_mbr) {
+ }
+
+ public void block() {
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/SetStateEvent.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/SetStateEvent.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/SetStateEvent.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,31 @@
+// $Id: SetStateEvent.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+
+package org.jgroups;
+
+
+
+
+
+
+/**
+ * Encapsulates a state returned by Channel.receive()
, as requested by
+ * Channel.getState(s)
previously.
+ * @author Bela Ban
+ * @version $Id: SetStateEvent.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+ */
+public class SetStateEvent {
+ byte[] state=null;
+ String state_id=null;
+
+ public SetStateEvent(byte[] state, String state_id) {
+ this.state=state;
+ this.state_id=state_id;
+ }
+
+
+ public byte[] getArg() {return state;}
+ public String getStateId() {return state_id;}
+
+ public String toString() {return "SetStateEvent[state=" + state + ", state_id=" + state_id + ']';}
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/StateTransferException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/StateTransferException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/StateTransferException.java 17 Aug 2012 14:51:05 -0000 1.1
@@ -0,0 +1,28 @@
+package org.jgroups;
+
+
+/**
+ * StateTransferException
is thrown to indicate failure of
+ * state transfer between cluster members.
+ *
+ *
+ * @author Vladimir Blagojevic
+ * @since 2.6
+ *
+ */
+public class StateTransferException extends ChannelException {
+
+ private static final long serialVersionUID = -4070956583392020498L;
+
+ public StateTransferException(){
+ }
+
+ public StateTransferException(String reason){
+ super(reason);
+ }
+
+ public StateTransferException(String reason,Throwable cause){
+ super(reason, cause);
+ }
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/StreamingGetStateEvent.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/StreamingGetStateEvent.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/StreamingGetStateEvent.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,88 @@
+package org.jgroups;
+
+import java.io.OutputStream;
+
+/**
+ *
+ * Represents an event returned by channel.receive()
, as a result
+ * of another channel instance requesting a state from this channel. Other channel
+ * has to invoke channel.getState()
indicating intent of state
+ * retrieval.
+ *
+ *
+ *
+ * Allows applications using a channel in a pull mode to receive
+ * StreamingGetStateEvent
event and thus provide state to requsting
+ * channel instance. Channels have to be configured with
+ * STREAMING_STATE_TRANSFER
protocol rather than the default
+ * STATE_TRANSFER
protocol in order to receive this event
+ *
+ *
+ *
+ * The following code demonstrates how to pull events from a channel, processing
+ * StreamingGetStateEvent
and sending hypothetical state through
+ * OutputStream
reference.
+ *
+ *
+ * Object obj=channel.receive(0);
+ * if(obj instanceof StreamingGetStateEvent) {
+ * StreamingGetStateEvent evt=(StreamingGetStateEvent)obj;
+ * OutputStream oos = null;
+ * try {
+ * oos = new ObjectOutputStream(evt.getArg());
+ * oos.writeObject(state);
+ * oos.flush();
+ * } catch (Exception e) {}
+ * finally
+ * {
+ * try {
+ * oos.close();
+ * } catch (IOException e) {
+ * System.err.println(e);
+ * }
+ * }
+ * }
+ *
+ *
+ *
+ * @author Vladimir Blagojevic
+ * @see org.jgroups.JChannel#getState(Address, long)
+ * @see org.jgroups.StreamingMessageListener#getState(OutputStream)
+ * @since 2.4
+ *
+ */
+
+public class StreamingGetStateEvent {
+
+ OutputStream os;
+ String state_id;
+
+ public StreamingGetStateEvent(OutputStream os,String state_id) {
+ super();
+ this.os=os;
+ this.state_id=state_id;
+ }
+ /**
+ * Returns OutputStream used for writing of a state.
+ *
+ * @return the OutputStream
+ */
+ public OutputStream getArg()
+ {
+ return os;
+ }
+
+ /**
+ * Returns id of the partial state if partial state was requested.
+ * If full state transfer was requested this method will return null.
+ *
+ * @see JChannel#getState(Address, long)
+ * @see JChannel#getState(Address, String, long)
+ * @return partial state id
+ */
+ public String getStateId()
+ {
+ return state_id;
+ }
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/StreamingSetStateEvent.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/StreamingSetStateEvent.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/StreamingSetStateEvent.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,83 @@
+package org.jgroups;
+import java.io.InputStream;
+/**
+ *
+ * Represents an event returned by channel.receive()
, as requested by
+ * channel.getState()
previously.
+ *
+ *
+ *
+ * Allows applications using a channel in a pull mode to receive a state from
+ * another channel instance providing state. Channels have to be configured with
+ * STREAMING_STATE_TRANSFER
protocol rather than the default
+ * STATE_TRANSFER
protocol in order to receive this event.
+ *
+ *
+ *
+ * The following code demonstrate how to pull events from a channel, processing
+ * StreamingSetStateEvent
and retrieving hypothetical state in the
+ * form of LinkedList from event's InputStream
reference.
+ *
+ *
+ * Object obj=channel.receive(0);
+ * if(obj instanceof StreamingSetStateEvent) {
+ * StreamingSetStateEvent evt=(StreamingSetStateEvent)obj;
+ * ObjectInputStream ois = null;
+ * try {
+ * ois = new ObjectInputStream(evt.getArg());
+ * state = (LinkedList)ois.readObject();
+ * } catch (Exception e) {}
+ * finally
+ * {
+ * try {
+ * ois.close();
+ * } catch (IOException e) {
+ * System.err.println(e);
+ * }
+ * }
+ * }
+ *
+ *
+ *
+ * @author Vladimir Blagojevic
+ * @see org.jgroups.JChannel#getState(Address, long)
+ * @see org.jgroups.StreamingMessageListener#setState(InputStream)
+ * @since 2.4
+ *
+ */
+public class StreamingSetStateEvent {
+
+ InputStream is;
+ String state_id;
+
+ public StreamingSetStateEvent(InputStream is,String state_id) {
+ super();
+ this.is=is;
+ this.state_id=state_id;
+ }
+
+ /**
+ * Returns InputStream used for reading of a state.
+ *
+ * @return the InputStream
+ */
+ public InputStream getArg()
+ {
+ return is;
+ }
+
+
+ /**
+ * Returns id of the partial state if partial state was requested.
+ * If full state transfer was requested this method will return null.
+ *
+ * @see JChannel#getState(Address, long)
+ * @see JChannel#getState(Address, String, long)
+ * @return partial state id
+ */
+ public String getStateId()
+ {
+ return state_id;
+ }
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/SuspectEvent.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/SuspectEvent.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/SuspectEvent.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,16 @@
+// $Id: SuspectEvent.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+
+package org.jgroups;
+
+/**
+ * Represents a suspect event.
+ * Gives access to the suspected member.
+ */
+public class SuspectEvent {
+ final Object suspected_mbr;
+
+ public SuspectEvent(Object suspected_mbr) {this.suspected_mbr=suspected_mbr;}
+
+ public Object getMember() {return suspected_mbr;}
+ public String toString() {return "SuspectEvent";}
+}
Index: 3rdParty_sources/jgroups/org/jgroups/SuspectedException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/SuspectedException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/SuspectedException.java 17 Aug 2012 14:51:03 -0000 1.1
@@ -0,0 +1,17 @@
+// $Id: SuspectedException.java,v 1.1 2012/08/17 14:51:03 marcin Exp $
+
+package org.jgroups;
+
+/**
+ * Thrown if a message is sent to a suspected member.
+ */
+public class SuspectedException extends Exception {
+ final Object suspect;
+
+ private static final long serialVersionUID=-6663279911010545655L;
+
+ public SuspectedException() {this.suspect=null;}
+ public SuspectedException(Object suspect) {this.suspect=suspect;}
+
+ public String toString() {return "SuspectedException";}
+}
Index: 3rdParty_sources/jgroups/org/jgroups/TimeoutException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/TimeoutException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/TimeoutException.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,23 @@
+// $Id: TimeoutException.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+
+package org.jgroups;
+
+/**
+ * Thrown if members fail to respond in time.
+ */
+public class TimeoutException extends Exception {
+ private static final long serialVersionUID = -3555655828017487825L;
+
+ public TimeoutException() {
+ super("TimeoutException");
+ }
+
+ public TimeoutException(String msg) {
+ super(msg);
+ }
+
+
+ public String toString() {
+ return super.toString();
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/Transport.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/Transport.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/Transport.java 17 Aug 2012 14:51:03 -0000 1.1
@@ -0,0 +1,18 @@
+// $Id: Transport.java,v 1.1 2012/08/17 14:51:03 marcin Exp $
+
+package org.jgroups;
+
+/**
+ * Defines a very small subset of the functionality of a channel,
+ * essentially only the methods for sending and receiving messages.
+ * Many building blocks require nothing else than a
+ * bare-bones facility to send and receive messages; therefore the Transport
+ * interface was created. It increases the genericness and portability of
+ * building blocks: being so simple, the Transport interface can easily be
+ * ported to a different toolkit, without requiring any modifications to
+ * building blocks.
+ */
+public interface Transport {
+ void send(Message msg) throws Exception;
+ Object receive(long timeout) throws Exception;
+}
Index: 3rdParty_sources/jgroups/org/jgroups/UnblockEvent.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/UnblockEvent.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/UnblockEvent.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,10 @@
+package org.jgroups;
+
+/**
+ * Trivial object that represents a block event.
+ * @author Bela Ban
+ * @version $Id: UnblockEvent.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+ */
+public class UnblockEvent {
+ public String toString() {return "UnblockEvent";}
+}
Index: 3rdParty_sources/jgroups/org/jgroups/UpHandler.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/UpHandler.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/UpHandler.java 17 Aug 2012 14:51:03 -0000 1.1
@@ -0,0 +1,14 @@
+// $Id: UpHandler.java,v 1.1 2012/08/17 14:51:03 marcin Exp $
+
+package org.jgroups;
+
+/**
+ * Provides a way of taking over a channel's tasks.
+ */
+public interface UpHandler {
+ /**
+ * Invoked for all channel events except connection management and state transfer.
+ * @param evt
+ */
+ Object up(Event evt);
+}
Index: 3rdParty_sources/jgroups/org/jgroups/Version.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/Version.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/Version.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,122 @@
+
+
+
+package org.jgroups;
+
+import org.jgroups.annotations.Immutable;
+
+/**
+ * We're using the scheme described at http://www.jboss.com/index.html?module=bb&op=viewtopic&t=77231
+ * for major, minor and micro version numbers. We have 5 bits for major and minor version numbers each and
+ * 6 bits for the micro version.
+ * This gives:
+ * X = 0-31 for major versions
+ * Y = 0-31 for minor versions
+ * Z = 0-63 for micro versions
+ *
+ * @author Bela Ban
+ * @version $Id: Version.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+ * Holds version information for JGroups.
+ */
+@Immutable
+public class Version {
+ public static final short major = 2;
+ public static final short minor = 6;
+ public static final short micro = 10;
+ public static final String description="2.6.10.GA";
+
+ public static final short version=encode(major, minor, micro);
+ public static final String string_version=print(version);
+ public static final String cvs="$Id: Version.java,v 1.1 2012/08/17 14:51:04 marcin Exp $";
+
+ private static final int MAJOR_SHIFT = 11;
+ private static final int MINOR_SHIFT = 6;
+ private static final int MAJOR_MASK = 0x00f800; // 1111100000000000 bit mask
+ private static final int MINOR_MASK = 0x0007c0; // 11111000000 bit mask
+ private static final int MICRO_MASK = 0x00003f; // 111111 bit mask
+
+
+
+ /**
+ * Prints the value of the description and cvs fields to System.out.
+ * @param args
+ */
+ public static void main(String[] args) {
+ System.out.println("\nVersion: " + description);
+ System.out.println("CVS: " + cvs + "\n");
+ }
+
+
+ /**
+ * Returns the catenation of the description and cvs fields.
+ * @return String with description
+ */
+ public static String printDescription() {
+ return "JGroups " + description + " [" + cvs + "]";
+ }
+
+ /**
+ * Returns the version field as a String.
+ * @return String with version
+ */
+ public static String printVersion() {
+ return string_version;
+ }
+
+
+ /**
+ * Compares the specified version number against the current version number.
+ * @param v short
+ * @return Result of == operator.
+ */
+ public static boolean isSame(short v) {
+ return version == v;
+ }
+
+ /** Method copied from http://www.jboss.com/index.html?module=bb&op=viewtopic&t=77231 */
+ public static short encode(int major, int minor, int micro) {
+ return (short)((major << MAJOR_SHIFT) + (minor << MINOR_SHIFT) + micro);
+ }
+
+ /** Method copied from http://www.jboss.com/index.html?module=bb&op=viewtopic&t=77231 */
+ public static String print(short version) {
+ int major=(version & MAJOR_MASK) >> MAJOR_SHIFT;
+ int minor=(version & MINOR_MASK) >> MINOR_SHIFT;
+ int micro=(version & MICRO_MASK);
+ return major + "." + minor + "." + micro;
+ }
+
+
+ public static short[] decode(short version) {
+ short major=(short)((version & MAJOR_MASK) >> MAJOR_SHIFT);
+ short minor=(short)((version & MINOR_MASK) >> MINOR_SHIFT);
+ short micro=(short)(version & MICRO_MASK);
+ return new short[]{major, minor, micro};
+ }
+
+ /**
+ * Checks whether ver is binary compatible with the current version. The rule for binary compatibility is that
+ * the major and minor versions have to match, whereas micro versions can differ.
+ * @param ver
+ * @return
+ */
+ public static boolean isBinaryCompatible(short ver) {
+ if(ver == version)
+ return true;
+ short[] tmp=decode(ver);
+ short tmp_major=tmp[0], tmp_minor=tmp[1];
+ return major == tmp_major && minor == tmp_minor;
+ }
+
+
+ public static boolean isBinaryCompatible(short ver1, short ver2) {
+ if(ver1 == ver2)
+ return true;
+ short[] tmp=decode(ver1);
+ short tmp_major=tmp[0], tmp_minor=tmp[1];
+ tmp=decode(ver2);
+ short tmp_major2=tmp[0], tmp_minor2=tmp[1];
+ return tmp_major == tmp_major2 && tmp_minor == tmp_minor2;
+ }
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/View.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/View.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/View.java 17 Aug 2012 14:51:04 -0000 1.1
@@ -0,0 +1,296 @@
+
+package org.jgroups;
+
+
+import org.jgroups.util.Streamable;
+import org.jgroups.util.Util;
+
+import java.io.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+
+/**
+ * A view is a local representation of the current membership of a group.
+ * Only one view is installed in a channel at a time.
+ * Views contain the address of its creator, an ID and a list of member addresses.
+ * These adresses are ordered, and the first address is always the coordinator of the view.
+ * This way, each member of the group knows who the new coordinator will be if the current one
+ * crashes or leaves the group.
+ * The views are sent between members using the VIEW_CHANGE event
+ * @author Bela Ban
+ * @version $Id: View.java,v 1.1 2012/08/17 14:51:04 marcin Exp $
+ */
+public class View implements Externalizable, Cloneable, Streamable {
+ /* A view is uniquely identified by its ViewID
+ * The view id contains the creator address and a Lamport time.
+ * The Lamport time is the highest timestamp seen or sent from a view.
+ * if a view change comes in with a lower Lamport time, the event is discarded.
+ */
+ protected ViewId vid=null;
+
+ /**
+ * A list containing all the members of the view
+ * This list is always ordered, with the coordinator being the first member.
+ * the second member will be the new coordinator if the current one disappears
+ * or leaves the group.
+ */
+ protected Vector members=null;
+
+ protected Map payload=null;
+ private static final long serialVersionUID=7027860705519930293L;
+
+
+ /**
+ * creates an empty view, should not be used
+ */
+ public View() {
+ }
+
+
+ /**
+ * Creates a new view
+ *
+ * @param vid The view id of this view (can not be null)
+ * @param members Contains a list of all the members in the view, can be empty but not null.
+ */
+ public View(ViewId vid, Vector members) {
+ this.vid=vid;
+ this.members=members;
+ }
+
+
+ /**
+ * Creates a new view
+ *
+ * @param creator The creator of this view (can not be null)
+ * @param id The lamport timestamp of this view
+ * @param members Contains a list of all the members in the view, can be empty but not null.
+ */
+ public View(Address creator, long id, Vector members) {
+ this(new ViewId(creator, id), members);
+ }
+
+
+ /**
+ * returns the view ID of this view
+ * if this view was created with the empty constructur, null will be returned
+ *
+ * @return the view ID of this view
+ */
+ public ViewId getVid() {
+ return vid;
+ }
+
+ /**
+ * returns the creator of this view
+ * if this view was created with the empty constructur, null will be returned
+ *
+ * @return the creator of this view in form of an Address object
+ */
+ public Address getCreator() {
+ return vid != null ? vid.getCoordAddress() : null;
+ }
+
+ /**
+ * Returns a reference to the List of members (ordered)
+ * Do NOT change this list, hence your will invalidate the view
+ * Make a copy if you have to modify it.
+ *
+ * @return a reference to the ordered list of members in this view
+ */
+ public Vector getMembers() {
+ return Util.unmodifiableVector(members);
+ }
+
+ /**
+ * returns true, if this view contains a certain member
+ *
+ * @param mbr - the address of the member,
+ * @return true if this view contains the member, false if it doesn't
+ * if the argument mbr is null, this operation returns false
+ */
+ public boolean containsMember(Address mbr) {
+ return !(mbr == null || members == null) && members.contains(mbr);
+ }
+
+
+ public boolean equals(Object obj) {
+ if(!(obj instanceof View))
+ return false;
+ if(vid != null) {
+ int rc=vid.compareTo(((View)obj).vid);
+ if(rc != 0)
+ return false;
+ if(members != null && ((View)obj).members != null) {
+ return members.equals(((View)obj).members);
+ }
+ }
+ else {
+ if(((View)obj).vid == null)
+ return true;
+ }
+ return false;
+ }
+
+
+ public int hashCode() {
+ return vid != null? vid.hashCode() : 0;
+ }
+
+ /**
+ * returns the number of members in this view
+ *
+ * @return the number of members in this view 0..n
+ */
+ public int size() {
+ return members == null ? 0 : members.size();
+ }
+
+
+ /**
+ * creates a copy of this view
+ *
+ * @return a copy of this view
+ */
+ public Object clone() {
+ ViewId vid2=vid != null ? (ViewId)vid.clone() : null;
+ Vector members2=members != null ? new Vector(members) : null;
+ return new View(vid2, members2);
+ }
+
+
+ /**
+ * debug only
+ */
+ public String printDetails() {
+ StringBuilder ret=new StringBuilder();
+ ret.append(vid).append("\n\t");
+ if(members != null) {
+ for(int i=0; i < members.size(); i++) {
+ ret.append(members.elementAt(i)).append("\n\t");
+ }
+ ret.append('\n');
+ }
+ return ret.toString();
+ }
+
+ /**
+ * Adds a key and value to the view. Since the payloads will be shipped around *with* the view, so the keys and
+ * values need to be serializable. Note that the total serialized size of all keys and values cannot
+ * exceed 65000 bytes !
+ * @param key
+ * @param value
+ */
+ public void addPayload(String key, Object value) {
+ if(payload == null) {
+ payload=new HashMap(7);
+ }
+ payload.put(key, value);
+ }
+
+ public Object getPayload(String key) {
+ if(payload != null)
+ return payload.get(key);
+ return null;
+ }
+
+
+ public String toString() {
+ StringBuilder ret=new StringBuilder(64);
+ ret.append(vid).append(" ").append(members);
+ return ret.toString();
+ }
+
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject(vid);
+ out.writeObject(members);
+ if(payload != null && !payload.isEmpty()) {
+ out.writeBoolean(true);
+ out.writeObject(payload);
+ }
+ else {
+ out.writeBoolean(false);
+ }
+ }
+
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ vid=(ViewId)in.readObject();
+ members=(Vector)in.readObject();
+ if(in.readBoolean()) {
+ payload=(Map)in.readObject();
+ }
+ }
+
+
+ public void writeTo(DataOutputStream out) throws IOException {
+ // vid
+ if(vid != null) {
+ out.writeBoolean(true);
+ vid.writeTo(out);
+ }
+ else
+ out.writeBoolean(false);
+
+ // members:
+ Util.writeAddresses(members, out);
+
+ if(payload != null && !payload.isEmpty()) {
+ try {
+ byte buffer[]=Util.objectToByteBuffer(payload);
+ out.writeShort(buffer.length);
+ out.write(buffer, 0, buffer.length);
+ }
+ catch(Exception e) {
+ throw new IOException("could not write View payload");
+ }
+ }
+ else {
+ out.writeShort(0);
+ }
+ }
+
+
+ public void readFrom(DataInputStream in) throws IOException, IllegalAccessException, InstantiationException {
+ boolean b;
+ // vid:
+ b=in.readBoolean();
+ if(b) {
+ vid=new ViewId();
+ vid.readFrom(in);
+ }
+
+ // members:
+ members=(Vector)Util.readAddresses(in, Vector.class);
+
+ short payloadLength=in.readShort();
+ if(payloadLength > 0) {
+ byte[] buffer=new byte[payloadLength];
+ in.read(buffer);
+ try {
+ payload=(Map)Util.objectFromByteBuffer(buffer);
+ }
+ catch(Exception e) {
+ throw new IOException("Could not read View payload " + buffer.length);
+ }
+ }
+ }
+
+ public int serializedSize() {
+ int retval=Global.BYTE_SIZE; // presence for vid
+ if(vid != null)
+ retval+=vid.serializedSize();
+ retval+=Util.size(members);
+
+ retval+=Global.SHORT_SIZE; // presence for payload
+ if(payload != null) {
+ retval+=Util.sizeOf(payload);
+ }
+ return retval;
+ }
+
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/ViewId.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/ViewId.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/ViewId.java 17 Aug 2012 14:51:05 -0000 1.1
@@ -0,0 +1,144 @@
+// $Id: ViewId.java,v 1.1 2012/08/17 14:51:05 marcin Exp $
+
+package org.jgroups;
+
+import org.jgroups.util.Streamable;
+import org.jgroups.util.Util;
+
+import java.io.*;
+
+
+/**
+ * ViewIds are used for ordering views (each view has a ViewId and a list of members).
+ * Ordering between views is important for example in a virtual synchrony protocol where
+ * all views seen by a member have to be ordered.
+ */
+public class ViewId implements Externalizable, Comparable, Cloneable, Streamable {
+ Address coord_addr=null; // Address of the issuer of this view
+ long id=0; // Lamport time of the view
+
+
+ public ViewId() { // used for externalization
+ }
+
+
+ /**
+ * Creates a ViewID with the coordinator address and a Lamport timestamp of 0.
+ *
+ * @param coord_addr the address of the member that issued this view
+ */
+ public ViewId(Address coord_addr) {
+ this.coord_addr=coord_addr;
+ }
+
+ /**
+ * Creates a ViewID with the coordinator address and the given Lamport timestamp.
+ *
+ * @param coord_addr - the address of the member that issued this view
+ * @param id - the Lamport timestamp of the view
+ */
+ public ViewId(Address coord_addr, long id) {
+ this.coord_addr=coord_addr;
+ this.id=id;
+ }
+
+ /**
+ * returns the lamport time of the view
+ *
+ * @return the lamport time timestamp
+ */
+ public long getId() {
+ return id;
+ }
+
+
+ /**
+ * returns the address of the member that issued this view
+ *
+ * @return the Address of the the issuer
+ */
+ public Address getCoordAddress() {
+ return coord_addr;
+ }
+
+
+ public String toString() {
+ return "[" + coord_addr + '|' + id + ']';
+ }
+
+ /**
+ * Cloneable interface
+ * Returns a new ViewID object containing the same address and lamport timestamp as this view
+ */
+ public Object clone() {
+ return new ViewId(coord_addr, id);
+ }
+
+ /**
+ * Old Copy method, deprecated because it is substituted by clone()
+ */
+ public ViewId copy() {
+ return (ViewId)clone();
+ }
+
+ /**
+ * Establishes an order between 2 ViewIds. First compare on id. Compare on coord_addr
+ * only if necessary (i.e. ids are equal) !
+ *
+ * @return 0 for equality, value less than 0 if smaller, greater than 0 if greater.
+ */
+ public int compareTo(Object other) {
+ if(other == null) return 1; //+++ Maybe necessary to throw an exception
+
+ if(!(other instanceof ViewId)) {
+ throw new ClassCastException("ViewId.compareTo(): view id is not comparable with different Objects");
+ }
+ return id > ((ViewId)other).id ? 1 : id < ((ViewId)other).id ? -1 : 0;
+ }
+
+ /**
+ * Old Compare
+ */
+ public int compare(Object o) {
+ return compareTo(o);
+ }
+
+
+ public boolean equals(Object other_view) {
+ return compareTo(other_view) == 0;
+ }
+
+
+ public int hashCode() {
+ return (int)id;
+ }
+
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject(coord_addr);
+ out.writeLong(id);
+ }
+
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ coord_addr=(Address)in.readObject();
+ id=in.readLong();
+ }
+
+ public void writeTo(DataOutputStream out) throws IOException {
+ Util.writeAddress(coord_addr, out);
+ out.writeLong(id);
+ }
+
+ public void readFrom(DataInputStream in) throws IOException, IllegalAccessException, InstantiationException {
+ coord_addr=Util.readAddress(in);
+ id=in.readLong();
+ }
+
+ public int serializedSize() {
+ int retval=Global.LONG_SIZE; // for the id
+ retval+=Util.size(coord_addr);
+ return retval;
+ }
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/overview.html
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/overview.html,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/overview.html 17 Aug 2012 14:51:05 -0000 1.1
@@ -0,0 +1,15 @@
+
+
+
+JGroups is a toolkit for reliable group communication. Processes
+can join a group, send messages to all members or single members, and
+receive messages from members in the group. The system keeps track of
+the members in every group, and notifies group members when a new
+member joins, or an existing member leaves or crashes. A group is
+identified by its name. Groups do not have to be created explicitly;
+when a process joins a non-existing group, that group will be created
+automatically. Member processes of a group can be located on the same
+host, within the same LAN, or across a WAN. A member can be part of
+multiple groups.
+
+
\ No newline at end of file
Index: 3rdParty_sources/jgroups/org/jgroups/package.html
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/package.html,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/package.html 17 Aug 2012 14:51:03 -0000 1.1
@@ -0,0 +1,5 @@
+
+
+ Provides top-level public JGroups classes such as Channel, Message, etc.
+
+
\ No newline at end of file
Index: 3rdParty_sources/jgroups/org/jgroups/annotations/GuardedBy.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/annotations/GuardedBy.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/annotations/GuardedBy.java 17 Aug 2012 14:51:28 -0000 1.1
@@ -0,0 +1,23 @@
+package org.jgroups.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Copyright (c) 2005 Brian Goetz and Tim Peierls
+ * Released under the Creative Commons Attribution License
+ * (http://creativecommons.org/licenses/by/2.5)
+ * Official home: http://www.jcip.net
+ *
+ * Adopted from Java Concurrency in Practice. This annotation defines the monitor that protects the variable
+ * annotated by @GuardedBy, e.g. @GuardedBy("lock") or @GuardedBy("this")
+ * @author Bela Ban
+ * @version $Id: GuardedBy.java,v 1.1 2012/08/17 14:51:28 marcin Exp $
+ */
+@Target({ElementType.FIELD, ElementType.METHOD})
+@Retention(RetentionPolicy.SOURCE)
+public @interface GuardedBy {
+ String value();
+}
Index: 3rdParty_sources/jgroups/org/jgroups/annotations/Immutable.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/annotations/Immutable.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/annotations/Immutable.java 17 Aug 2012 14:51:28 -0000 1.1
@@ -0,0 +1,22 @@
+package org.jgroups.annotations;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Copyright (c) 2005 Brian Goetz and Tim Peierls
+ * Released under the Creative Commons Attribution License
+ * (http://creativecommons.org/licenses/by/2.5)
+ * Official home: http://www.jcip.net
+ *
+ * Adopted from Java Concurrency in Practice. This annotation defines an immutable class, ie. a class whose
+ * instances cannot be modified after creation
+ * @author Bela Ban
+ * @version $Id: Immutable.java,v 1.1 2012/08/17 14:51:28 marcin Exp $
+ */
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.SOURCE)
+public @interface Immutable {
+}
Index: 3rdParty_sources/jgroups/org/jgroups/auth/AuthToken.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/auth/AuthToken.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/auth/AuthToken.java 17 Aug 2012 14:51:28 -0000 1.1
@@ -0,0 +1,33 @@
+package org.jgroups.auth;
+
+import org.jgroups.util.Streamable;
+import org.jgroups.Message;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.Serializable;
+import java.util.Properties;
+/**
+ * Abstract AuthToken class used by implementations of AUTH, e.g. SimpleToken, X509Token
+ * @author Chris Mills
+ */
+public abstract class AuthToken implements Serializable, Streamable{
+ protected final Log log = LogFactory.getLog(this.getClass());
+ /**
+ * Used to return the full package and class name of the implementation. This is used by the AUTH protocol to create an instance of the implementation.
+ * @return a java.lang.String object of the package and class name
+ */
+ public abstract String getName();
+ /**
+ * Called during the setup of the AUTH protocol to pass property values from the JGroups config XML document to the implementing class.
+ * @param properties a java.util.Properties object of config parameters
+ */
+ public abstract void setValue(Properties properties);
+ /**
+ * This method should be implemented to perform the actual authentication of joining members.
+ * @param token the token sent by the joiner
+ * @param msg the Message object containing the actual JOIN_REQ
+ * @return true if authenticaion passed or false if it failed.
+ */
+ public abstract boolean authenticate(AuthToken token, Message msg);
+}
Index: 3rdParty_sources/jgroups/org/jgroups/auth/FixedMembershipToken.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/auth/FixedMembershipToken.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/auth/FixedMembershipToken.java 17 Aug 2012 14:51:28 -0000 1.1
@@ -0,0 +1,128 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This 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 software 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 software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jgroups.auth;
+
+import org.jgroups.Message;
+import org.jgroups.util.Util;
+
+import java.util.Properties;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.DataInputStream;
+
+/**
+ *
+ * The FixedMemberShipToken object predefines a list of IP addresses and Ports that can join the group.
+ *
+ *
+ * Configuration parameters for this example are shown below:
+ *
+ *
+ * fixed_members_value (required) = List of IP addresses & ports (optionally) - ports must be seperated by a '/' e.g. 127.0.0.1/1010*127.0.0.1/4567
+ * fixed_members_seperator (required) = The seperator used between IP addresses - e.g. *
+ *
+ * @author Chris Mills (millsy@jboss.com)
+ */
+public class FixedMembershipToken extends AuthToken {
+ private static final String FIXED_MEMBERS_ATTR = "fixed_members_value";
+ private static final String FIXED_MEMBERS_SEPERATOR_ATTR = "fixed_members_seperator";
+
+ private List memberList = null;
+ private String token = "emptyToken";
+
+ public FixedMembershipToken(){
+ }
+
+ public String getName(){
+ return "org.jgroups.auth.FixedMembershipToken";
+ }
+
+ public boolean authenticate(AuthToken token, Message msg){
+ if((token != null) && (token instanceof FixedMembershipToken) && (this.memberList != null)){
+ //Found a valid Token to authenticate against
+ FixedMembershipToken serverToken = (FixedMembershipToken) token;
+
+ String sourceAddressWithPort = msg.getSrc().toString();
+ String sourceAddressWithoutPort = sourceAddressWithPort.substring(0, sourceAddressWithPort.indexOf(":"));
+
+ if(log.isDebugEnabled()){
+ log.debug("AUTHToken received from " + sourceAddressWithPort);
+ }
+
+ if((this.memberList.contains(sourceAddressWithPort)) || (this.memberList.contains(sourceAddressWithoutPort))){
+ //validated
+ if(log.isDebugEnabled()){
+ log.debug("FixedMembershipToken match");
+ }
+ return true;
+ }else{
+ if(log.isWarnEnabled()){
+ log.warn("Authentication failed on FixedMembershipToken");
+ }
+ return false;
+ }
+ }
+
+ if(log.isWarnEnabled()){
+ log.warn("Invalid AuthToken instance - wrong type or null");
+ }
+ return false;
+ }
+
+ public void setValue(Properties properties){
+ memberList = new ArrayList();
+ StringTokenizer memberListTokenizer = new StringTokenizer((String)properties.get(FixedMembershipToken.FIXED_MEMBERS_ATTR),
+ (String)properties.get(FixedMembershipToken.FIXED_MEMBERS_SEPERATOR_ATTR));
+ while(memberListTokenizer.hasMoreTokens()){
+ memberList.add(memberListTokenizer.nextToken().replace('/', ':'));
+ }
+ properties.remove(FixedMembershipToken.FIXED_MEMBERS_ATTR);
+ properties.remove(FixedMembershipToken.FIXED_MEMBERS_SEPERATOR_ATTR);
+ }
+ /**
+ * Required to serialize the object to pass across the wire
+ * @param out
+ * @throws java.io.IOException
+ */
+ public void writeTo(DataOutputStream out) throws IOException {
+ if(log.isDebugEnabled()){
+ log.debug("SimpleToken writeTo()");
+ }
+ Util.writeString(this.token, out);
+ }
+ /**
+ * Required to deserialize the object when read in from the wire
+ * @param in
+ * @throws IOException
+ * @throws IllegalAccessException
+ * @throws InstantiationException
+ */
+ public void readFrom(DataInputStream in) throws IOException, IllegalAccessException, InstantiationException {
+ if(log.isDebugEnabled()){
+ log.debug("SimpleToken readFrom()");
+ }
+ this.token = Util.readString(in);
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/auth/MD5Token.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/auth/MD5Token.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/auth/MD5Token.java 17 Aug 2012 14:51:28 -0000 1.1
@@ -0,0 +1,123 @@
+package org.jgroups.auth;
+
+import org.jgroups.Message;
+import org.jgroups.util.Util;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ *
+ * This is an example of using a preshared token that is encrypted using an MD5/SHA hash for authentication purposes. All members of the group have to have the same string value in the JGroups config.
+ *
+ *
+ * Configuration parameters for this example are shown below:
+ *
+ *
+ * token_hash (required) = MD5(default)/SHA
+ * auth_value (required) = the string to encrypt
+ *
+ * @see org.jgroups.auth.AuthToken
+ * @author Chris Mills
+ */
+public class MD5Token extends AuthToken {
+
+ public static final String TOKEN_ATTR = "auth_value";
+ public static final String TOKEN_TYPE = "token_hash";
+
+ private String token = null;
+ private String hash_type = "MD5";
+
+ public MD5Token(){
+ //need an empty constructor
+ }
+
+ public MD5Token(String token){
+ this.token = hash(token);
+ }
+
+ public MD5Token(String token, String hash_type){
+ this.token = hash(token);
+ this.hash_type = hash_type;
+ }
+
+ public void setValue(Properties properties){
+ this.token = hash((String)properties.get(MD5Token.TOKEN_ATTR));
+ properties.remove(MD5Token.TOKEN_ATTR);
+
+ if(properties.containsKey(MD5Token.TOKEN_TYPE)){
+ hash_type = (String)properties.get(MD5Token.TOKEN_TYPE);
+ properties.remove(MD5Token.TOKEN_TYPE);
+ }
+ }
+
+ public String getName(){
+ return "org.jgroups.auth.MD5Token";
+ }
+ /**
+ * Called during setup to hash the auth_value string in to an MD5/SHA hash
+ * @param token the string to hash
+ * @return the hashed version of the string
+ */
+ private String hash(String token){
+ //perform the hashing of the token key
+ String hashedToken = null;
+
+ if(hash_type.equalsIgnoreCase("SHA")){
+ hashedToken = Util.sha(token);
+ }else{
+ hashedToken = Util.md5(token);
+ }
+
+ if(hashedToken == null){
+ //failed to encrypt
+ if(log.isWarnEnabled()){
+ log.warn("Failed to hash token - sending in clear text");
+ }
+ return token;
+ }
+ return hashedToken;
+ }
+
+ public boolean authenticate(AuthToken token, Message msg){
+
+ if((token != null) && (token instanceof MD5Token)){
+ //Found a valid Token to authenticate against
+ MD5Token serverToken = (MD5Token) token;
+
+ if((this.token != null) && (serverToken.token != null) && (this.token.equalsIgnoreCase(serverToken.token))){
+ //validated
+ if(log.isDebugEnabled()){
+ log.debug("MD5Token match");
+ }
+ return true;
+ }else{
+ if(log.isWarnEnabled()){
+ log.warn("Authentication failed on MD5Token");
+ }
+ return false;
+ }
+ }
+
+ if(log.isWarnEnabled()){
+ log.warn("Invalid AuthToken instance - wrong type or null");
+ }
+ return false;
+ }
+
+ public void writeTo(DataOutputStream out) throws IOException {
+ if(log.isDebugEnabled()){
+ log.debug("MD5Token writeTo()");
+ }
+ Util.writeString(this.token, out);
+ }
+
+ public void readFrom(DataInputStream in) throws IOException, IllegalAccessException, InstantiationException {
+ if(log.isDebugEnabled()){
+ log.debug("MD5Token readFrom()");
+ }
+ this.token = Util.readString(in);
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/auth/SimpleToken.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/auth/SimpleToken.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/auth/SimpleToken.java 17 Aug 2012 14:51:28 -0000 1.1
@@ -0,0 +1,91 @@
+package org.jgroups.auth;
+
+import org.jgroups.util.Util;
+import org.jgroups.Message;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.DataInputStream;
+import java.util.Properties;
+/**
+ *
+ * This is an example of using a preshared token for authentication purposes. All members of the group have to have the same string value in the JGroups config.
+ *
+ * JGroups config parameters:
+ *
+ * auth_value (required) = the string to encrypt
+ *
+ * @see org.jgroups.auth.AuthToken
+ * @author Chris Mills
+ */
+public class SimpleToken extends AuthToken {
+
+ public static final String TOKEN_ATTR = "auth_value";
+ private String token = null;
+
+ public SimpleToken(){
+ //need an empty constructor
+ }
+
+ public SimpleToken(String token){
+ this.token = token;
+ }
+
+ public void setValue(Properties properties){
+ this.token = (String)properties.get(SimpleToken.TOKEN_ATTR);
+ properties.remove(SimpleToken.TOKEN_ATTR);
+ }
+
+ public String getName(){
+ return "org.jgroups.auth.SimpleToken";
+ }
+
+ public boolean authenticate(AuthToken token, Message msg){
+ if((token != null) && (token instanceof SimpleToken)){
+ //Found a valid Token to authenticate against
+ SimpleToken serverToken = (SimpleToken) token;
+
+ if((this.token != null) && (serverToken.token != null) && (this.token.equalsIgnoreCase(serverToken.token))){
+ //validated
+ if(log.isDebugEnabled()){
+ log.debug("SimpleToken match");
+ }
+ return true;
+ }else{
+ if(log.isWarnEnabled()){
+ log.warn("Authentication failed on SimpleToken");
+ }
+ return false;
+ }
+ }
+
+ if(log.isWarnEnabled()){
+ log.warn("Invalid AuthToken instance - wrong type or null");
+ }
+ return false;
+ }
+ /**
+ * Required to serialize the object to pass across the wire
+ * @param out
+ * @throws IOException
+ */
+ public void writeTo(DataOutputStream out) throws IOException {
+ if(log.isDebugEnabled()){
+ log.debug("SimpleToken writeTo()");
+ }
+ Util.writeString(this.token, out);
+ }
+ /**
+ * Required to deserialize the object when read in from the wire
+ * @param in
+ * @throws IOException
+ * @throws IllegalAccessException
+ * @throws InstantiationException
+ */
+ public void readFrom(DataInputStream in) throws IOException, IllegalAccessException, InstantiationException {
+ if(log.isDebugEnabled()){
+ log.debug("SimpleToken readFrom()");
+ }
+ this.token = Util.readString(in);
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/auth/X509Token.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/auth/X509Token.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/auth/X509Token.java 17 Aug 2012 14:51:28 -0000 1.1
@@ -0,0 +1,245 @@
+package org.jgroups.auth;
+
+import org.jgroups.util.Util;
+import org.jgroups.Message;
+
+import javax.crypto.Cipher;
+import java.io.*;
+import java.util.Properties;
+import java.security.cert.X509Certificate;
+import java.security.PrivateKey;
+import java.security.KeyStore;
+/**
+ *
+ * This is an example of using a preshared token that is encrypted using an X509 certificate for authentication purposes. All members of the group have to have the same string value in the JGroups config.
+ *
+ *
+ * This example uses certificates contained within a specified keystore. Configuration parameters for this example are shown below:
+ *
+ *
+ * keystore_type = JKS(default)/PKCS12 - see http://java.sun.com/j2se/1.4.2/docs/guide/security/CryptoSpec.html#AppA
+ * keystore_path (required) = the location of the keystore
+ * keystore_password (required) = the password of the keystore
+ * cert_alias (required) = the alias of the certification within the keystore
+ * cert_password = the password of the certification within the keystore
+ * auth_value (required) = the string to encrypt
+ * cipher_type = RSA(default)/AES/Blowfish/DES/DESede/PBEWithMD5AndDES/PBEWithHmacSHA1AndDESede/RC2/RC4/RC5 - see http://java.sun.com/j2se/1.4.2/docs/guide/security/jce/JCERefGuide.html#AppA
+ *
+ * @see org.jgroups.auth.AuthToken
+ * @author Chris Mills
+ */
+public class X509Token extends AuthToken {
+
+ public static final String KEYSTORE_TYPE = "keystore_type";
+ public static final String KEYSTORE_PATH = "keystore_path";
+ public static final String KEYSTORE_PASSWORD = "keystore_password";
+ public static final String CERT_ALIAS = "cert_alias";
+ public static final String CERT_PASSWORD = "cert_password";
+ public static final String TOKEN_ATTR = "auth_value";
+ public static final String CIPHER_TYPE = "cipher_type";
+
+ private boolean valueSet = false;
+
+ private String keystore_type = null;
+ private String cert_alias = null;
+ private String keystore_path = null;
+ private String token_attr = null;
+ private String cipher_type = null;
+
+ private byte[] encryptedToken = null;
+
+ private char[] cert_password = null;
+ private char[] keystore_password = null;
+
+ private Cipher cipher = null;
+ private PrivateKey certPrivateKey = null;
+ private X509Certificate certificate = null;
+
+ public X509Token() {
+ //need an empty constructor
+ }
+
+ public void setValue(Properties properties) {
+ if(log.isDebugEnabled()){
+ log.debug("setting values on X509Token object");
+ }
+
+ if(properties.containsKey(TOKEN_ATTR)){
+ this.token_attr = (String) properties.get(TOKEN_ATTR);
+ properties.remove(TOKEN_ATTR);
+ if(log.isDebugEnabled()){
+ log.debug("token_attr = " + this.token_attr);
+ }
+ }
+
+ if(properties.containsKey(KEYSTORE_TYPE)){
+ this.keystore_type = (String) properties.get(KEYSTORE_TYPE);
+ properties.remove(KEYSTORE_TYPE);
+ if(log.isDebugEnabled()){
+ log.debug("keystore_type = " + this.keystore_type);
+ }
+ }else{
+ this.keystore_type = "JKS";
+ if(log.isDebugEnabled()){
+ log.debug("keystore_type = " + this.keystore_type);
+ }
+ }
+
+ if(properties.containsKey(KEYSTORE_PATH)){
+ this.keystore_path = (String) properties.get(KEYSTORE_PATH);
+ properties.remove(KEYSTORE_PATH);
+ if(log.isDebugEnabled()){
+ log.debug("keystore_path = " + this.keystore_path);
+ }
+ }
+
+ if(properties.containsKey(KEYSTORE_PASSWORD)){
+ this.keystore_password = ((String) properties.get(KEYSTORE_PASSWORD)).toCharArray();
+ properties.remove(KEYSTORE_PASSWORD);
+ if(log.isDebugEnabled()){
+ log.debug("keystore_password = " + this.keystore_password);
+ }
+ }
+
+ if(properties.containsKey(CERT_ALIAS)){
+ this.cert_alias = (String) properties.get(CERT_ALIAS);
+ properties.remove(CERT_ALIAS);
+ if(log.isDebugEnabled()){
+ log.debug("cert_alias = " + this.cert_alias);
+ }
+ }
+
+ if(properties.containsKey(CERT_PASSWORD)){
+ this.cert_password = ((String) properties.get(CERT_PASSWORD)).toCharArray();
+ properties.remove(CERT_PASSWORD);
+ if(log.isDebugEnabled()){
+ log.debug("cert_password = " + this.cert_password);
+ }
+ }else{
+ this.cert_password = this.keystore_password;
+ if(log.isDebugEnabled()){
+ log.debug("cert_password = " + this.cert_password);
+ }
+ }
+
+ if(properties.containsKey(CIPHER_TYPE)){
+ this.cipher_type = (String) properties.get(CIPHER_TYPE);
+ properties.remove(CIPHER_TYPE);
+ if(log.isDebugEnabled()){
+ log.debug("cipher_type = " + this.cipher_type);
+ }
+ }else{
+ this.cipher_type = "RSA";
+ if(log.isDebugEnabled()){
+ log.debug("cipher_type = " + this.cipher_type);
+ }
+ }
+
+ if(getCertificate()){
+ this.valueSet = true;
+ if(log.isDebugEnabled()){
+ log.debug("X509Token created correctly");
+ }
+ }
+ }
+
+ public String getName() {
+ return "org.jgroups.auth.X509Token";
+ }
+
+ public boolean authenticate(AuthToken token, Message msg) {
+ if (!this.valueSet) {
+ if(log.isFatalEnabled()){
+ log.fatal("X509Token not setup correctly - check token attrs");
+ }
+ return false;
+ }
+
+ if((token != null) && (token instanceof X509Token)){
+ //got a valid X509 token object
+ X509Token serverToken = (X509Token)token;
+ if(!serverToken.valueSet){
+ if(log.isFatalEnabled()){
+ log.fatal("X509Token - recieved token not valid");
+ }
+ return false;
+ }
+
+ try{
+ if(log.isDebugEnabled()){
+ log.debug("setting cipher to decrypt mode");
+ }
+ this.cipher.init(Cipher.DECRYPT_MODE, this.certPrivateKey);
+ String serverBytes = new String(this.cipher.doFinal(serverToken.encryptedToken));
+ if((serverBytes != null) && (serverBytes.equalsIgnoreCase(this.token_attr))){
+ if(log.isDebugEnabled()){
+ log.debug("X509 authentication passed");
+ }
+ return true;
+ }
+ }catch(Exception e){
+ if(log.isFatalEnabled()){
+ log.fatal(e);
+ }
+ }
+ }
+ if(log.isWarnEnabled()){
+ log.warn("X509 authentication failed");
+ }
+ return false;
+ }
+
+ public void writeTo(DataOutputStream out) throws IOException {
+ if(log.isDebugEnabled()){
+ log.debug("X509Token writeTo()");
+ }
+ Util.writeByteBuffer(this.encryptedToken, out);
+ }
+
+ public void readFrom(DataInputStream in) throws IOException, IllegalAccessException, InstantiationException {
+ if(log.isDebugEnabled()){
+ log.debug("X509Token readFrom()");
+ }
+ this.encryptedToken = Util.readByteBuffer(in);
+ this.valueSet = true;
+ }
+ /**
+ * Used during setup to get the certification from the keystore and encrypt the auth_value with the private key
+ * @return true if the certificate was found and the string encypted correctly otherwise returns false
+ */
+ private boolean getCertificate() {
+ try{
+ KeyStore store = KeyStore.getInstance(this.keystore_type);
+ java.io.FileInputStream fis = new java.io.FileInputStream(this.keystore_path);
+ store.load(fis, this.keystore_password);
+
+ this.cipher = Cipher.getInstance(this.cipher_type);
+ this.certificate = (X509Certificate) store.getCertificate(this.cert_alias);
+
+ if(log.isDebugEnabled()){
+ log.debug("certificate = " + this.certificate.toString());
+ }
+
+ this.cipher.init(Cipher.ENCRYPT_MODE, this.certificate);
+ this.encryptedToken = this.cipher.doFinal(this.token_attr.getBytes());
+
+ if(log.isDebugEnabled()){
+ log.debug("encryptedToken = " + this.encryptedToken);
+ }
+
+ KeyStore.PrivateKeyEntry privateKey = (KeyStore.PrivateKeyEntry)store.getEntry(this.cert_alias, new KeyStore.PasswordProtection(this.cert_password));
+ this.certPrivateKey = privateKey.getPrivateKey();
+
+ if(log.isDebugEnabled()){
+ log.debug("certPrivateKey = " + this.certPrivateKey.toString());
+ }
+
+ return true;
+ }catch(Exception e){
+ if(log.isFatalEnabled()){
+ log.fatal(e);
+ }
+ return false;
+ }
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/BasicConnectionTable.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/BasicConnectionTable.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/BasicConnectionTable.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,853 @@
+package org.jgroups.blocks;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jgroups.Address;
+import org.jgroups.Global;
+import org.jgroups.Version;
+import org.jgroups.stack.IpAddress;
+import org.jgroups.util.DefaultThreadFactory;
+import org.jgroups.util.PortsManager;
+import org.jgroups.util.ThreadFactory;
+import org.jgroups.util.Util;
+
+import java.io.*;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Shared class for TCP connection tables.
+ * @author Scott Marlow
+ * @author Bela Ban
+ */
+public abstract class BasicConnectionTable {
+ private ThreadFactory factory;
+ final Map conns=new HashMap(); // keys: Addresses (peer address), values: Connection
+ Receiver receiver=null;
+ boolean use_send_queues=false; // max number of messages in a send queue
+ int send_queue_size=10000;
+ InetAddress bind_addr=null;
+ Address local_addr=null; // bind_addr + port of srv_sock
+ int srv_port=7800;
+ int recv_buf_size=120000;
+ int send_buf_size=60000;
+ final Vector conn_listeners=new Vector(); // listeners to be notified when a conn is established/torn down
+ Reaper reaper=null; // closes conns that have been idle for more than n secs
+ long reaper_interval=60000; // reap unused conns once a minute
+ long conn_expire_time=300000; // connections can be idle for 5 minutes before they are reaped
+ int sock_conn_timeout=1000; // max time in millis to wait for Socket.connect() to return
+ int peer_addr_read_timeout=2000; // max time in milliseconds to block on reading peer address
+ final ThreadGroup thread_group=new ThreadGroup(Util.getGlobalThreadGroup(), "ConnectionTable");
+ protected final Log log= LogFactory.getLog(getClass());
+ final byte[] cookie={'b', 'e', 'l', 'a'};
+ boolean use_reaper=false; // by default we don't reap idle conns
+ static final int backlog=20; // 20 conn requests are queued by ServerSocket (addtl will be discarded)
+ volatile ServerSocket srv_sock=null;
+ boolean tcp_nodelay=false;
+ int linger=-1;
+
+ protected PortsManager pm=null;
+
+ /**
+ * The address which will be broadcast to the group (the externally visible address which this host should
+ * be contacted on). If external_addr is null, it will default to the same address that the server socket is bound to.
+ */
+ InetAddress external_addr=null;
+ int max_port=0; // maximum port to bind to (if < srv_port, no limit)
+ Thread acceptor=null; // continuously calls srv_sock.accept()
+ boolean running=false;
+ /** Total number of Connections created for this connection table */
+ static AtomicInteger conn_creations=new AtomicInteger(0);
+
+ final static long MAX_JOIN_TIMEOUT=Global.THREAD_SHUTDOWN_WAIT_TIME;
+
+ protected BasicConnectionTable() {
+ factory = new DefaultThreadFactory(new ThreadGroup(Util.getGlobalThreadGroup(),"ConnectionTable"),"Connection Table", false);
+ }
+
+ public final void setReceiver(Receiver r) {
+ receiver=r;
+ }
+
+ public void addConnectionListener(ConnectionListener l) {
+ if(l != null && !conn_listeners.contains(l))
+ conn_listeners.addElement(l);
+ }
+
+ public void removeConnectionListener(ConnectionListener l) {
+ if(l != null) conn_listeners.removeElement(l);
+ }
+
+ public Address getLocalAddress() {
+ if(local_addr == null)
+ local_addr=bind_addr != null ? new IpAddress(bind_addr, srv_port) : null;
+ return local_addr;
+ }
+
+ public int getSendBufferSize() {
+ return send_buf_size;
+ }
+
+ public void setSendBufferSize(int send_buf_size) {
+ this.send_buf_size=send_buf_size;
+ }
+
+ public int getReceiveBufferSize() {
+ return recv_buf_size;
+ }
+
+ public void setReceiveBufferSize(int recv_buf_size) {
+ this.recv_buf_size=recv_buf_size;
+ }
+
+ public int getSocketConnectionTimeout() {
+ return sock_conn_timeout;
+ }
+
+ public void setSocketConnectionTimeout(int sock_conn_timeout) {
+ this.sock_conn_timeout=sock_conn_timeout;
+ }
+
+ public int getPeerAddressReadTimeout() {
+ return peer_addr_read_timeout;
+ }
+
+ public void setPeerAddressReadTimeout(int peer_addr_read_timeout) {
+ this.peer_addr_read_timeout=peer_addr_read_timeout;
+ }
+
+ public int getNumConnections() {
+ return conns.size();
+ }
+
+ public static int getNumberOfConnectionCreations() {
+ return conn_creations.intValue();
+ }
+
+ public boolean getTcpNodelay() {
+ return tcp_nodelay;
+ }
+
+ public void setTcpNodelay(boolean tcp_nodelay) {
+ this.tcp_nodelay=tcp_nodelay;
+ }
+
+ public int getLinger() {
+ return linger;
+ }
+
+ public void setLinger(int linger) {
+ this.linger=linger;
+ }
+
+ public void setThreadFactory(ThreadFactory factory){
+ this.factory = factory;
+ }
+
+ public ThreadFactory getThreadFactory(){
+ return factory;
+ }
+
+ public boolean getUseSendQueues() {return use_send_queues;}
+
+ public void setUseSendQueues(boolean flag) {this.use_send_queues=flag;}
+
+ public int getSendQueueSize() {
+ return send_queue_size;
+ }
+
+ public void setSendQueueSize(int send_queue_size) {
+ this.send_queue_size=send_queue_size;
+ }
+
+ public void start() throws Exception {
+ running=true;
+ }
+
+ public void stop() {
+ running=false;
+
+ // 1. Stop the reaper
+ if(reaper != null)
+ reaper.stop();
+
+ // 2. close the server socket (this also stops the acceptor thread)
+ if(srv_sock != null) {
+ try {
+ if(pm != null) {
+ int tmp_port=srv_sock.getLocalPort();
+ pm.updatePort(tmp_port);
+ }
+ ServerSocket tmp=srv_sock;
+ srv_sock=null;
+ tmp.close();
+ if(acceptor != null)
+ Util.interruptAndWaitToDie(acceptor);
+ }
+ catch(Exception e) {
+ }
+ }
+
+ // 3. then close the connections
+ Collection connsCopy=null;
+ synchronized(conns) {
+ connsCopy=new LinkedList(conns.values());
+ conns.clear();
+ }
+ for(Connection conn:connsCopy) {
+ conn.destroy();
+ }
+ connsCopy.clear();
+ local_addr=null;
+ }
+
+ /**
+ Remove addr
from connection table. This is typically triggered when a member is suspected.
+ */
+ public void removeConnection(Address addr) {
+ Connection conn;
+
+ synchronized(conns) {
+ conn=conns.remove(addr);
+ }
+
+ if(conn != null) {
+ try {
+ conn.destroy(); // won't do anything if already destroyed
+ }
+ catch(Exception e) {
+ }
+ }
+ if(log.isTraceEnabled()) log.trace("removed " + addr + ", connections are " + toString());
+ }
+
+ /**
+ * Calls the receiver callback. We do not serialize access to this method, and it may be called concurrently
+ * by several Connection handler threads. Therefore the receiver needs to be reentrant.
+ */
+ public void receive(Address sender, byte[] data, int offset, int length) {
+ if(receiver != null) {
+ receiver.receive(sender, data, offset, length);
+ }
+ else
+ if(log.isErrorEnabled()) log.error("receiver is null (not set) !");
+ }
+
+ public String toString() {
+ StringBuilder ret=new StringBuilder();
+ Address key;
+ Connection val;
+ Entry entry;
+ HashMap copy;
+
+ synchronized(conns) {
+ copy=new HashMap(conns);
+ }
+ ret.append("local_addr=" + local_addr).append("\n");
+ ret.append("connections (" + copy.size() + "):\n");
+ for(Iterator> it=copy.entrySet().iterator(); it.hasNext();) {
+ entry=it.next();
+ key=entry.getKey();
+ val=entry.getValue();
+ ret.append("key: " + key + ": " + val + '\n');
+ }
+ ret.append('\n');
+ return ret.toString();
+ }
+
+ void notifyConnectionOpened(Address peer) {
+ if(peer == null) return;
+ for(int i=0; i < conn_listeners.size(); i++)
+ conn_listeners.elementAt(i).connectionOpened(peer);
+ }
+
+ void notifyConnectionClosed(Address peer) {
+ if(peer == null) return;
+ for(int i=0; i < conn_listeners.size(); i++)
+ conn_listeners.elementAt(i).connectionClosed(peer);
+ }
+
+ void addConnection(Address peer, Connection c) {
+ synchronized (conns) {
+ conns.put(peer, c);
+ }
+ if(reaper != null && !reaper.isRunning())
+ reaper.start();
+ }
+
+ public void send(Address dest, byte[] data, int offset, int length) throws Exception {
+ Connection conn;
+ if(dest == null) {
+ if(log.isErrorEnabled())
+ log.error("destination is null");
+ return;
+ }
+
+ if(data == null) {
+ log.warn("data is null; discarding packet");
+ return;
+ }
+
+ if(!running) {
+ if(log.isWarnEnabled())
+ log.warn("connection table is not running, discarding message to " + dest);
+ return;
+ }
+
+ if(dest.equals(local_addr)) {
+ receive(local_addr, data, offset, length);
+ return;
+ }
+
+ // 1. Try to obtain correct Connection (or create one if not yet existent)
+ try {
+ conn=getConnection(dest);
+ if(conn == null) return;
+ }
+ catch(Throwable ex) {
+ throw new Exception("connection to " + dest + " could not be established", ex);
+ }
+
+ // 2. Send the message using that connection
+ try {
+ conn.send(data, offset, length);
+ }
+ catch(Throwable ex) {
+ if(log.isTraceEnabled())
+ log.trace("sending msg to " + dest + " failed (" + ex.getClass().getName() + "); removing from connection table", ex);
+ removeConnection(dest);
+ }
+ }
+
+ abstract Connection getConnection(Address dest) throws Exception;
+
+ /**
+ * Removes all connections from ConnectionTable which are not in current_mbrs
+ * @param current_mbrs
+ */
+ public void retainAll(Collection current_mbrs) {
+ if(current_mbrs == null) return;
+ HashMap copy;
+ synchronized(conns) {
+ copy=new HashMap(conns);
+ conns.keySet().retainAll(current_mbrs);
+ }
+ copy.keySet().removeAll(current_mbrs);
+
+ //destroy orphaned connection i.e. connections
+ //to members that are not in current view
+ for(Connection orphanConnection:copy.values()){
+ if (log.isTraceEnabled())
+ log.trace("At " + local_addr + " destroying orphan to "
+ + orphanConnection.getPeerAddress());
+ orphanConnection.destroy();
+ }
+ copy.clear();
+ }
+
+
+
+ /** Used for message reception. */
+ public interface Receiver {
+ void receive(Address sender, byte[] data, int offset, int length);
+ }
+
+ /** Used to be notified about connection establishment and teardown. */
+ public interface ConnectionListener {
+ void connectionOpened(Address peer_addr);
+ void connectionClosed(Address peer_addr);
+ }
+
+ class Connection implements Runnable {
+ Socket sock=null; // socket to/from peer (result of srv_sock.accept() or new Socket())
+ String sock_addr=null; // used for Thread.getName()
+ DataOutputStream out=null; // for sending messages
+ DataInputStream in=null; // for receiving messages
+ Thread receiverThread=null; // thread for receiving messages
+ Address peer_addr=null; // address of the 'other end' of the connection
+ final Lock send_lock=new ReentrantLock(); // serialize send()
+ long last_access=System.currentTimeMillis(); // last time a message was sent or received
+
+ /** Bounded queue of data to be sent to the peer of this connection */
+ BlockingQueue send_queue=null;
+ Sender sender=null;
+ boolean is_running=false;
+
+
+ private String getSockAddress() {
+ if(sock_addr != null)
+ return sock_addr;
+ if(sock != null) {
+ StringBuilder sb;
+ sb=new StringBuilder();
+ sb.append(sock.getLocalAddress().getHostAddress()).append(':').append(sock.getLocalPort());
+ sb.append(" - ").append(sock.getInetAddress().getHostAddress()).append(':').append(sock.getPort());
+ sock_addr=sb.toString();
+ }
+ return sock_addr;
+ }
+
+
+
+
+ Connection(Socket s, Address peer_addr) {
+ sock=s;
+ this.peer_addr=peer_addr;
+
+ if(use_send_queues) {
+ send_queue=new LinkedBlockingQueue(send_queue_size);
+ sender=new Sender();
+ }
+
+ try {
+ // out=new DataOutputStream(sock.getOutputStream());
+ // in=new DataInputStream(sock.getInputStream());
+
+ // The change to buffered input and output stream yielded a 400% performance gain !
+ // bela Sept 7 2006
+ out=new DataOutputStream(new BufferedOutputStream(sock.getOutputStream()));
+ in=new DataInputStream(new BufferedInputStream(sock.getInputStream()));
+ if(sender != null)
+ sender.start();
+ conn_creations.incrementAndGet();
+ }
+ catch(Exception ex) {
+ if(log.isErrorEnabled()) log.error("exception is " + ex);
+ }
+ }
+
+
+ boolean established() {
+ return receiverThread != null;
+ }
+
+
+ void setPeerAddress(Address peer_addr) {
+ this.peer_addr=peer_addr;
+ }
+
+ Address getPeerAddress() {return peer_addr;}
+
+ void updateLastAccessed() {
+ last_access=System.currentTimeMillis();
+ }
+
+ void init() {
+ is_running=true;
+ if(receiverThread == null || !receiverThread.isAlive()) {
+ // Roland Kurmann 4/7/2003, put in thread_group
+ receiverThread=getThreadFactory().newThread(thread_group,this, "ConnectionTable.Connection.Receiver [" + getSockAddress() + "]");
+ receiverThread.start();
+ if(log.isTraceEnabled())
+ log.trace("receiver started: " + receiverThread);
+ }
+
+ }
+
+ /**
+ * Returns true if underlying socket to peer is closed
+ *
+ * @return
+ */
+ boolean isSocketClosed() {
+ return !(sock != null && sock.isConnected());
+ }
+
+
+ void destroy() {
+ if(log.isTraceEnabled()) log.trace("destroyed " + this);
+ is_running=false;
+ closeSocket(); // should terminate handler as well
+ if(sender != null)
+ sender.stop();
+ Thread tmp=receiverThread;
+ receiverThread=null;
+ if(tmp != null) {
+ Util.interruptAndWaitToDie(tmp);
+ }
+
+ conn_creations.decrementAndGet();
+ }
+
+
+ /**
+ *
+ * @param data Guaranteed to be non null
+ * @param offset
+ * @param length
+ */
+ void send(byte[] data, int offset, int length) {
+ if(!is_running) {
+ if(log.isWarnEnabled())
+ log.warn("Connection is not running, discarding message");
+ return;
+ }
+ if(use_send_queues) {
+ try {
+ // we need to copy the byte[] buffer here because the original buffer might get changed meanwhile
+ byte[] tmp=new byte[length];
+ System.arraycopy(data, offset, tmp, 0, length);
+ send_queue.put(tmp);
+ }
+ catch(InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ else
+ _send(data, offset, length, true);
+ }
+
+
+ /**
+ * Sends data using the 'out' output stream of the socket
+ * @param data
+ * @param offset
+ * @param length
+ * @param acquire_lock
+ */
+ private void _send(byte[] data, int offset, int length, boolean acquire_lock) {
+ if(acquire_lock)
+ send_lock.lock();
+
+ try {
+ doSend(data, offset, length);
+ updateLastAccessed();
+ }
+ catch(InterruptedException iex) {
+ Thread.currentThread().interrupt(); // set interrupt flag again
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) log.error("failed sending data to " + peer_addr + ": " + ex);
+ }
+ finally {
+ if(acquire_lock)
+ send_lock.unlock();
+ }
+ }
+
+
+ void doSend(byte[] data, int offset, int length) throws Exception {
+ try {
+ // we're using 'double-writes', sending the buffer to the destination in 2 pieces. this would
+ // ensure that, if the peer closed the connection while we were idle, we would get an exception.
+ // this won't happen if we use a single write (see Stevens, ch. 5.13).
+ if(out != null) {
+ out.writeInt(length); // write the length of the data buffer first
+ Util.doubleWrite(data, offset, length, out);
+ out.flush(); // may not be very efficient (but safe)
+ }
+ }
+ catch(Exception ex) {
+ removeConnection(peer_addr);
+ throw ex;
+ }
+ }
+
+
+ /**
+ * Reads the peer's address. First a cookie has to be sent which has to match my own cookie, otherwise
+ * the connection will be refused
+ */
+ Address readPeerAddress(Socket client_sock) throws Exception {
+ Address client_peer_addr=null;
+ byte[] input_cookie=new byte[cookie.length];
+ int client_port=client_sock != null? client_sock.getPort() : 0;
+ short version;
+ InetAddress client_addr=client_sock != null? client_sock.getInetAddress() : null;
+
+ int timeout=client_sock.getSoTimeout();
+ client_sock.setSoTimeout(peer_addr_read_timeout);
+
+ try {
+
+ if(in != null) {
+ initCookie(input_cookie);
+
+ // read the cookie first
+ in.read(input_cookie, 0, input_cookie.length);
+ if(!matchCookie(input_cookie))
+ throw new SocketException("ConnectionTable.Connection.readPeerAddress(): cookie sent by " +
+ client_peer_addr + " does not match own cookie; terminating connection");
+ // then read the version
+ version=in.readShort();
+
+ if(Version.isBinaryCompatible(version) == false) {
+ if(log.isWarnEnabled())
+ log.warn(new StringBuilder("packet from ").append(client_addr).append(':').append(client_port).
+ append(" has different version (").append(Version.print(version)).append(") from ours (").
+ append(Version.printVersion()).append("). This may cause problems"));
+ }
+ client_peer_addr=new IpAddress();
+ client_peer_addr.readFrom(in);
+
+ updateLastAccessed();
+ }
+ return client_peer_addr;
+ }
+ finally {
+ client_sock.setSoTimeout(timeout);
+ }
+ }
+
+
+ /**
+ * Send the cookie first, then the our port number. If the cookie doesn't match the receiver's cookie,
+ * the receiver will reject the connection and close it.
+ */
+ void sendLocalAddress(Address local_addr) {
+ if(local_addr == null) {
+ if(log.isWarnEnabled()) log.warn("local_addr is null");
+ return;
+ }
+ if(out != null) {
+ try {
+ // write the cookie
+ out.write(cookie, 0, cookie.length);
+
+ // write the version
+ out.writeShort(Version.version);
+ local_addr.writeTo(out);
+ out.flush(); // needed ?
+ updateLastAccessed();
+ }
+ catch(Throwable t) {
+ if(log.isErrorEnabled()) log.error("exception is " + t);
+ }
+ }
+ }
+
+
+ void initCookie(byte[] c) {
+ if(c != null)
+ for(int i=0; i < c.length; i++)
+ c[i]=0;
+ }
+
+ boolean matchCookie(byte[] input) {
+ if(input == null || input.length < cookie.length) return false;
+ for(int i=0; i < cookie.length; i++)
+ if(cookie[i] != input[i]) return false;
+ return true;
+ }
+
+
+ String printCookie(byte[] c) {
+ if(c == null) return "";
+ return new String(c);
+ }
+
+
+ public void run() {
+ byte[] buf=new byte[256]; // start with 256, increase as we go
+ int len=0;
+
+ while(receiverThread != null && receiverThread.equals(Thread.currentThread()) && is_running) {
+ try {
+ if(in == null) {
+ if(log.isErrorEnabled()) log.error("input stream is null !");
+ break;
+ }
+ len=in.readInt();
+ if(len > buf.length)
+ buf=new byte[len];
+ in.readFully(buf, 0, len);
+ updateLastAccessed();
+ receive(peer_addr, buf, 0, len); // calls receiver.receive(msg)
+ }
+ catch(OutOfMemoryError mem_ex) {
+ if(log.isWarnEnabled()) log.warn("dropped invalid message, closing connection");
+ break; // continue;
+ }
+ catch(IOException io_ex) {
+ //this is very common occurrence, hence log under trace level
+ if(log.isTraceEnabled()) log.trace("Excption while read blocked for data from peer ", io_ex);
+ notifyConnectionClosed(peer_addr);
+ break;
+ }
+ catch(Throwable e) {
+ if(log.isWarnEnabled()) log.warn("Problem encountered while receiving message from peer " + peer_addr, e);
+ }
+ }
+ if(log.isTraceEnabled())
+ log.trace("ConnectionTable.Connection.Receiver terminated");
+ receiverThread=null;
+ closeSocket();
+ // remove(peer_addr);
+ }
+
+
+ public String toString() {
+ StringBuilder ret=new StringBuilder();
+ InetAddress local=null, remote=null;
+ String local_str, remote_str;
+
+ Socket tmp_sock=sock;
+ if(tmp_sock == null)
+ ret.append("");
+ else {
+ //since the sock variable gets set to null we want to make
+ //make sure we make it through here without a nullpointer exception
+ local=tmp_sock.getLocalAddress();
+ remote=tmp_sock.getInetAddress();
+ local_str=local != null ? Util.shortName(local) : "";
+ remote_str=remote != null ? Util.shortName(remote) : "";
+ ret.append('<' + local_str + ':' + tmp_sock.getLocalPort() +
+ " --> " + remote_str + ':' + tmp_sock.getPort() + "> (" +
+ ((System.currentTimeMillis() - last_access) / 1000) + " secs old)");
+ }
+ tmp_sock=null;
+
+ return ret.toString();
+ }
+
+
+ void closeSocket() {
+ Util.close(sock); // should actually close in/out (so we don't need to close them explicitly)
+ sock=null;
+ Util.close(out); // flushes data
+ // removed 4/22/2003 (request by Roland Kurmann)
+ // out=null;
+ Util.close(in);
+ }
+
+
+ class Sender implements Runnable {
+ Thread senderThread;
+ private boolean is_it_running=false;
+
+ void start() {
+ if(senderThread == null || !senderThread.isAlive()) {
+ senderThread=getThreadFactory().newThread(thread_group,this, "ConnectionTable.Connection.Sender local_addr=" + local_addr + " [" + getSockAddress() + "]");
+ senderThread.setDaemon(true);
+ is_it_running=true;
+ senderThread.start();
+ if(log.isTraceEnabled())
+ log.trace("sender thread started: " + senderThread);
+ }
+ }
+
+ void stop() {
+ is_it_running=false;
+ if(send_queue != null)
+ send_queue.clear();
+ if(senderThread != null) {
+ Thread tmp=senderThread;
+ senderThread=null;
+ Util.interruptAndWaitToDie(tmp);
+ }
+ }
+
+ boolean isRunning() {
+ return is_it_running && senderThread != null;
+ }
+
+ public void run() {
+ byte[] data;
+ while(senderThread != null && senderThread.equals(Thread.currentThread()) && is_it_running) {
+ try {
+ data=send_queue.take();
+ if(data == null)
+ continue;
+ // we don't need to serialize access to 'out' as we're the only thread sending messages
+ _send(data, 0, data.length, false);
+ }
+ catch(InterruptedException e) {
+ ;
+ }
+ }
+ is_it_running=false;
+ if(log.isTraceEnabled())
+ log.trace("ConnectionTable.Connection.Sender thread terminated");
+ }
+ }
+
+
+ }
+
+ class Reaper implements Runnable {
+ Thread t=null;
+
+ Reaper() {
+ ;
+ }
+
+ // return true if we have zero connections
+ private boolean haveZeroConnections() {
+ synchronized(conns) {
+ return conns.isEmpty();
+ }
+ }
+
+ public void start() {
+
+ if(haveZeroConnections())
+ return;
+ if(t != null && !t.isAlive())
+ t=null;
+ if(t == null) {
+ //RKU 7.4.2003, put in threadgroup
+ t=getThreadFactory().newThread(thread_group, this, "ConnectionTable.ReaperThread");
+ t.setDaemon(true); // will allow us to terminate if all remaining threads are daemons
+ t.start();
+ }
+ }
+
+ public void stop() {
+ Thread tmp=t;
+ if(t != null)
+ t=null;
+ if(tmp != null) {
+ Util.interruptAndWaitToDie(tmp);
+ }
+ }
+
+
+ public boolean isRunning() {
+ return t != null;
+ }
+
+ public void run() {
+ Connection connection;
+ Entry entry;
+ long curr_time;
+
+ if(log.isDebugEnabled()) log.debug("connection reaper thread was started. Number of connections=" +
+ conns.size() + ", reaper_interval=" + reaper_interval + ", conn_expire_time=" +
+ conn_expire_time);
+
+ while(!haveZeroConnections() && t != null && t.equals(Thread.currentThread())) {
+ Util.sleep(reaper_interval);
+ if(t == null || !Thread.currentThread().equals(t))
+ break;
+ synchronized(conns) {
+ curr_time=System.currentTimeMillis();
+ for(Iterator> it=conns.entrySet().iterator(); it.hasNext();) {
+ entry=it.next();
+ connection=entry.getValue();
+ if(log.isTraceEnabled()) log.trace("connection is " +
+ ((curr_time - connection.last_access) / 1000) + " seconds old (curr-time=" +
+ curr_time + ", last_access=" + connection.last_access + ')');
+ if(connection.last_access + conn_expire_time < curr_time) {
+ if(log.isTraceEnabled()) log.trace("connection " + connection +
+ " has been idle for too long (conn_expire_time=" + conn_expire_time +
+ "), will be removed");
+ connection.destroy();
+ it.remove();
+ }
+ }
+ }
+ }
+ if(log.isDebugEnabled()) log.debug("reaper terminated");
+ t=null;
+ }
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/ConnectionTable.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/ConnectionTable.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/ConnectionTable.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,375 @@
+// $Id: ConnectionTable.java,v 1.1 2012/08/17 14:51:18 marcin Exp $
+
+package org.jgroups.blocks;
+
+import org.jgroups.Address;
+import org.jgroups.util.PortsManager;
+import org.jgroups.stack.IpAddress;
+
+import java.io.IOException;
+import java.net.*;
+
+
+/**
+ * Manages incoming and outgoing TCP connections. For each outgoing message to destination P, if there
+ * is not yet a connection for P, one will be created. Subsequent outgoing messages will use this
+ * connection. For incoming messages, one server socket is created at startup. For each new incoming
+ * client connecting, a new thread from a thread pool is allocated and listens for incoming messages
+ * until the socket is closed by the peer. Sockets/threads with no activity will be killed
+ * after some time.
+ *
+ * Incoming messages from any of the sockets can be received by setting the message listener.
+ * @author Bela Ban
+ */
+public class ConnectionTable extends BasicConnectionTable implements Runnable {
+
+ /**
+ * Regular ConnectionTable without expiration of idle connections
+ * @param srv_port The port on which the server will listen. If this port is reserved, the next
+ * free port will be taken (incrementing srv_port).
+ */
+ public ConnectionTable(int srv_port) throws Exception {
+ this.srv_port=srv_port;
+ init();
+ }
+
+
+ public ConnectionTable(InetAddress bind_addr, int srv_port) throws Exception {
+ this.srv_port=srv_port;
+ this.bind_addr=bind_addr;
+ init();
+ }
+
+
+ /**
+ * ConnectionTable including a connection reaper. Connections that have been idle for more than conn_expire_time
+ * milliseconds will be closed and removed from the connection table. On next access they will be re-created.
+ * @param srv_port The port on which the server will listen
+ * @param reaper_interval Number of milliseconds to wait for reaper between attepts to reap idle connections
+ * @param conn_expire_time Number of milliseconds a connection can be idle (no traffic sent or received until
+ * it will be reaped
+ */
+ public ConnectionTable(int srv_port, long reaper_interval, long conn_expire_time) throws Exception {
+ this.srv_port=srv_port;
+ this.reaper_interval=reaper_interval;
+ this.conn_expire_time=conn_expire_time;
+ use_reaper=true;
+ init();
+ }
+
+
+ public ConnectionTable(Receiver r, InetAddress bind_addr, InetAddress external_addr,
+ int srv_port, int max_port) throws Exception {
+ setReceiver(r);
+ this.bind_addr=bind_addr;
+ this.external_addr=external_addr;
+ this.srv_port=srv_port;
+ this.max_port=max_port;
+ init();
+ }
+
+
+ /**
+ * Create a ConnectionTable
+ * @param r A reference to a receiver of all messages received by this class. Method receive()
+ * will be called.
+ * @param bind_addr The host name or IP address of the interface to which the server socket will bind.
+ * This is interesting only in multi-homed systems. If bind_addr is null, the
+ * server socket will bind to the first available interface (e.g. /dev/hme0 on
+ * Solaris or /dev/eth0 on Linux systems).
+ * @param external_addr The address which will be broadcast to the group (the externally visible address
+ * which this host should be contacted on). If external_addr is null, it will default to
+ * the same address that the server socket is bound to.
+ * @param srv_port The port to which the server socket will bind to. If this port is reserved, the next
+ * free port will be taken (incrementing srv_port).
+ * @param max_port The largest port number that the server socket will be bound to. If max_port < srv_port
+ * then there is no limit.
+ */
+ public ConnectionTable(Receiver r, InetAddress bind_addr, InetAddress external_addr,
+ int srv_port, int max_port, PortsManager pm) throws Exception {
+ setReceiver(r);
+ this.bind_addr=bind_addr;
+ this.external_addr=external_addr;
+ this.srv_port=srv_port;
+ this.max_port=max_port;
+ this.pm=pm;
+ init();
+ }
+
+
+ public ConnectionTable(Receiver r, InetAddress bind_addr, InetAddress external_addr, int srv_port, int max_port,
+ long reaper_interval, long conn_expire_time) throws Exception {
+ setReceiver(r);
+ this.bind_addr=bind_addr;
+ this.external_addr=external_addr;
+ this.srv_port=srv_port;
+ this.max_port=max_port;
+ this.reaper_interval=reaper_interval;
+ this.conn_expire_time=conn_expire_time;
+ use_reaper=true;
+ init();
+ }
+
+ /**
+ * ConnectionTable including a connection reaper. Connections that have been idle for more than conn_expire_time
+ * milliseconds will be closed and removed from the connection table. On next access they will be re-created.
+ *
+ * @param r The Receiver
+ * @param bind_addr The host name or IP address of the interface to which the server socket will bind.
+ * This is interesting only in multi-homed systems. If bind_addr is null, the
+ * server socket will bind to the first available interface (e.g. /dev/hme0 on
+ * Solaris or /dev/eth0 on Linux systems).
+ * @param external_addr The address which will be broadcast to the group (the externally visible address
+ * which this host should be contacted on). If external_addr is null, it will default to
+ * the same address that the server socket is bound to.
+ * @param srv_port The port to which the server socket will bind to. If this port is reserved, the next
+ * free port will be taken (incrementing srv_port).
+ * @param max_port The largest port number that the server socket will be bound to. If max_port < srv_port
+ * then there is no limit.
+ * @param reaper_interval Number of milliseconds to wait for reaper between attepts to reap idle connections
+ * @param conn_expire_time Number of milliseconds a connection can be idle (no traffic sent or received until
+ * it will be reaped
+ */
+ public ConnectionTable(Receiver r, InetAddress bind_addr, InetAddress external_addr, int srv_port, int max_port,
+ long reaper_interval, long conn_expire_time, PortsManager pm) throws Exception {
+ setReceiver(r);
+ this.bind_addr=bind_addr;
+ this.external_addr=external_addr;
+ this.srv_port=srv_port;
+ this.max_port=max_port;
+ this.pm=pm;
+ this.reaper_interval=reaper_interval;
+ this.conn_expire_time=conn_expire_time;
+ use_reaper=true;
+ init();
+ }
+
+
+
+ /** Try to obtain correct Connection (or create one if not yet existent) */
+ Connection getConnection(Address dest) throws Exception {
+ Connection conn=null;
+ Socket sock;
+
+ synchronized(conns) {
+ conn=conns.get(dest);
+ if(conn == null) {
+ // changed by bela Jan 18 2004: use the bind address for the client sockets as well
+ SocketAddress tmpBindAddr=new InetSocketAddress(bind_addr, 0);
+ InetAddress tmpDest=((IpAddress)dest).getIpAddress();
+ SocketAddress destAddr=new InetSocketAddress(tmpDest, ((IpAddress)dest).getPort());
+ sock=new Socket();
+ sock.bind(tmpBindAddr);
+ sock.setKeepAlive(true);
+ sock.setTcpNoDelay(tcp_nodelay);
+ if(linger > 0)
+ sock.setSoLinger(true, linger);
+ else
+ sock.setSoLinger(false, -1);
+ sock.connect(destAddr, sock_conn_timeout);
+
+ try {
+ sock.setSendBufferSize(send_buf_size);
+ }
+ catch(IllegalArgumentException ex) {
+ if(log.isErrorEnabled()) log.error("exception setting send buffer size to " +
+ send_buf_size + " bytes", ex);
+ }
+ try {
+ sock.setReceiveBufferSize(recv_buf_size);
+ }
+ catch(IllegalArgumentException ex) {
+ if(log.isErrorEnabled()) log.error("exception setting receive buffer size to " +
+ send_buf_size + " bytes", ex);
+ }
+ conn=new Connection(sock, dest);
+ conn.sendLocalAddress(local_addr);
+ notifyConnectionOpened(dest);
+ addConnection(dest, conn);
+ conn.init();
+ if(log.isTraceEnabled()) log.trace("created socket to " + dest);
+ }
+ return conn;
+ }
+ }
+
+
+ public final void start() throws Exception {
+ acceptor=getThreadFactory().newThread(thread_group,this, "ConnectionTable.AcceptorThread");
+ acceptor.start();
+
+ // start the connection reaper - will periodically remove unused connections
+ if(use_reaper && reaper == null) {
+ reaper=new Reaper();
+ reaper.start();
+ }
+ super.start();
+ }
+
+ protected void init() throws Exception {
+
+ srv_sock=createServerSocket(srv_port, max_port);
+
+ if (external_addr!=null)
+ local_addr=new IpAddress(external_addr, srv_sock.getLocalPort());
+ else if (bind_addr != null)
+ local_addr=new IpAddress(bind_addr, srv_sock.getLocalPort());
+ else
+ local_addr=new IpAddress(srv_sock.getLocalPort());
+
+ if(log.isDebugEnabled()) log.debug("server socket listening on " + local_addr);
+ }
+
+
+
+
+ /**
+ * Acceptor thread. Continuously accept new connections. Create a new thread for each new
+ * connection and put it in conns. When the thread should stop, it is
+ * interrupted by the thread creator.
+ */
+ public void run() {
+ Socket client_sock=null;
+ Connection conn=null;
+ Address peer_addr;
+
+ while(srv_sock != null) {
+ try {
+ conn=null;
+ client_sock=srv_sock.accept();
+ if(!running) {
+ if(log.isWarnEnabled())
+ log.warn("cannot accept connection from " + client_sock.getRemoteSocketAddress() + " as I'm closed");
+ break;
+ }
+ if(log.isTraceEnabled())
+ log.trace("[" +local_addr + "] accepted connection from " + client_sock.getInetAddress() + ":" + client_sock.getPort());
+ try {
+ client_sock.setSendBufferSize(send_buf_size);
+ }
+ catch(IllegalArgumentException ex) {
+ if(log.isErrorEnabled()) log.error("exception setting send buffer size to " + send_buf_size + " bytes", ex);
+ }
+ try {
+ client_sock.setReceiveBufferSize(recv_buf_size);
+ }
+ catch(IllegalArgumentException ex) {
+ if(log.isErrorEnabled()) log.error("exception setting receive buffer size to " + send_buf_size + " bytes", ex);
+ }
+
+ client_sock.setKeepAlive(true);
+ client_sock.setTcpNoDelay(tcp_nodelay);
+ if(linger > 0)
+ client_sock.setSoLinger(true, linger);
+ else
+ client_sock.setSoLinger(false, -1);
+
+ // create new thread and add to conn table
+ conn=new Connection(client_sock, null); // will call receive(msg)
+ // get peer's address
+ peer_addr=conn.readPeerAddress(client_sock);
+
+ // client_addr=new IpAddress(client_sock.getInetAddress(), client_port);
+ conn.setPeerAddress(peer_addr);
+
+ synchronized(conns) {
+ Connection tmp=conns.get(peer_addr);
+ //Vladimir Nov, 5th, 2007
+ //we might have a connection to peer but is that
+ //connection still open?
+ boolean connectionOpen = tmp != null && !tmp.isSocketClosed();
+ if(connectionOpen) {
+ if(peer_addr.compareTo(local_addr) > 0) {
+ if(log.isTraceEnabled())
+ log.trace("peer's address (" + peer_addr + ") is greater than our local address (" +
+ local_addr + "), replacing our existing connection");
+ // peer's address is greater, add peer's connection to ConnectionTable, destroy existing connection
+ removeConnection(peer_addr);
+ addConnection(peer_addr, conn);
+ notifyConnectionOpened(peer_addr);
+ }
+ else {
+ if(log.isTraceEnabled())
+ log.trace("peer's address (" + peer_addr + ") is smaller than our local address (" +
+ local_addr + "), rejecting peer connection request");
+ conn.destroy();
+ continue;
+ }
+ }
+ else {
+ addConnection(peer_addr, conn);
+ notifyConnectionOpened(peer_addr);
+ }
+ }
+
+ conn.init(); // starts handler thread on this socket
+ }
+ catch(SocketTimeoutException timeout_ex) {
+ if(log.isWarnEnabled()) log.warn("timed out waiting for peer address, closing connection " + conn + ": " + timeout_ex);
+ if(conn != null)
+ conn.destroy();
+ if(srv_sock == null)
+ break; // socket was closed, therefore stop
+ }
+ catch(SocketException sock_ex) {
+ if(log.isWarnEnabled() && srv_sock != null) log.warn("Could not read accept connection from peer " + sock_ex);
+ if(conn != null)
+ conn.destroy();
+ if(srv_sock == null)
+ break; // socket was closed, therefore stop
+ }
+ catch(Throwable ex) {
+ if(log.isWarnEnabled()) log.warn("Could not read accept connection from peer " + ex);
+ if(srv_sock == null)
+ break; // socket was closed, therefore stop
+ }
+ }
+ if(client_sock != null)
+ try {client_sock.close();} catch(IOException e) {}
+ if(log.isTraceEnabled())
+ log.trace(Thread.currentThread().getName() + " terminated");
+ }
+
+
+ /** Finds first available port starting at start_port and returns server socket.
+ * Will not bind to port >end_port. Sets srv_port */
+ protected ServerSocket createServerSocket(int start_port, int end_port) throws Exception {
+ ServerSocket ret=null;
+
+ while(true) {
+ try {
+ if(start_port > 0 && pm != null)
+ start_port=pm.getNextAvailablePort(start_port);
+ if(bind_addr == null)
+ ret=new ServerSocket(start_port);
+ else {
+ // changed (bela Sept 7 2007): we accept connections on all NICs
+ ret=new ServerSocket(start_port, backlog, bind_addr);
+ }
+ }
+ catch(BindException bind_ex) {
+ if (start_port==end_port) throw new BindException("No available port to bind to");
+ if(bind_addr != null && !bind_addr.isLoopbackAddress()) {
+ NetworkInterface nic=NetworkInterface.getByInetAddress(bind_addr);
+ if(nic == null)
+ throw new BindException("bind_addr " + bind_addr + " is not a valid interface");
+ }
+ start_port++;
+ continue;
+ }
+ catch(IOException io_ex) {
+ if(log.isErrorEnabled()) log.error("exception is " + io_ex);
+ }
+ srv_port=start_port;
+ break;
+ }
+ if(ret == null)
+ throw new IOException("Could not create server socket in port range " + start_port + " - " +end_port);
+ return ret;
+ }
+
+
+
+
+}
+
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/ConnectionTableNIO.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/ConnectionTableNIO.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/ConnectionTableNIO.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,1540 @@
+// $Id: ConnectionTableNIO.java,v 1.1 2012/08/17 14:51:18 marcin Exp $
+
+package org.jgroups.blocks;
+
+import org.apache.commons.logging.Log;
+import org.jgroups.Address;
+import org.jgroups.Global;
+import org.jgroups.stack.IpAddress;
+import org.jgroups.util.PortsManager;
+import org.jgroups.util.ShutdownRejectedExecutionHandler;
+
+import java.io.IOException;
+import java.net.*;
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.*;
+import java.util.concurrent.*;
+
+/**
+ * Manages incoming and outgoing TCP connections. For each outgoing message to destination P, if there
+ * is not yet a connection for P, one will be created. Subsequent outgoing messages will use this
+ * connection. For incoming messages, one server socket is created at startup. For each new incoming
+ * client connecting, a new thread from a thread pool is allocated and listens for incoming messages
+ * until the socket is closed by the peer. Sockets/threads with no activity will be killed
+ * after some time.
+ *
+ * Incoming messages from any of the sockets can be received by setting the message listener.
+ *
+ * We currently require use_incoming_packet_handler=true (release 2.4 will support use_incoming_packet_handler=false
+ * due to threadless stack support).
+ *
+ * @author Bela Ban, Scott Marlow, Alex Fu
+ */
+public class ConnectionTableNIO extends BasicConnectionTable implements Runnable {
+
+ private ServerSocketChannel m_serverSocketChannel;
+ private Selector m_acceptSelector;
+
+ private WriteHandler[] m_writeHandlers;
+ private int m_nextWriteHandler = 0;
+ private final Object m_lockNextWriteHandler = new Object();
+
+ private ReadHandler[] m_readHandlers;
+ private int m_nextReadHandler = 0;
+ private final Object m_lockNextReadHandler = new Object();
+
+ // thread pool for processing read requests
+ private Executor m_requestProcessors;
+ private volatile boolean serverStopping=false;
+
+ private final List m_backGroundThreads = new LinkedList(); // Collection of all created threads
+
+ private int m_reader_threads = 3;
+
+ private int m_writer_threads = 3;
+
+ private int m_processor_threads = 5; // PooledExecutor.createThreads()
+ private int m_processor_minThreads = 5; // PooledExecutor.setMinimumPoolSize()
+ private int m_processor_maxThreads = 5; // PooledExecutor.setMaxThreads()
+ private int m_processor_queueSize=100; // Number of queued requests that can be pending waiting
+ // for a background thread to run the request.
+ private long m_processor_keepAliveTime = Long.MAX_VALUE; // PooledExecutor.setKeepAliveTime( milliseconds);
+ // negative value used to mean to wait forever, instead set to Long.MAX_VALUE to wait forever
+
+
+
+ /**
+ * @param srv_port
+ * @throws Exception
+ */
+ public ConnectionTableNIO(int srv_port) throws Exception {
+ this.srv_port=srv_port;
+ start();
+ }
+
+ /**
+ * @param srv_port
+ * @param reaper_interval
+ * @param conn_expire_time
+ * @throws Exception
+ */
+ public ConnectionTableNIO(int srv_port, long reaper_interval,
+ long conn_expire_time) throws Exception {
+ this.srv_port=srv_port;
+ this.reaper_interval=reaper_interval;
+ this.conn_expire_time=conn_expire_time;
+ start();
+ }
+
+ /**
+ * @param r
+ * @param bind_addr
+ * @param external_addr
+ * @param srv_port
+ * @param max_port
+ * @throws Exception
+ */
+ public ConnectionTableNIO(Receiver r, InetAddress bind_addr, InetAddress external_addr, int srv_port, int max_port)
+ throws Exception
+ {
+ setReceiver(r);
+ this.external_addr=external_addr;
+ this.bind_addr=bind_addr;
+ this.srv_port=srv_port;
+ this.max_port=max_port;
+ use_reaper=true;
+ start();
+ }
+
+
+ public ConnectionTableNIO(Receiver r, InetAddress bind_addr, InetAddress external_addr,
+ int srv_port, int max_port, boolean doStart)
+ throws Exception
+ {
+ setReceiver(r);
+ this.external_addr=external_addr;
+ this.bind_addr=bind_addr;
+ this.srv_port=srv_port;
+ this.max_port=max_port;
+ use_reaper=true;
+ if(doStart)
+ start();
+ }
+
+ public ConnectionTableNIO(Receiver r, InetAddress bind_addr, InetAddress external_addr,
+ int srv_port, int max_port, PortsManager pm,
+ boolean doStart)
+ throws Exception
+ {
+ setReceiver(r);
+ this.external_addr=external_addr;
+ this.bind_addr=bind_addr;
+ this.srv_port=srv_port;
+ this.max_port=max_port;
+ this.pm=pm;
+ use_reaper=true;
+ if(doStart)
+ start();
+ }
+
+
+ /**
+ * @param r
+ * @param bind_addr
+ * @param external_addr
+ * @param srv_port
+ * @param max_port
+ * @param reaper_interval
+ * @param conn_expire_time
+ * @throws Exception
+ */
+ public ConnectionTableNIO(Receiver r, InetAddress bind_addr, InetAddress external_addr, int srv_port, int max_port,
+ long reaper_interval, long conn_expire_time
+ ) throws Exception
+ {
+ setReceiver(r);
+ this.bind_addr=bind_addr;
+ this.external_addr=external_addr;
+ this.srv_port=srv_port;
+ this.max_port=max_port;
+ this.reaper_interval=reaper_interval;
+ this.conn_expire_time=conn_expire_time;
+ use_reaper=true;
+ start();
+ }
+
+
+ public ConnectionTableNIO(Receiver r, InetAddress bind_addr, InetAddress external_addr,
+ int srv_port, int max_port,
+ long reaper_interval, long conn_expire_time, boolean doStart
+ ) throws Exception
+ {
+ setReceiver(r);
+ this.bind_addr=bind_addr;
+ this.external_addr=external_addr;
+ this.srv_port=srv_port;
+ this.max_port=max_port;
+ this.reaper_interval=reaper_interval;
+ this.conn_expire_time=conn_expire_time;
+ use_reaper=true;
+ if(doStart)
+ start();
+ }
+
+ public ConnectionTableNIO(Receiver r, InetAddress bind_addr, InetAddress external_addr,
+ int srv_port, int max_port, PortsManager pm,
+ long reaper_interval, long conn_expire_time, boolean doStart
+ ) throws Exception
+ {
+ setReceiver(r);
+ this.bind_addr=bind_addr;
+ this.external_addr=external_addr;
+ this.srv_port=srv_port;
+ this.max_port=max_port;
+ this.pm=pm;
+ this.reaper_interval=reaper_interval;
+ this.conn_expire_time=conn_expire_time;
+ use_reaper=true;
+ if(doStart)
+ start();
+ }
+
+
+
+ public int getReaderThreads() { return m_reader_threads; }
+
+ public void setReaderThreads(int m_reader_threads) {
+ this.m_reader_threads=m_reader_threads;
+ }
+
+ public int getWriterThreads() { return m_writer_threads; }
+
+ public void setWriterThreads(int m_writer_threads) {
+ this.m_writer_threads=m_writer_threads;
+ }
+
+ public int getProcessorThreads() { return m_processor_threads; }
+
+ public void setProcessorThreads(int m_processor_threads) {
+ this.m_processor_threads=m_processor_threads;
+ }
+
+ public int getProcessorMinThreads() { return m_processor_minThreads;}
+
+ public void setProcessorMinThreads(int m_processor_minThreads) {
+ this.m_processor_minThreads=m_processor_minThreads;
+ }
+
+ public int getProcessorMaxThreads() { return m_processor_maxThreads;}
+
+ public void setProcessorMaxThreads(int m_processor_maxThreads) {
+ this.m_processor_maxThreads=m_processor_maxThreads;
+ }
+
+ public int getProcessorQueueSize() { return m_processor_queueSize; }
+
+ public void setProcessorQueueSize(int m_processor_queueSize) {
+ this.m_processor_queueSize=m_processor_queueSize;
+ }
+
+ public long getProcessorKeepAliveTime() { return m_processor_keepAliveTime; }
+
+ public void setProcessorKeepAliveTime(long m_processor_keepAliveTime) {
+ this.m_processor_keepAliveTime=m_processor_keepAliveTime;
+ }
+
+
+ /**
+ * Try to obtain correct Connection (or create one if not yet existent)
+ */
+ ConnectionTable.Connection getConnection(Address dest) throws Exception
+ {
+ Connection conn;
+ SocketChannel sock_ch;
+
+ synchronized (conns)
+ {
+ conn = (Connection) conns.get(dest);
+ if (conn == null)
+ {
+ InetSocketAddress destAddress = new InetSocketAddress(((IpAddress) dest).getIpAddress(),
+ ((IpAddress) dest).getPort());
+ sock_ch = SocketChannel.open(destAddress);
+ sock_ch.socket().setTcpNoDelay(tcp_nodelay);
+ conn = new Connection(sock_ch, dest);
+
+ conn.sendLocalAddress(local_addr);
+ // This outbound connection is ready
+
+ sock_ch.configureBlocking(false);
+
+ try
+ {
+ if (log.isTraceEnabled())
+ log.trace("About to change new connection send buff size from " + sock_ch.socket().getSendBufferSize() + " bytes");
+ sock_ch.socket().setSendBufferSize(send_buf_size);
+ if (log.isTraceEnabled())
+ log.trace("Changed new connection send buff size to " + sock_ch.socket().getSendBufferSize() + " bytes");
+ }
+ catch (IllegalArgumentException ex)
+ {
+ if (log.isErrorEnabled()) log.error("exception setting send buffer size to " +
+ send_buf_size + " bytes: " + ex);
+ }
+ try
+ {
+ if (log.isTraceEnabled())
+ log.trace("About to change new connection receive buff size from " + sock_ch.socket().getReceiveBufferSize() + " bytes");
+ sock_ch.socket().setReceiveBufferSize(recv_buf_size);
+ if (log.isTraceEnabled())
+ log.trace("Changed new connection receive buff size to " + sock_ch.socket().getReceiveBufferSize() + " bytes");
+ }
+ catch (IllegalArgumentException ex)
+ {
+ if (log.isErrorEnabled()) log.error("exception setting receive buffer size to " +
+ send_buf_size + " bytes: " + ex);
+ }
+
+ int idx;
+ synchronized (m_lockNextWriteHandler)
+ {
+ idx = m_nextWriteHandler = (m_nextWriteHandler + 1) % m_writeHandlers.length;
+ }
+ conn.setupWriteHandler(m_writeHandlers[idx]);
+
+ // Put the new connection to the queue
+ try
+ {
+ synchronized (m_lockNextReadHandler)
+ {
+ idx = m_nextReadHandler = (m_nextReadHandler + 1) % m_readHandlers.length;
+ }
+ m_readHandlers[idx].add(conn);
+
+ } catch (InterruptedException e)
+ {
+ if (log.isWarnEnabled())
+ log.warn("Thread (" +Thread.currentThread().getName() + ") was interrupted, closing connection", e);
+ // What can we do? Remove it from table then.
+ conn.destroy();
+ throw e;
+ }
+
+ // Add connection to table
+ addConnection(dest, conn);
+
+ notifyConnectionOpened(dest);
+ if (log.isTraceEnabled()) log.trace("created socket to " + dest);
+ }
+ return conn;
+ }
+ }
+
+ public final void start() throws Exception {
+ super.start();
+ init();
+ srv_sock=createServerSocket(srv_port, max_port);
+
+ if (external_addr!=null)
+ local_addr=new IpAddress(external_addr, srv_sock.getLocalPort());
+ else if (bind_addr != null)
+ local_addr=new IpAddress(bind_addr, srv_sock.getLocalPort());
+ else
+ local_addr=new IpAddress(srv_sock.getLocalPort());
+
+ if(log.isDebugEnabled()) log.debug("server socket created on " + local_addr);
+
+
+ //Roland Kurmann 4/7/2003, put in thread_group
+ acceptor=getThreadFactory().newThread(thread_group, this, "ConnectionTable.AcceptorThread");
+ acceptor.setDaemon(true);
+ acceptor.start();
+ m_backGroundThreads.add(acceptor);
+
+ // start the connection reaper - will periodically remove unused connections
+ if(use_reaper && reaper == null) {
+ reaper=new Reaper();
+ reaper.start();
+ }
+ }
+
+ protected void init()
+ throws Exception
+ {
+
+ // use directExector if max thread pool size is less than or equal to zero.
+ if(getProcessorMaxThreads() <= 0) {
+ m_requestProcessors = new Executor() {
+
+ public void execute(Runnable command) {
+ command.run();
+ }
+ };
+ }
+ else
+ {
+ // Create worker thread pool for processing incoming buffers
+ ThreadPoolExecutor requestProcessors = new ThreadPoolExecutor(getProcessorMinThreads(), getProcessorMaxThreads(),
+ getProcessorKeepAliveTime(), TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue(getProcessorQueueSize()));
+
+ requestProcessors.setThreadFactory(new ThreadFactory() {
+ public Thread newThread(Runnable runnable) {
+ Thread new_thread=new Thread(thread_group, runnable);
+ new_thread.setDaemon(true);
+ new_thread.setName("ConnectionTableNIO.Thread");
+ m_backGroundThreads.add(new_thread);
+ return new_thread;
+ }
+ });
+ requestProcessors.setRejectedExecutionHandler(new ShutdownRejectedExecutionHandler(requestProcessors.getRejectedExecutionHandler()));
+ m_requestProcessors = requestProcessors;
+ }
+
+ m_writeHandlers = WriteHandler.create(getThreadFactory(),getWriterThreads(), thread_group, m_backGroundThreads, log);
+ m_readHandlers = ReadHandler.create(getThreadFactory(),getReaderThreads(), this, thread_group, m_backGroundThreads, log);
+ }
+
+
+ /**
+ * Closes all open sockets, the server socket and all threads waiting for incoming messages
+ */
+ public void stop()
+ {
+ super.stop();
+ serverStopping = true;
+
+ if(reaper != null)
+ reaper.stop();
+
+ // Stop the main selector
+ if(m_acceptSelector != null)
+ m_acceptSelector.wakeup();
+
+ // Stop selector threads
+ if(m_readHandlers != null)
+ {
+ for (int i = 0; i < m_readHandlers.length; i++)
+ {
+ try
+ {
+ m_readHandlers[i].add(new Shutdown());
+ } catch (InterruptedException e)
+ {
+ log.error("Thread ("+Thread.currentThread().getName() +") was interrupted, failed to shutdown selector", e);
+ }
+ }
+ }
+ if(m_writeHandlers != null)
+ {
+ for (int i = 0; i < m_writeHandlers.length; i++)
+ {
+ try
+ {
+ m_writeHandlers[i].queue.put(new Shutdown());
+ m_writeHandlers[i].selector.wakeup();
+ } catch (InterruptedException e)
+ {
+ log.error("Thread ("+Thread.currentThread().getName() +") was interrupted, failed to shutdown selector", e);
+ }
+ }
+ }
+
+ // Stop the callback thread pool
+ if(m_requestProcessors instanceof ThreadPoolExecutor)
+ ((ThreadPoolExecutor)m_requestProcessors).shutdownNow();
+
+ if(m_requestProcessors instanceof ThreadPoolExecutor){
+ try{
+ ((ThreadPoolExecutor) m_requestProcessors).awaitTermination(Global.THREADPOOL_SHUTDOWN_WAIT_TIME,
+ TimeUnit.MILLISECONDS);
+ }catch(InterruptedException e){
+ }
+ }
+
+ // then close the connections
+ synchronized(conns) {
+ Iterator it=conns.values().iterator();
+ while(it.hasNext()) {
+ Connection conn=(Connection)it.next();
+ conn.destroy();
+ }
+ conns.clear();
+ }
+
+ while(!m_backGroundThreads.isEmpty()) {
+ Thread t =m_backGroundThreads.remove(0);
+ try {
+ t.join();
+ } catch(InterruptedException e) {
+ log.error("Thread ("+Thread.currentThread().getName() +") was interrupted while waiting on thread " + t.getName() + " to finish.");
+ }
+ }
+ m_backGroundThreads.clear();
+
+ }
+
+ /**
+ * Acceptor thread. Continuously accept new connections and assign readhandler/writehandler
+ * to them.
+ */
+ public void run() {
+ Connection conn;
+
+ while(m_serverSocketChannel.isOpen() && !serverStopping) {
+ int num;
+ try {
+ num=m_acceptSelector.select();
+ }
+ catch(IOException e) {
+ if(log.isWarnEnabled())
+ log.warn("Select operation on listening socket failed", e);
+ continue; // Give up this time
+ }
+
+ if(num > 0) {
+ Set readyKeys=m_acceptSelector.selectedKeys();
+ for(Iterator i=readyKeys.iterator(); i.hasNext();) {
+ SelectionKey key=i.next();
+ i.remove();
+ // We only deal with new incoming connections
+
+ ServerSocketChannel readyChannel=(ServerSocketChannel)key.channel();
+ SocketChannel client_sock_ch;
+ try {
+ client_sock_ch=readyChannel.accept();
+ }
+ catch(IOException e) {
+ if(log.isWarnEnabled())
+ log.warn("Attempt to accept new connection from listening socket failed", e);
+ // Give up this connection
+ continue;
+ }
+
+ if(log.isTraceEnabled())
+ log.trace("accepted connection, client_sock=" + client_sock_ch.socket());
+
+ try {
+ client_sock_ch.socket().setSendBufferSize(send_buf_size);
+ }
+ catch(IllegalArgumentException ex) {
+ if(log.isErrorEnabled()) log.error("exception setting send buffer size to " + send_buf_size + " bytes: ", ex);
+ }
+ catch(SocketException e) {
+ if(log.isErrorEnabled()) log.error("exception setting send buffer size to " + send_buf_size + " bytes: ", e);
+ }
+
+ try {
+ client_sock_ch.socket().setReceiveBufferSize(recv_buf_size);
+ }
+ catch(IllegalArgumentException ex) {
+ if(log.isErrorEnabled()) log.error("exception setting receive buffer size to " + send_buf_size + " bytes: ", ex);
+ }
+ catch(SocketException e) {
+ if(log.isErrorEnabled()) log.error("exception setting receive buffer size to " + recv_buf_size + " bytes: ", e);
+ }
+
+ conn=new Connection(client_sock_ch, null);
+ try {
+ Address peer_addr=conn.readPeerAddress(client_sock_ch.socket());
+ conn.peer_addr=peer_addr;
+ synchronized(conns) {
+ Connection tmp=(Connection)conns.get(peer_addr);
+ if(tmp != null) {
+ if(peer_addr.compareTo(local_addr) > 0) {
+ if(log.isTraceEnabled())
+ log.trace("peer's address (" + peer_addr + ") is greater than our local address (" +
+ local_addr + "), replacing our existing connection");
+ // peer's address is greater, add peer's connection to ConnectionTable, destroy existing connection
+ addConnection(peer_addr, conn);
+ tmp.destroy();
+ notifyConnectionOpened(peer_addr);
+ }
+ else {
+ if(log.isTraceEnabled())
+ log.trace("peer's address (" + peer_addr + ") is smaller than our local address (" +
+ local_addr + "), rejecting peer connection request");
+ conn.destroy();
+ continue;
+ }
+ }
+ else {
+ addConnection(peer_addr, conn);
+ }
+ }
+ notifyConnectionOpened(peer_addr);
+ client_sock_ch.configureBlocking(false);
+ }
+ catch(IOException e) {
+ if(log.isWarnEnabled())
+ log.warn("Attempt to configure non-blocking mode failed", e);
+ conn.destroy();
+ continue;
+ }
+ catch(Exception e) {
+ if(log.isWarnEnabled())
+ log.warn("Attempt to handshake with other peer failed", e);
+ conn.destroy();
+ continue;
+ }
+
+ int idx;
+ synchronized(m_lockNextWriteHandler) {
+ idx=m_nextWriteHandler=(m_nextWriteHandler + 1) % m_writeHandlers.length;
+ }
+ conn.setupWriteHandler(m_writeHandlers[idx]);
+
+ try {
+ synchronized(m_lockNextReadHandler) {
+ idx=m_nextReadHandler=(m_nextReadHandler + 1) % m_readHandlers.length;
+ }
+ m_readHandlers[idx].add(conn);
+
+ }
+ catch(InterruptedException e) {
+ if(log.isWarnEnabled())
+ log.warn("Attempt to configure read handler for accepted connection failed", e);
+ // close connection
+ conn.destroy();
+ }
+ } // end of iteration
+ } // end of selected key > 0
+ } // end of thread
+
+ if(m_serverSocketChannel.isOpen()) {
+ try {
+ m_serverSocketChannel.close();
+ }
+ catch(Exception e) {
+ log.error("exception closing server listening socket", e);
+ }
+ }
+ if(log.isTraceEnabled())
+ log.trace("acceptor thread terminated");
+
+ }
+
+
+ /**
+ * Finds first available port starting at start_port and returns server socket. Sets srv_port
+ */
+ protected ServerSocket createServerSocket(int start_port, int end_port) throws Exception
+ {
+ this.m_acceptSelector = Selector.open();
+ m_serverSocketChannel = ServerSocketChannel.open();
+ m_serverSocketChannel.configureBlocking(false);
+
+ if(start_port > 0 && pm != null)
+ start_port=pm.getNextAvailablePort(start_port);
+
+ while (true)
+ {
+ try
+ {
+ SocketAddress sockAddr;
+ if (bind_addr == null)
+ {
+ sockAddr=new InetSocketAddress(start_port);
+ m_serverSocketChannel.socket().bind(sockAddr);
+ }
+ else
+ {
+ sockAddr=new InetSocketAddress(bind_addr, start_port);
+ m_serverSocketChannel.socket().bind(sockAddr, backlog);
+ }
+ }
+ catch (BindException bind_ex)
+ {
+ if (start_port == end_port)
+ throw (BindException) ((new BindException("No available port to bind to (start_port=" + start_port + ")")).initCause(bind_ex));
+ start_port++;
+ continue;
+ }
+ catch (SocketException bind_ex)
+ {
+ if (start_port == end_port)
+ throw (BindException) ((new BindException("No available port to bind to (start_port=" + start_port + ")")).initCause(bind_ex));
+ start_port++;
+ continue;
+ }
+ catch (IOException io_ex)
+ {
+ if (log.isErrorEnabled()) log.error("Attempt to bind serversocket failed, port="+start_port+", bind addr=" + bind_addr ,io_ex);
+ throw io_ex;
+ }
+ srv_port = start_port;
+ break;
+ }
+ m_serverSocketChannel.register(this.m_acceptSelector, SelectionKey.OP_ACCEPT);
+ return m_serverSocketChannel.socket();
+ }
+
+ protected void runRequest(Address addr, ByteBuffer buf) throws InterruptedException {
+ m_requestProcessors.execute(new ExecuteTask(addr, buf));
+ }
+
+
+ // Represents shutdown
+ private static class Shutdown {
+ }
+
+ // ReadHandler has selector to deal with read, it runs in seperated thread
+ private static class ReadHandler implements Runnable {
+ private final Selector selector= initHandler();
+ private final LinkedBlockingQueue queue= new LinkedBlockingQueue();
+ private final ConnectionTableNIO connectTable;
+ private final Log log;
+
+ ReadHandler(ConnectionTableNIO ct, Log log) {
+ connectTable= ct;
+ this.log=log;
+ }
+
+ public Selector initHandler()
+ {
+ // Open the selector
+ try
+ {
+ return Selector.open();
+ } catch (IOException e)
+ {
+ if (log.isErrorEnabled()) log.error(e);
+ throw new IllegalStateException(e.getMessage());
+ }
+
+ }
+
+ /**
+ * create instances of ReadHandler threads for receiving data.
+ *
+ * @param workerThreads is the number of threads to create.
+ */
+ private static ReadHandler[] create(org.jgroups.util.ThreadFactory f,int workerThreads, ConnectionTableNIO ct, ThreadGroup tg, List backGroundThreads, Log log)
+ {
+ ReadHandler[] handlers = new ReadHandler[workerThreads];
+ for (int looper = 0; looper < workerThreads; looper++)
+ {
+ handlers[looper] = new ReadHandler(ct, log);
+
+
+ Thread thread = f.newThread(tg, handlers[looper], "nioReadHandlerThread");
+ thread.setDaemon(true);
+ thread.start();
+ backGroundThreads.add(thread);
+ }
+ return handlers;
+ }
+
+
+ private void add(Object conn) throws InterruptedException
+ {
+ queue.put(conn);
+ wakeup();
+ }
+
+ private void wakeup()
+ {
+ selector.wakeup();
+ }
+
+ public void run()
+ {
+ while (true)
+ { // m_s can be closed by the management thread
+ int events;
+ try
+ {
+ events = selector.select();
+ } catch (IOException e)
+ {
+ if (log.isWarnEnabled())
+ log.warn("Select operation on socket failed", e);
+ continue; // Give up this time
+ } catch (ClosedSelectorException e)
+ {
+ if (log.isWarnEnabled())
+ log.warn("Select operation on socket failed" , e);
+ return; // Selector gets closed, thread stops
+ }
+
+ if (events > 0)
+ { // there are read-ready channels
+ Set readyKeys = selector.selectedKeys();
+ try
+ {
+ for (Iterator i = readyKeys.iterator(); i.hasNext();)
+ {
+ SelectionKey key = (SelectionKey) i.next();
+ i.remove();
+ // Do partial read and handle call back
+ Connection conn = (Connection) key.attachment();
+ if(conn != null && conn.getSocketChannel() != null)
+ {
+ try
+ {
+ if (conn.getSocketChannel().isOpen())
+ readOnce(conn);
+ else
+ { // socket connection is already closed, clean up connection state
+ conn.closed();
+ }
+ } catch (IOException e)
+ {
+ if (log.isTraceEnabled()) log.trace("Read operation on socket failed" , e);
+ // The connection must be bad, cancel the key, close socket, then
+ // remove it from table!
+ key.cancel();
+ conn.destroy();
+ conn.closed();
+ }
+ }
+ }
+ }
+ catch(ConcurrentModificationException e) {
+ if (log.isTraceEnabled()) log.trace("Selection set changed", e);
+ // valid events should still be in the selection set the next time
+ }
+ }
+
+ // Now we look at the connection queue to get any new connections added
+ Object o;
+ try
+ {
+ o = queue.poll(0L, TimeUnit.MILLISECONDS); // get a connection
+ } catch (InterruptedException e)
+ {
+ if (log.isTraceEnabled()) log.trace("Thread ("+Thread.currentThread().getName() +") was interrupted while polling queue" ,e);
+ // We must give up
+ continue;
+ }
+ if (null == o)
+ continue;
+ if (o instanceof Shutdown) { // shutdown command?
+ try {
+ selector.close();
+ } catch(IOException e) {
+ if (log.isTraceEnabled()) log.trace("Read selector close operation failed" , e);
+ }
+ return; // stop reading
+ }
+ Connection conn = (Connection) o;// must be a new connection
+ SocketChannel sc = conn.getSocketChannel();
+ try
+ {
+ sc.register(selector, SelectionKey.OP_READ, conn);
+ } catch (ClosedChannelException e)
+ {
+ if (log.isTraceEnabled()) log.trace("Socket channel was closed while we were trying to register it to selector" , e);
+ // Channel becomes bad. The connection must be bad,
+ // close socket, then remove it from table!
+ conn.destroy();
+ conn.closed();
+ }
+ } // end of the while true loop
+ }
+
+ private void readOnce(Connection conn)
+ throws IOException
+ {
+ ConnectionReadState readState = conn.getReadState();
+ if (!readState.isHeadFinished())
+ { // a brand new message coming or header is not completed
+ // Begin or continue to read header
+ int size = readHeader(conn);
+ if (0 == size)
+ { // header is not completed
+ return;
+ }
+ }
+ // Begin or continue to read body
+ if (readBody(conn) > 0)
+ { // not finish yet
+ return;
+ }
+ Address addr = conn.getPeerAddress();
+ ByteBuffer buf = readState.getReadBodyBuffer();
+ // Clear status
+ readState.bodyFinished();
+ // Assign worker thread to execute call back
+ try
+ {
+ connectTable.runRequest(addr, buf);
+ } catch (InterruptedException e)
+ {
+ // Cannot do call back, what can we do?
+ // Give up handling the message then
+ log.error("Thread ("+Thread.currentThread().getName() +") was interrupted while assigning executor to process read request" , e);
+ }
+ }
+
+ /**
+ * Read message header from channel. It doesn't try to complete. If there is nothing in
+ * the channel, the method returns immediately.
+ *
+ * @param conn The connection
+ * @return 0 if header hasn't been read completely, otherwise the size of message body
+ * @throws IOException
+ */
+ private int readHeader(Connection conn)
+ throws IOException
+ {
+ ConnectionReadState readState = conn.getReadState();
+ ByteBuffer headBuf = readState.getReadHeadBuffer();
+
+ SocketChannel sc = conn.getSocketChannel();
+ while (headBuf.remaining() > 0)
+ {
+ int num = sc.read(headBuf);
+ if (-1 == num)
+ {// EOS
+ throw new IOException("Peer closed socket");
+ }
+ if (0 == num) // no more data
+ return 0;
+ }
+ // OK, now we get the whole header, change the status and return message size
+ return readState.headFinished();
+ }
+
+ /**
+ * Read message body from channel. It doesn't try to complete. If there is nothing in
+ * the channel, the method returns immediately.
+ *
+ * @param conn The connection
+ * @return remaining bytes for the message
+ * @throws IOException
+ */
+ private int readBody(Connection conn)
+ throws IOException
+ {
+ ByteBuffer bodyBuf = conn.getReadState().getReadBodyBuffer();
+
+ SocketChannel sc = conn.getSocketChannel();
+ while (bodyBuf.remaining() > 0)
+ {
+ int num = sc.read(bodyBuf);
+ if (-1 == num) // EOS
+ throw new IOException("Couldn't read from socket as peer closed the socket");
+ if (0 == num) // no more data
+ return bodyBuf.remaining();
+ }
+ // OK, we finished reading the whole message! Flip it (not necessary though)
+ bodyBuf.flip();
+ return 0;
+ }
+ }
+
+ private class ExecuteTask implements Runnable {
+ Address m_addr = null;
+ ByteBuffer m_buf = null;
+
+ public ExecuteTask(Address addr, ByteBuffer buf)
+ {
+ m_addr = addr;
+ m_buf = buf;
+ }
+
+ public void run()
+ {
+ receive(m_addr, m_buf.array(), m_buf.arrayOffset(), m_buf.limit());
+ }
+ }
+
+ private class ConnectionReadState {
+ private final Connection m_conn;
+
+ // Status for receiving message
+ private boolean m_headFinished = false;
+ private ByteBuffer m_readBodyBuf = null;
+ private final ByteBuffer m_readHeadBuf = ByteBuffer.allocate(Connection.HEADER_SIZE);
+
+ public ConnectionReadState(Connection conn)
+ {
+ m_conn = conn;
+ }
+
+ ByteBuffer getReadBodyBuffer()
+ {
+ return m_readBodyBuf;
+ }
+
+ ByteBuffer getReadHeadBuffer()
+ {
+ return m_readHeadBuf;
+ }
+
+ void bodyFinished()
+ {
+ m_headFinished = false;
+ m_readHeadBuf.clear();
+ m_readBodyBuf = null;
+ m_conn.updateLastAccessed();
+ }
+
+ /**
+ * Status change for finishing reading the message header (data already in buffer)
+ *
+ * @return message size
+ */
+ int headFinished()
+ {
+ m_headFinished = true;
+ m_readHeadBuf.flip();
+ int messageSize = m_readHeadBuf.getInt();
+ m_readBodyBuf = ByteBuffer.allocate(messageSize);
+ m_conn.updateLastAccessed();
+ return messageSize;
+ }
+
+ boolean isHeadFinished()
+ {
+ return m_headFinished;
+ }
+ }
+
+ class Connection extends ConnectionTable.Connection {
+ private SocketChannel sock_ch = null;
+ private WriteHandler m_writeHandler;
+ private SelectorWriteHandler m_selectorWriteHandler;
+ private final ConnectionReadState m_readState;
+
+ private static final int HEADER_SIZE = 4;
+ final ByteBuffer headerBuffer = ByteBuffer.allocate(HEADER_SIZE);
+
+ Connection(SocketChannel s, Address peer_addr)
+ {
+ super(s.socket(), peer_addr);
+ sock_ch = s;
+ m_readState = new ConnectionReadState(this);
+ is_running=true;
+ }
+
+ private ConnectionReadState getReadState()
+ {
+ return m_readState;
+ }
+
+ private void setupWriteHandler(WriteHandler hdlr)
+ {
+ m_writeHandler = hdlr;
+ m_selectorWriteHandler = hdlr.add(sock_ch);
+ }
+
+
+
+ void doSend(byte[] buffie, int offset, int length) throws Exception
+ {
+ MyFuture result = new MyFuture();
+ m_writeHandler.write(sock_ch, ByteBuffer.wrap(buffie, offset, length), result, m_selectorWriteHandler);
+ Object ex = result.get();
+ if (ex instanceof Exception)
+ {
+ if (log.isErrorEnabled())
+ log.error("failed sending message", (Exception)ex);
+ if (((Exception)ex).getCause() instanceof IOException)
+ throw (IOException) ((Exception)ex).getCause();
+ throw (Exception)ex;
+ }
+ result.get();
+ }
+
+
+ SocketChannel getSocketChannel()
+ {
+ return sock_ch;
+ }
+
+ void closeSocket()
+ {
+
+ if (sock_ch != null)
+ {
+ try
+ {
+ if(sock_ch.isConnected() && sock_ch.isOpen()) {
+ sock_ch.close();
+ }
+ }
+ catch (Exception e)
+ {
+ log.error("error closing socket connection", e);
+ }
+ sock_ch = null;
+ }
+ }
+
+
+ void closed()
+ {
+ Address peerAddr = getPeerAddress();
+ synchronized (conns)
+ {
+ conns.remove(peerAddr);
+ }
+ notifyConnectionClosed(peerAddr);
+ }
+ }
+
+
+ /**
+ * Handle writing to non-blocking NIO connection.
+ */
+ private static class WriteHandler implements Runnable {
+ // Create a queue for write requests (unbounded)
+ private final LinkedBlockingQueue queue= new LinkedBlockingQueue();
+
+ private final Selector selector= initSelector();
+ private int m_pendingChannels; // count of the number of channels that have pending writes
+ // note that this variable is only accessed by one thread.
+
+ // allocate and reuse the header for all buffer write operations
+ private ByteBuffer m_headerBuffer = ByteBuffer.allocate(Connection.HEADER_SIZE);
+ private final Log log;
+
+
+ public WriteHandler(Log log) {
+ this.log=log;
+ }
+
+ Selector initSelector() {
+ try
+ {
+ return SelectorProvider.provider().openSelector();
+ }
+ catch (IOException e)
+ {
+ if (log.isErrorEnabled()) log.error(e);
+ throw new IllegalStateException(e.getMessage());
+ }
+ }
+
+ /**
+ * create instances of WriteHandler threads for sending data.
+ *
+ * @param workerThreads is the number of threads to create.
+ */
+ private static WriteHandler[] create(org.jgroups.util.ThreadFactory f, int workerThreads, ThreadGroup tg, List backGroundThreads, Log log)
+ {
+ WriteHandler[] handlers = new WriteHandler[workerThreads];
+ for (int looper = 0; looper < workerThreads; looper++)
+ {
+ handlers[looper] = new WriteHandler(log);
+
+ Thread thread = f.newThread(tg, handlers[looper], "nioWriteHandlerThread");
+ thread.setDaemon(true);
+ thread.start();
+ backGroundThreads.add(thread);
+ }
+ return handlers;
+ }
+
+ /**
+ * Add a new channel to be handled.
+ *
+ * @param channel
+ */
+ private SelectorWriteHandler add(SocketChannel channel)
+ {
+ return new SelectorWriteHandler(channel, selector, m_headerBuffer);
+ }
+
+ /**
+ * Writes buffer to the specified socket connection. This is always performed asynchronously. If you want
+ * to perform a synchrounous write, call notification.`get() which will block until the write operation is complete.
+ * Best practice is to call notification.getException() which may return any exceptions that occured during the write
+ * operation.
+ *
+ * @param channel is where the buffer is written to.
+ * @param buffer is what we write.
+ * @param notification may be specified if you want to know how many bytes were written and know if an exception
+ * occurred.
+ */
+ private void write(SocketChannel channel, ByteBuffer buffer, MyFuture notification, SelectorWriteHandler hdlr) throws InterruptedException
+ {
+ queue.put(new WriteRequest(channel, buffer, notification, hdlr));
+ }
+
+ private static void close(SelectorWriteHandler entry)
+ {
+ entry.cancel();
+ }
+
+ private static void handleChannelError( SelectorWriteHandler entry, Throwable error)
+ {
+ // notify callers of the exception and drain all of the send buffers for this channel.
+ do
+ {
+ if (error != null)
+ entry.notifyError(error);
+ }
+ while (entry.next());
+ close(entry);
+ }
+
+ // process the write operation
+ private void processWrite(Selector selector)
+ {
+ Set keys = selector.selectedKeys();
+ Object arr[] = keys.toArray();
+ for (Object anArr : arr) {
+ SelectionKey key = (SelectionKey) anArr;
+ SelectorWriteHandler entry = (SelectorWriteHandler) key.attachment();
+ boolean needToDecrementPendingChannels = false;
+ try {
+ if (0 == entry.write()) { // write the buffer and if the remaining bytes is zero,
+ // notify the caller of number of bytes written.
+ entry.notifyObject(entry.getBytesWritten());
+ // switch to next write buffer or clear interest bit on socket channel.
+ if (!entry.next()) {
+ needToDecrementPendingChannels = true;
+ }
+ }
+
+ }
+ catch (IOException e) {
+ needToDecrementPendingChannels = true;
+ // connection must of closed
+ handleChannelError(entry, e);
+ }
+ finally {
+ if (needToDecrementPendingChannels)
+ m_pendingChannels--;
+ }
+ }
+ keys.clear();
+ }
+
+ public void run()
+ {
+ while (selector.isOpen())
+ {
+ try
+ {
+ WriteRequest queueEntry;
+ Object o;
+
+ // When there are no more commands in the Queue, we will hit the blocking code after this loop.
+ while (null != (o = queue.poll(0L, TimeUnit.MILLISECONDS)))
+ {
+ if (o instanceof Shutdown) // Stop the thread
+ {
+ try {
+ selector.close();
+ } catch(IOException e) {
+ if (log.isTraceEnabled()) log.trace("Write selector close operation failed" , e);
+ }
+ return;
+ }
+ queueEntry = (WriteRequest) o;
+
+ if (queueEntry.getHandler().add(queueEntry))
+ {
+ // If the add operation returns true, than means that a buffer is available to be written to the
+ // corresponding channel and channel's selection key has been modified to indicate interest in the
+ // 'write' operation.
+ // If the add operation threw an exception, we will not increment m_pendingChannels which
+ // seems correct as long as a new buffer wasn't added to be sent.
+ // Another way to view this is that we don't have to protect m_pendingChannels on the increment
+ // side, only need to protect on the decrement side (this logic of this run() will be incorrect
+ // if m_pendingChannels is set incorrectly).
+ m_pendingChannels++;
+ }
+
+ try
+ {
+ // process any connections ready to be written to.
+ if (selector.selectNow() > 0)
+ {
+ processWrite(selector);
+ }
+ }
+ catch (IOException e)
+ { // need to understand what causes this error so we can handle it properly
+ if (log.isErrorEnabled()) log.error("SelectNow operation on write selector failed, didn't expect this to occur, please report this", e);
+ return; // if select fails, give up so we don't go into a busy loop.
+ }
+ }
+
+ // if there isn't any pending work to do, block on queue to get next request.
+ if (m_pendingChannels == 0)
+ {
+ o = queue.take();
+ if (o instanceof Shutdown){ // Stop the thread
+ try {
+ selector.close();
+ } catch(IOException e) {
+ if (log.isTraceEnabled()) log.trace("Write selector close operation failed" , e);
+ }
+ return;
+ }
+ queueEntry = (WriteRequest) o;
+ if (queueEntry.getHandler().add(queueEntry))
+ m_pendingChannels++;
+ }
+ // otherwise do a blocking wait select operation.
+ else
+ {
+ try
+ {
+ if ((selector.select()) > 0)
+ {
+ processWrite(selector);
+ }
+ }
+ catch (IOException e)
+ { // need to understand what causes this error
+ if (log.isErrorEnabled()) log.error("Failure while writing to socket",e);
+ }
+ }
+ }
+ catch (InterruptedException e)
+ {
+ if (log.isErrorEnabled()) log.error("Thread ("+Thread.currentThread().getName() +") was interrupted", e);
+ }
+ catch (Throwable e) // Log throwable rather than terminating this thread.
+ { // We are a daemon thread so we shouldn't prevent the process from terminating if
+ // the controlling thread decides that should happen.
+ if (log.isErrorEnabled()) log.error("Thread ("+Thread.currentThread().getName() +") caught Throwable" , e);
+ }
+ }
+ }
+ }
+
+
+ // Wrapper class for passing Write requests. There will be an instance of this class for each socketChannel
+ // mapped to a Selector.
+ public static class SelectorWriteHandler {
+
+ private final List m_writeRequests = new LinkedList(); // Collection of writeRequests
+ private boolean m_headerSent = false;
+ private SocketChannel m_channel;
+ private SelectionKey m_key;
+ private Selector m_selector;
+ private int m_bytesWritten = 0;
+ private boolean m_enabled = false;
+ private ByteBuffer m_headerBuffer;
+
+ SelectorWriteHandler(SocketChannel channel, Selector selector, ByteBuffer headerBuffer)
+ {
+ m_channel = channel;
+ m_selector = selector;
+ m_headerBuffer = headerBuffer;
+ }
+
+ private void register(Selector selector, SocketChannel channel) throws ClosedChannelException
+ {
+ // register the channel but don't enable OP_WRITE until we have a write request.
+ m_key = channel.register(selector, 0, this);
+ }
+
+ // return true if selection key is enabled when it wasn't previous to call.
+ private boolean enable()
+ {
+ boolean rc = false;
+
+ try
+ {
+ if (m_key == null)
+ { // register the socket on first access,
+ // we are the only thread using this variable, so no sync needed.
+ register(m_selector, m_channel);
+ }
+ }
+ catch (ClosedChannelException e)
+ {
+ return rc;
+ }
+
+ if (!m_enabled)
+ {
+ rc = true;
+ try
+ {
+ m_key.interestOps(SelectionKey.OP_WRITE);
+ }
+ catch (CancelledKeyException e)
+ { // channel must of closed
+ return false;
+ }
+ m_enabled = true;
+ }
+ return rc;
+ }
+
+ private void disable()
+ {
+ if (m_enabled)
+ {
+ try
+ {
+ m_key.interestOps(0); // pass zero which means that we are not interested in being
+ // notified of anything for this channel.
+ }
+ catch (CancelledKeyException eat) // If we finished writing and didn't get an exception, then
+ { // we probably don't need to throw this exception (if they try to write
+ // again, we will then throw an exception).
+ }
+ m_enabled = false;
+ }
+ }
+
+ private void cancel()
+ {
+ m_key.cancel();
+ }
+
+ boolean add(WriteRequest entry)
+ {
+ m_writeRequests.add(entry);
+ return enable();
+ }
+
+ WriteRequest getCurrentRequest()
+ {
+ return m_writeRequests.get(0);
+ }
+
+ SocketChannel getChannel()
+ {
+ return m_channel;
+ }
+
+ ByteBuffer getBuffer()
+ {
+ return getCurrentRequest().getBuffer();
+ }
+
+ MyFuture getCallback()
+ {
+ return getCurrentRequest().getCallback();
+ }
+
+ int getBytesWritten()
+ {
+ return m_bytesWritten;
+ }
+
+ void notifyError(Throwable error)
+ {
+ if (getCallback() != null)
+ getCallback().setException(error);
+ }
+
+ void notifyObject(Object result)
+ {
+ if (getCallback() != null)
+ getCallback().set(result);
+ }
+
+ /**
+ * switch to next request or disable write interest bit if there are no more buffers.
+ *
+ * @return true if another request was found to be processed.
+ */
+ boolean next()
+ {
+ m_headerSent = false;
+ m_bytesWritten = 0;
+
+ m_writeRequests.remove(0); // remove current entry
+ boolean rc = !m_writeRequests.isEmpty();
+ if (!rc) // disable select for this channel if no more entries
+ disable();
+ return rc;
+ }
+
+ /**
+ * @return bytes remaining to write. This function will only throw IOException, unchecked exceptions are not
+ * expected to be thrown from here. It is very important for the caller to know if an unchecked exception can
+ * be thrown in here. Please correct the following throws list to include any other exceptions and update
+ * caller to handle them.
+ * @throws IOException
+ */
+ int write() throws IOException
+ {
+ // Send header first. Note that while we are writing the shared header buffer,
+ // no other threads can access the header buffer as we are the only thread that has access to it.
+ if (!m_headerSent)
+ {
+ m_headerSent = true;
+ m_headerBuffer.clear();
+ m_headerBuffer.putInt(getBuffer().remaining());
+ m_headerBuffer.flip();
+ do
+ {
+ getChannel().write(m_headerBuffer);
+ } // we should be able to handle writing the header in one action but just in case, just do a busy loop
+ while (m_headerBuffer.remaining() > 0);
+
+ }
+
+ m_bytesWritten += (getChannel().write(getBuffer()));
+
+ return getBuffer().remaining();
+ }
+
+ }
+
+ public static class WriteRequest {
+ private final SocketChannel m_channel;
+ private final ByteBuffer m_buffer;
+ private final MyFuture m_callback;
+ private final SelectorWriteHandler m_hdlr;
+
+ WriteRequest(SocketChannel channel, ByteBuffer buffer, MyFuture callback, SelectorWriteHandler hdlr)
+ {
+ m_channel = channel;
+ m_buffer = buffer;
+ m_callback = callback;
+ m_hdlr = hdlr;
+ }
+
+ SelectorWriteHandler getHandler()
+ {
+ return m_hdlr;
+ }
+
+ SocketChannel getChannel()
+ {
+ return m_channel;
+ }
+
+ ByteBuffer getBuffer()
+ {
+ return m_buffer;
+ }
+
+ MyFuture getCallback()
+ {
+ return m_callback;
+ }
+
+ }
+
+ private static class NullCallable implements Callable {
+
+ public Object call() {
+ System.out.println("nullCallable.call invoked");
+ return null;
+ }
+ }
+ private static final NullCallable NULLCALL = new NullCallable();
+
+ public static class MyFuture extends FutureTask { // make FutureTask work like the old FutureResult
+ public MyFuture() {
+ super(NULLCALL);
+ }
+
+ protected void set(Object o) {
+ super.set(o);
+ }
+
+
+ protected void setException(Throwable t) {
+ super.setException(t);
+ }
+ }
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/DistributedHashtable.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/DistributedHashtable.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/DistributedHashtable.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,701 @@
+// $Id: DistributedHashtable.java,v 1.1 2012/08/17 14:51:18 marcin Exp $
+
+package org.jgroups.blocks;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jgroups.*;
+import org.jgroups.persistence.CannotPersistException;
+import org.jgroups.persistence.CannotRemoveException;
+import org.jgroups.persistence.PersistenceFactory;
+import org.jgroups.persistence.PersistenceManager;
+import org.jgroups.util.Promise;
+import org.jgroups.util.Util;
+
+import java.io.*;
+import java.util.*;
+
+
+/**
+ * Provides the abstraction of a java.util.Hashtable that is replicated at several
+ * locations. Any change to the hashtable (clear, put, remove etc) will transparently be
+ * propagated to all replicas in the group. All read-only methods will always access the
+ * local replica.
+ * Both keys and values added to the hashtable must be serializable , the reason
+ * being that they will be sent across the network to all replicas of the group. Having said
+ * this, it is now for example possible to add RMI remote objects to the hashtable as they
+ * are derived from java.rmi.server.RemoteObject
which in turn is serializable.
+ * This allows to lookup shared distributed objects by their name and invoke methods on them,
+ * regardless of one's onw location. A DistributedHashtable
thus allows to
+ * implement a distributed naming service in just a couple of lines.
+ * An instance of this class will contact an existing member of the group to fetch its
+ * initial state (using the state exchange funclet StateExchangeFunclet
.
+ * @author Bela Ban
+ * @author Alfonso Olias-Sanz
+ * @version $Id: DistributedHashtable.java,v 1.1 2012/08/17 14:51:18 marcin Exp $
+ * @deprecated Use {@link org.jgroups.blocks.ReplicatedHashMap} instead
+ */
+public class DistributedHashtable extends Hashtable implements ExtendedMessageListener, ExtendedMembershipListener {
+ private static final long serialVersionUID=7910133360803785134L;
+
+
+ public interface Notification {
+ void entrySet(Object key, Object value);
+ void entryRemoved(Object key);
+ void viewChange(Vector new_mbrs, Vector old_mbrs);
+ void contentsSet(Map new_entries);
+ void contentsCleared();
+ }
+
+
+ private transient Channel channel;
+ protected transient RpcDispatcher disp=null;
+ private String groupname=null;
+ private final transient Vector notifs=new Vector(); // to be notified when mbrship changes
+ private final Vector members=new Vector(); // keeps track of all DHTs
+ private transient Class[] put_signature=null;
+ private transient Class[] putAll_signature=null;
+ private transient Class[] clear_signature=null;
+ private transient Class[] remove_signature=null;
+ private transient boolean persistent=false; // whether to use PersistenceManager to save state
+ private transient PersistenceManager persistence_mgr=null;
+
+ /** Determines when the updates have to be sent across the network, avoids sending unnecessary
+ * messages when there are no member in the group */
+ private transient boolean send_message = false;
+
+ protected final transient Promise state_promise=new Promise();
+
+ protected final Log log=LogFactory.getLog(this.getClass());
+
+
+
+
+ /**
+ * Creates a DistributedHashtable
+ * @param groupname The name of the group to join
+ * @param factory The ChannelFactory which will be used to create a channel
+ * @param properties The property string to be used to define the channel. This will override the properties of
+ * the factory. If null, then the factory properties will be used
+ * @param state_timeout The time to wait until state is retrieved in milliseconds. A value of 0 means wait forever.
+ */
+ public DistributedHashtable(String groupname, ChannelFactory factory,
+ String properties, long state_timeout)
+ throws ChannelException {
+ this.groupname=groupname;
+ initSignatures();
+ if(factory != null) {
+ channel=properties != null? factory.createChannel((Object)properties) : factory.createChannel();
+ }
+ else {
+ channel=new JChannel(properties);
+ }
+ disp=new RpcDispatcher(channel, this, this, this);
+ channel.connect(groupname);
+ start(state_timeout);
+ }
+
+ /**
+ * Creates a DisttributedHashtable. Optionally the contents can be saved to
+ * persistemt storage using the {@link PersistenceManager}.
+ * @param groupname Name of the group to join
+ * @param factory Instance of a ChannelFactory to create the channel
+ * @param properties Protocol stack properties. This will override the properties of the factory. If
+ * null, then the factory properties will be used
+ * @param persistent Whether the contents should be persisted
+ * @param state_timeout Max number of milliseconds to wait until state is
+ * retrieved
+ */
+ public DistributedHashtable(String groupname, ChannelFactory factory, String properties,
+ boolean persistent, long state_timeout)
+ throws ChannelException {
+ this.groupname=groupname;
+ this.persistent=persistent;
+ initSignatures();
+ if(factory != null) {
+ channel=properties != null? factory.createChannel((Object)properties) : factory.createChannel();
+ }
+ else {
+ channel=new JChannel(properties);
+ }
+ disp=new RpcDispatcher(channel, this, this, this);
+ channel.connect(groupname);
+ start(state_timeout);
+ }
+
+
+ public DistributedHashtable(Channel channel, long state_timeout) {
+ this(channel, false, state_timeout);
+ }
+
+
+ public DistributedHashtable(Channel channel, boolean persistent, long state_timeout) {
+ this.groupname = channel.getClusterName();
+ this.channel = channel;
+ this.persistent=persistent;
+ init(state_timeout);
+ }
+
+ /**
+ * Uses a user-provided PullPushAdapter to create the dispatcher rather than a Channel. If id is non-null, it will be
+ * used to register under that id. This is typically used when another building block is already using
+ * PullPushAdapter, and we want to add this building block in addition. The id is the used to discriminate
+ * between messages for the various blocks on top of PullPushAdapter. If null, we will assume we are the
+ * first block created on PullPushAdapter.
+ * @param adapter The PullPushAdapter which to use as underlying transport
+ * @param id A serializable object (e.g. an Integer) used to discriminate (multiplex/demultiplex) between
+ * requests/responses for different building blocks on top of PullPushAdapter.
+ * @param state_timeout Max number of milliseconds to wait until state is
+ * retrieved
+ */
+ public DistributedHashtable(PullPushAdapter adapter, Serializable id, long state_timeout)
+ throws ChannelNotConnectedException, ChannelClosedException {
+ initSignatures();
+ this.channel = (Channel)adapter.getTransport();
+ this.groupname = this.channel.getClusterName();
+ disp=new RpcDispatcher(adapter, id, this, this, this);
+ start(state_timeout);
+ }
+
+ public DistributedHashtable(PullPushAdapter adapter, Serializable id) {
+ initSignatures();
+ this.channel = (Channel)adapter.getTransport();
+ this.groupname = this.channel.getClusterName();
+ disp=new RpcDispatcher(adapter, id, this, this, this);
+ }
+
+ protected final void init(long state_timeout) {
+ initSignatures();
+ disp = new RpcDispatcher(channel, this, this, this);
+
+ // Changed by bela (jan 20 2003): start() has to be called by user (only when providing
+ // own channel). First, Channel.connect() has to be called, then start().
+ // start(state_timeout);
+ }
+
+
+ /**
+ * Fetches the state
+ * @param state_timeout
+ * @throws ChannelClosedException
+ * @throws ChannelNotConnectedException
+ */
+ public final void start(long state_timeout) throws ChannelClosedException, ChannelNotConnectedException {
+ boolean rc;
+ if(persistent) {
+ if(log.isInfoEnabled()) log.info("fetching state from database");
+ try {
+ persistence_mgr=PersistenceFactory.getInstance().createManager();
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) log.error("failed creating PersistenceManager, " +
+ "turning persistency off. Exception: " + Util.printStackTrace(ex));
+ persistent=false;
+ }
+ }
+
+ state_promise.reset();
+ rc=channel.getState(null, state_timeout);
+ if(rc) {
+ if(log.isInfoEnabled()) log.info("state was retrieved successfully, waiting for setState()");
+ Boolean result=state_promise.getResult(state_timeout);
+ if(result == null) {
+ if(log.isErrorEnabled()) log.error("setState() never got called");
+ }
+ else {
+ if(log.isInfoEnabled()) log.info("setState() was called");
+ }
+ }
+ else {
+ if(log.isInfoEnabled()) log.info("state could not be retrieved (first member)");
+ if(persistent) {
+ if(log.isInfoEnabled()) log.info("fetching state from database");
+ try {
+ Map m=persistence_mgr.retrieveAll();
+ if(m != null) {
+ Map.Entry entry;
+ Object key, val;
+ for(Iterator it=m.entrySet().iterator(); it.hasNext();) {
+ entry=(Map.Entry)it.next();
+ key=entry.getKey();
+ val=entry.getValue();
+ if(log.isInfoEnabled()) log.info("inserting " + key + " --> " + val);
+ put(key, val); // will replicate key and value
+ }
+ }
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) log.error("failed creating PersistenceManager, " +
+ "turning persistency off. Exception: " + Util.printStackTrace(ex));
+ persistent=false;
+ }
+ }
+ }
+ }
+
+
+ public Address getLocalAddress() {return channel != null ? channel.getLocalAddress() : null;}
+ public String getGroupName() {return groupname;}
+ public Channel getChannel() {return channel;}
+ public boolean getPersistent() {return persistent;}
+ public void setPersistent(boolean p) {persistent=p;}
+
+
+ public void setDeadlockDetection(boolean flag) {
+ if(disp != null)
+ disp.setDeadlockDetection(flag);
+ }
+
+ public void addNotifier(Notification n) {
+ if(!notifs.contains(n))
+ notifs.addElement(n);
+ }
+
+ public void removeNotifier(Notification n) {
+ if(notifs.contains(n))
+ notifs.removeElement(n);
+ }
+
+ public void stop() {
+ if(disp != null) {
+ disp.stop();
+ disp=null;
+ }
+ if(channel != null) {
+ channel.close();
+ channel=null;
+ }
+ }
+
+
+ /**
+ * Maps the specified key to the specified value in the hashtable. Neither of both parameters can be null
+ * @param key - the hashtable key
+ * @param value - the value
+ * @return the previous value of the specified key in this hashtable, or null if it did not have one
+ */
+ public Object put(Object key, Object value) {
+ Object prev_val=get(key);
+
+ //Changes done by
+ //if true, propagate action to the group
+ if(send_message == true) {
+ try {
+ disp.callRemoteMethods(
+ null, "_put", new Object[]{key,value},
+ put_signature,
+ GroupRequest.GET_ALL,
+ 0);
+ }
+ catch(Exception e) {
+ //return null;
+ }
+ }
+ else {
+ _put(key, value);
+ //don't have to do prev_val = super.put(..) as is done at the beginning
+ }
+ return prev_val;
+ }
+
+ /**
+ * Copies all of the mappings from the specified Map to this Hashtable These mappings will replace any mappings that this Hashtable had for any of the keys currently in the specified Map.
+ * @param m - Mappings to be stored in this map
+ */
+ public void putAll(Map m) {
+ //Changes done by
+ //if true, propagate action to the group
+ if(send_message == true) {
+ try {
+ disp.callRemoteMethods(
+ null, "_putAll", new Object[]{m},
+ putAll_signature,
+ GroupRequest.GET_ALL,
+ 0);
+ }
+ catch(Throwable t) {
+ }
+ }
+ else {
+ _putAll(m);
+ }
+ }
+
+ /**
+ * Clears this hashtable so that it contains no keys
+ */
+ public void clear() {
+ //Changes done by
+ //if true, propagate action to the group
+ if(send_message == true) {
+ try {
+ disp.callRemoteMethods(
+ null, "_clear", null,
+ clear_signature,
+ GroupRequest.GET_ALL,
+ 0);
+ }
+ catch(Exception e) {
+ if(log.isErrorEnabled()) log.error("exception=" + e);
+ }
+ }
+ else {
+ _clear();
+ }
+ }
+
+ /**
+ * Removes the key (and its corresponding value) from the Hashtable.
+ * @param key - the key to be removed.
+ * @return the value to which the key had been mapped in this hashtable, or null if the key did not have a mapping.
+ */
+ public Object remove(Object key) {
+ Object retval = get(key);
+
+ //Changes done by
+ //if true, propagate action to the group
+ if(send_message == true) {
+ try {
+ disp.callRemoteMethods(
+ null, "_remove", new Object[]{key},
+ remove_signature,
+ GroupRequest.GET_ALL,
+ 0);
+ //return retval;
+ }
+ catch(Exception e) {
+ //return null;
+ }
+ }
+ else {
+ _remove(key);
+ //don't have to do retval = super.remove(..) as is done at the beginning
+ }
+ return retval;
+ }
+
+
+
+ /*------------------------ Callbacks -----------------------*/
+
+ public Object _put(Object key, Object value) {
+ Object retval=super.put(key, value);
+ if(persistent) {
+ try {
+ persistence_mgr.save((Serializable)key, (Serializable)value);
+ }
+ catch(CannotPersistException cannot_persist_ex) {
+ if(log.isErrorEnabled()) log.error("failed persisting " + key + " + " +
+ value + ", exception=" + cannot_persist_ex);
+ }
+ catch(Throwable t) {
+ if(log.isErrorEnabled()) log.error("failed persisting " + key + " + " +
+ value + ", exception=" + Util.printStackTrace(t));
+ }
+ }
+ for(int i=0; i < notifs.size(); i++)
+ ((Notification)notifs.elementAt(i)).entrySet(key, value);
+ return retval;
+ }
+
+
+ /**
+ * @see java.util.Map#putAll(java.util.Map)
+ */
+ public void _putAll(Map m) {
+ if (m == null)
+ return;
+
+ // Calling the method below seems okay, but would result in ... deadlock !
+ // The reason is that Map.putAll() calls put(), which we override, which results in
+ // lock contention for the map.
+
+ // ---> super.putAll(m); <--- CULPRIT !!!@#$%$
+
+ // That said let's do it the stupid way:
+ Map.Entry entry;
+ for(Iterator it=m.entrySet().iterator(); it.hasNext();) {
+ entry=(Map.Entry)it.next();
+ super.put(entry.getKey(), entry.getValue());
+ }
+
+ if (persistent) {
+ try {
+ persistence_mgr.saveAll(m);
+ }
+ catch (CannotPersistException persist_ex) {
+ if(log.isErrorEnabled()) log.error("failed persisting contents: " + persist_ex);
+ }
+ catch (Throwable t) {
+ if(log.isErrorEnabled()) log.error("failed persisting contents: " + t);
+ }
+ }
+ for(int i=0; i < notifs.size(); i++)
+ ((Notification)notifs.elementAt(i)).contentsSet(m);
+ }
+
+
+ public void _clear() {
+ super.clear();
+ if(persistent) {
+ try {
+ persistence_mgr.clear();
+ }
+ catch(CannotRemoveException cannot_remove_ex) {
+ if(log.isErrorEnabled()) log.error("failed clearing contents, exception=" + cannot_remove_ex);
+ }
+ catch(Throwable t) {
+ if(log.isErrorEnabled()) log.error("failed clearing contents, exception=" + t);
+ }
+ }
+ for(int i=0; i < notifs.size(); i++)
+ ((Notification)notifs.elementAt(i)).contentsCleared();
+ }
+
+
+ public Object _remove(Object key) {
+ Object retval=super.remove(key);
+ if(persistent) {
+ try {
+ persistence_mgr.remove((Serializable)key);
+ }
+ catch(CannotRemoveException cannot_remove_ex) {
+ if(log.isErrorEnabled()) log.error("failed clearing contents, exception=" + cannot_remove_ex);
+ }
+ catch(Throwable t) {
+ if(log.isErrorEnabled()) log.error("failed clearing contents, exception=" + t);
+ }
+ }
+ for(int i=0; i < notifs.size(); i++)
+ ((Notification)notifs.elementAt(i)).entryRemoved(key);
+
+ return retval;
+ }
+
+ /*----------------------------------------------------------*/
+
+
+
+ /*-------------------- State Exchange ----------------------*/
+
+ public void receive(Message msg) { }
+
+ public byte[] getState() {
+ Object key, val;
+ Hashtable copy=new Hashtable();
+
+ for(Enumeration e=keys(); e.hasMoreElements();) {
+ key=e.nextElement();
+ val=get(key);
+ copy.put(key, val);
+ }
+ try {
+ return Util.objectToByteBuffer(copy);
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) log.error("exception marshalling state: " + ex);
+ return null;
+ }
+ }
+
+
+ public void setState(byte[] new_state) {
+ Hashtable new_copy;
+
+ try {
+ new_copy=(Hashtable)Util.objectFromByteBuffer(new_state);
+ if(new_copy == null)
+ return;
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) log.error("exception unmarshalling state: " + ex);
+ return;
+ }
+ _putAll(new_copy);
+ state_promise.setResult(Boolean.TRUE);
+ }
+
+
+
+ /*------------------- Membership Changes ----------------------*/
+
+ public void viewAccepted(View new_view) {
+ Vector new_mbrs=new_view.getMembers();
+
+ if(new_mbrs != null) {
+ sendViewChangeNotifications(new_mbrs, members); // notifies observers (joined, left)
+ members.removeAllElements();
+ for(int i=0; i < new_mbrs.size(); i++)
+ members.addElement(new_mbrs.elementAt(i));
+ }
+ //if size is bigger than one, there are more peers in the group
+ //otherwise there is only one server.
+ send_message=members.size() > 1;
+ }
+
+
+ /** Called when a member is suspected */
+ public void suspect(Address suspected_mbr) {
+ ;
+ }
+
+
+ /** Block sending and receiving of messages until ViewAccepted is called */
+ public void block() {}
+
+
+
+ void sendViewChangeNotifications(Vector new_mbrs, Vector old_mbrs) {
+ Vector joined, left;
+ Object mbr;
+ Notification n;
+
+ if(notifs.size() == 0 || old_mbrs == null || new_mbrs == null ||
+ old_mbrs.size() == 0 || new_mbrs.size() == 0)
+ return;
+
+
+ // 1. Compute set of members that joined: all that are in new_mbrs, but not in old_mbrs
+ joined=new Vector();
+ for(int i=0; i < new_mbrs.size(); i++) {
+ mbr=new_mbrs.elementAt(i);
+ if(!old_mbrs.contains(mbr))
+ joined.addElement(mbr);
+ }
+
+
+ // 2. Compute set of members that left: all that were in old_mbrs, but not in new_mbrs
+ left=new Vector();
+ for(int i=0; i < old_mbrs.size(); i++) {
+ mbr=old_mbrs.elementAt(i);
+ if(!new_mbrs.contains(mbr)) {
+ left.addElement(mbr);
+ }
+ }
+
+ for(int i=0; i < notifs.size(); i++) {
+ n=(Notification)notifs.elementAt(i);
+ n.viewChange(joined, left);
+ }
+ }
+
+
+ final void initSignatures() {
+ try {
+ if(put_signature == null) {
+ put_signature=new Class[] {Object.class,Object.class};
+ }
+
+ if(putAll_signature == null) {
+ putAll_signature=new Class[] {Map.class};
+ }
+
+ if(clear_signature == null)
+ clear_signature=new Class[0];
+
+ if(remove_signature == null) {
+ remove_signature=new Class[] {Object.class};
+ }
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) log.error("exception=" + ex);
+ }
+ }
+
+ public static void main(String[] args) {
+ try {
+ // The setup here is kind of weird:
+ // 1. Create a channel
+ // 2. Create a DistributedHashtable (on the channel)
+ // 3. Connect the channel (so the HT gets a VIEW_CHANGE)
+ // 4. Start the HT
+ //
+ // A simpler setup is
+ // DistributedHashtable ht = new DistributedHashtable("demo", null,
+ // "file://c:/JGroups-2.0/conf/state_transfer.xml", 5000);
+
+ JChannel c = new JChannel("file:/c:/JGroups-2.0/conf/state_transfer.xml");
+ DistributedHashtable ht = new DistributedHashtable(c, false, 5000);
+ c.connect("demo");
+ ht.start(5000);
+
+
+
+ ht.put("name", "Michelle Ban");
+ Object old_key = ht.remove("name");
+ System.out.println("old key was " + old_key);
+ ht.put("newkey", "newvalue");
+
+ Map m = new HashMap();
+ m.put("k1", "v1");
+ m.put("k2", "v2");
+
+ ht.putAll(m);
+
+ System.out.println("hashmap is " + ht);
+ }
+ catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+ public byte[] getState(String state_id) {
+ // not implemented
+ return null;
+ }
+
+ public void getState(OutputStream ostream) {
+ Object key, val;
+ Hashtable copy=new Hashtable();
+ ObjectOutputStream oos = null;
+
+ for(Enumeration e=keys(); e.hasMoreElements();) {
+ key=e.nextElement();
+ val=get(key);
+ copy.put(key, val);
+ }
+ try {
+ oos = new ObjectOutputStream(ostream);
+ oos.writeObject(copy);
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) log.error("exception marshalling state: " + ex);
+ }
+ finally{
+ Util.close(oos);
+ }
+ }
+
+ public void getState(String state_id, OutputStream ostream) {
+ }
+
+ public void setState(String state_id, byte[] state) {
+ }
+
+ public void setState(InputStream istream) {
+ Hashtable new_copy = null;
+ ObjectInputStream ois = null;
+ try{
+ ois = new ObjectInputStream(istream);
+ new_copy = (Hashtable) ois.readObject();
+ ois.close();
+ }catch(Throwable e){
+ e.printStackTrace();
+ if(log.isErrorEnabled()) log.error("exception marshalling state: " + e);
+ }finally{
+ Util.close(ois);
+ }
+ if(new_copy != null)
+ _putAll(new_copy);
+
+ state_promise.setResult(Boolean.TRUE);
+ }
+
+ public void setState(String state_id, InputStream istream) {
+ }
+
+ public void unblock() {
+ }
+
+}
+
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/DistributedLockManager.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/DistributedLockManager.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/DistributedLockManager.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,784 @@
+package org.jgroups.blocks;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jgroups.ChannelException;
+import org.jgroups.MembershipListener;
+import org.jgroups.View;
+import org.jgroups.Address;
+import org.jgroups.blocks.VotingAdapter.FailureVoteResult;
+import org.jgroups.blocks.VotingAdapter.VoteResult;
+import org.jgroups.util.Rsp;
+import org.jgroups.util.RspList;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * Distributed lock manager is responsible for maintaining the lock information
+ * consistent on all participating nodes.
+ *
+ * @author Roman Rokytskyy (rrokytskyy@acm.org)
+ * @author Robert Schaffar-Taurok (robert@fusion.at)
+ * @version $Id: DistributedLockManager.java,v 1.1 2012/08/17 14:51:17 marcin Exp $
+ */
+public class DistributedLockManager implements TwoPhaseVotingListener, LockManager, VoteResponseProcessor, MembershipListener {
+ /**
+ * Definitions for the implementation of the VoteResponseProcessor
+ */
+ private static final int PROCESS_CONTINUE = 0;
+ private static final int PROCESS_SKIP = 1;
+ private static final int PROCESS_BREAK = 2;
+
+ /**
+ * This parameter means that lock acquisition expires after 5 seconds.
+ * If there were no "commit" operation on prepared lock, then it
+ * is treated as expired and is removed from the prepared locks table.
+ */
+ private static final long ACQUIRE_EXPIRATION = 5000;
+
+ /**
+ * This parameter is used during lock releasing. If group fails to release
+ * the lock during the specified period of time, unlocking fails.
+ */
+ private static final long VOTE_TIMEOUT = 10000;
+
+ /** HashMap. List of all prepared locks */
+ private final HashMap preparedLocks = new HashMap();
+
+ /** HashMap. List of all prepared releases */
+ private final HashMap preparedReleases = new HashMap();
+
+ /* HashMap. List of locks on the node */
+ private final HashMap heldLocks = new HashMap();
+
+ private final TwoPhaseVotingAdapter votingAdapter;
+
+ private final Object id;
+
+ final Vector current_members=new Vector();
+
+ protected final Log log=LogFactory.getLog(getClass());
+
+
+ /**
+ * Create instance of this class.
+ *
+ * @param voteChannel instance of {@link VotingAdapter} that will be used
+ * for voting purposes on the lock decrees. voteChannel() will
+ * be wrapped by the instance of the {@link TwoPhaseVotingAdapter}.
+ *
+ * @param id the unique identifier of this lock manager.
+ *
+ * todo check if the node with the same id is already in the group.
+ */
+ public DistributedLockManager(VotingAdapter voteChannel, Object id) {
+ this(new TwoPhaseVotingAdapter(voteChannel), id);
+ }
+
+ /**
+ * Constructor for the DistributedLockManager_cl object.
+ *
+ * @param channel instance of {@link TwoPhaseVotingAdapter}
+ * that will be used for voting purposes on the lock decrees.
+ *
+ * @param id the unique identifier of this lock manager.
+ *
+ * @todo check if the node with the same id is already in the group.
+ */
+ public DistributedLockManager(TwoPhaseVotingAdapter channel, Object id) {
+ this.id = id;
+ this.votingAdapter = channel;
+ this.votingAdapter.addListener(this);
+ if(votingAdapter.getVoteChannel() != null) {
+ votingAdapter.getVoteChannel().addMembershipListener(this);
+ setInitialMembership(votingAdapter.getVoteChannel().getMembers());
+ }
+ }
+
+ private void setInitialMembership(Collection members) {
+ if(members != null) {
+ current_members.clear();
+ current_members.addAll(members);
+ }
+ }
+
+
+ /**
+ * Performs local lock. This method also performs the clean-up of the lock
+ * table, all expired locks are removed.
+ */
+ private boolean localLock(LockDecree lockDecree) {
+ // remove expired locks
+ removeExpired(lockDecree);
+
+ LockDecree localLock =
+ (LockDecree) heldLocks.get(lockDecree.getKey());
+
+ if (localLock == null) {
+
+ // promote lock into commited state
+ lockDecree.commit();
+
+ // no lock exist, perform local lock, note:
+ // we do not store locks that were requested by other manager.
+ if (lockDecree.managerId.equals(id))
+ heldLocks.put(lockDecree.getKey(), lockDecree);
+
+ // everything is fine :)
+ return true;
+ } else
+ return localLock.requester.equals(lockDecree.requester);
+
+ }
+
+ /**
+ * Returns true
if the requested lock can be granted by the
+ * current node.
+ *
+ * @param decree instance of LockDecree
containing information
+ * about the lock.
+ */
+ private boolean canLock(LockDecree decree) {
+ // clean expired locks
+ removeExpired(decree);
+
+ LockDecree lock = (LockDecree)heldLocks.get(decree.getKey());
+ return lock == null || lock.requester.equals(decree.requester);
+ }
+
+ /**
+ * Returns true
if the requested lock can be released by the
+ * current node.
+ *
+ * @param decree instance of {@link LockDecree} containing information
+ * about the lock.
+ */
+ private boolean canRelease(LockDecree decree) {
+ // clean expired locks
+ removeExpired(decree);
+
+ // we need to check only hold locks, because
+ // prepared locks cannot contain the lock
+ LockDecree lock = (LockDecree)heldLocks.get(decree.getKey());
+ return lock == null || lock.requester.equals(decree.requester);
+ }
+
+ /**
+ * Removes expired locks.
+ *
+ * @param decree instance of {@link LockDecree} describing the lock.
+ */
+ private void removeExpired(LockDecree decree) {
+ // remove the invalid (expired) lock
+ LockDecree localLock = (LockDecree)heldLocks.get(decree.getKey());
+ if (localLock != null && !localLock.isValid())
+ heldLocks.remove(localLock.getKey());
+ }
+
+ /**
+ * Releases lock locally.
+ *
+ * @param lockDecree instance of {@link LockDecree} describing the lock.
+ */
+ private boolean localRelease(LockDecree lockDecree) {
+ // remove expired locks
+ removeExpired(lockDecree);
+
+ LockDecree localLock=
+ (LockDecree) heldLocks.get(lockDecree.getKey());
+
+ if(localLock == null) {
+ // no lock exist
+ return true;
+ }
+ else if(localLock.requester.equals(lockDecree.requester)) {
+ // requester owns the lock, release the lock
+ heldLocks.remove(lockDecree.getKey());
+ return true;
+ }
+ else
+ // lock does not belong to requester
+ return false;
+ }
+
+ /**
+ * Locks an object with lockId
on behalf of the specified
+ * owner
.
+ *
+ * @param lockId Object
representing the object to be locked.
+ * @param owner object that requests the lock. This should be the Address of a JGroups member, otherwise we cannot
+ * release the locks for a crashed member !
+ * @param timeout time during which group members should decide
+ * whether to grant a lock or not.
+ *
+ * @throws LockNotGrantedException when the lock cannot be granted.
+ *
+ * @throws ClassCastException if lockId or owner are not serializable.
+ *
+ * @throws ChannelException if something bad happened to underlying channel.
+ */
+ public void lock(Object lockId, Object owner, int timeout)
+ throws LockNotGrantedException, ChannelException
+ {
+ if (!(lockId instanceof Serializable) || !(owner instanceof Serializable))
+ throw new ClassCastException("DistributedLockManager works only with serializable objects.");
+
+ boolean acquired = votingAdapter.vote(
+ new AcquireLockDecree(lockId, owner, id), timeout);
+
+ if (!acquired)
+ throw new LockNotGrantedException("Lock " + lockId + " cannot be granted.");
+ }
+
+ /**
+ * Unlocks an object with lockId
on behalf of the specified
+ * owner
.
+ *
+ * since 2.2.9 this method is only a wrapper for
+ * unlock(Object lockId, Object owner, boolean releaseMultiLocked).
+ * Use that with releaseMultiLocked set to true if you want to be able to
+ * release multiple locked locks (for example after a merge)
+ *
+ * @param lockId long
representing the object to be unlocked.
+ * @param owner object that releases the lock.
+ *
+ * @throws LockNotReleasedException when the lock cannot be released.
+ * @throws ClassCastException if lockId or owner are not serializable.
+ *
+ */
+ public void unlock(Object lockId, Object owner)
+ throws LockNotReleasedException, ChannelException
+ {
+ try {
+ unlock(lockId, owner, false, VOTE_TIMEOUT);
+ } catch (LockMultiLockedException e) {
+ // This should never happen when releaseMultiLocked is false
+ log.error("Caught MultiLockedException but releaseMultiLocked is false", e);
+ }
+ }
+
+
+ public void unlock(Object lockId, Object owner, long timeout)
+ throws LockNotReleasedException, ChannelException
+ {
+ try {
+ unlock(lockId, owner, false, timeout);
+ } catch (LockMultiLockedException e) {
+ // This should never happen when releaseMultiLocked is false
+ log.error("Caught MultiLockedException but releaseMultiLocked is false", e);
+ }
+ }
+
+
+ /**
+ * Unlocks an object with lockId
on behalf of the specified
+ * owner
.
+ * @param lockId long
representing the object to be unlocked.
+ * @param owner object that releases the lock.
+ * @param releaseMultiLocked releases also multiple locked locks. (eg. locks that are locked by another DLM after a merge)
+ *
+ * @throws LockNotReleasedException when the lock cannot be released.
+ * @throws ClassCastException if lockId or owner are not serializable.
+ * @throws LockMultiLockedException if releaseMultiLocked is true and a multiple locked lock has been released.
+ */
+ public void unlock(Object lockId, Object owner, boolean releaseMultiLocked)
+ throws LockNotReleasedException, ChannelException, LockMultiLockedException
+ {
+ unlock(lockId, owner, releaseMultiLocked, VOTE_TIMEOUT);
+ }
+
+
+ public void unlock(Object lockId, Object owner, boolean releaseMultiLocked, long timeout)
+ throws LockNotReleasedException, ChannelException, LockMultiLockedException
+ {
+
+ if (!(lockId instanceof Serializable) || !(owner instanceof Serializable))
+ throw new ClassCastException("DistributedLockManager " +
+ "works only with serializable objects.");
+
+ ReleaseLockDecree releaseLockDecree = new ReleaseLockDecree(lockId, owner, id);
+ boolean released = false;
+ if (releaseMultiLocked) {
+ released = votingAdapter.vote(releaseLockDecree, timeout, this);
+ if (releaseLockDecree.isMultipleLocked()) {
+ throw new LockMultiLockedException("Lock was also locked by other DistributedLockManager(s)");
+ }
+ } else {
+ released = votingAdapter.vote(releaseLockDecree, timeout);
+ }
+
+ if (!released)
+ throw new LockNotReleasedException("Lock cannot be unlocked.");
+ }
+
+
+
+ /**
+ * Checks the list of prepared locks/unlocks to determine if we are in the
+ * middle of the two-phase commit process for the lock acqusition/release.
+ * Here we do not tolerate if the request comes from the same node on behalf
+ * of the same owner.
+ *
+ * @param preparedContainer either preparedLocks
or
+ * preparedReleases
depending on the situation.
+ *
+ * @param requestedDecree instance of LockDecree
representing
+ * the lock.
+ */
+ private static boolean checkPrepared(HashMap preparedContainer,
+ LockDecree requestedDecree)
+ {
+ LockDecree preparedDecree =
+ (LockDecree)preparedContainer.get(requestedDecree.getKey());
+
+ // if prepared lock is not valid, remove it from the list
+ if ((preparedDecree != null) && !preparedDecree.isValid()) {
+ preparedContainer.remove(preparedDecree.getKey());
+
+ preparedDecree = null;
+ }
+
+ return preparedDecree == null || requestedDecree.requester.equals(preparedDecree.requester);
+ }
+
+ /**
+ * Prepare phase for the lock acquisition or release.
+ *
+ * @param decree should be an instance LockDecree
, if not,
+ * we throw VoteException
to be ignored by the
+ * VoteChannel
.
+ *
+ * @return true
when preparing the lock operation succeeds.
+ *
+ * @throws VoteException if we should be ignored during voting.
+ */
+ public synchronized boolean prepare(Object decree) throws VoteException {
+ if (!(decree instanceof LockDecree))
+ throw new VoteException("Uknown decree type. Ignore me.");
+
+ if (decree instanceof AcquireLockDecree) {
+ AcquireLockDecree acquireDecree = (AcquireLockDecree)decree;
+ if(log.isDebugEnabled()) log.debug("Preparing to acquire decree " + acquireDecree.lockId);
+
+ if (!checkPrepared(preparedLocks, acquireDecree))
+ // there is a prepared lock owned by third party
+ return false;
+
+ if (canLock(acquireDecree)) {
+ preparedLocks.put(acquireDecree.getKey(), acquireDecree);
+ return true;
+ } else
+ // we are unable to aquire local lock
+ return false;
+ } else
+ if (decree instanceof ReleaseLockDecree) {
+ ReleaseLockDecree releaseDecree = (ReleaseLockDecree)decree;
+
+
+ if(log.isDebugEnabled()) log.debug("Preparing to release decree " + releaseDecree.lockId);
+
+ if (!checkPrepared(preparedReleases, releaseDecree))
+ // there is a prepared release owned by third party
+ return false;
+
+ if (canRelease(releaseDecree)) {
+ preparedReleases.put(releaseDecree.getKey(), releaseDecree);
+ // we have local lock and the prepared lock
+ return true;
+ } else
+ // we were unable to aquire local lock
+ return false;
+ } else
+ if (decree instanceof MultiLockDecree) {
+ // Here we abuse the voting mechanism for notifying the other lockManagers of multiple locked objects.
+ MultiLockDecree multiLockDecree = (MultiLockDecree)decree;
+
+ if(log.isDebugEnabled()) {
+ log.debug("Marking " + multiLockDecree.getKey() + " as multilocked");
+ }
+
+ LockDecree lockDecree = (LockDecree)heldLocks.get(multiLockDecree.getKey());
+ if (lockDecree != null) {
+ lockDecree.setMultipleLocked(true);
+ }
+ return true;
+ }
+
+ // we should not be here
+ return false;
+ }
+
+ /**
+ * Commit phase for the lock acquisition or release.
+ *
+ * @param decree should be an instance LockDecree
, if not,
+ * we throw VoteException
to be ignored by the
+ * VoteChannel
.
+ *
+ * @return true
when commiting the lock operation succeeds.
+ *
+ * @throws VoteException if we should be ignored during voting.
+ */
+ public synchronized boolean commit(Object decree) throws VoteException {
+ if (!(decree instanceof LockDecree))
+ throw new VoteException("Uknown decree type. Ignore me.");
+
+ if (decree instanceof AcquireLockDecree) {
+
+
+ if(log.isDebugEnabled()) log.debug("Committing decree acquisition " + ((LockDecree)decree).lockId);
+
+ if (!checkPrepared(preparedLocks, (LockDecree)decree))
+ // there is a prepared lock owned by third party
+ return false;
+
+ if (localLock((LockDecree)decree)) {
+ preparedLocks.remove(((LockDecree)decree).getKey());
+ return true;
+ } else
+ return false;
+ } else
+ if (decree instanceof ReleaseLockDecree) {
+
+
+ if(log.isDebugEnabled()) log.debug("Committing decree release " + ((LockDecree)decree).lockId);
+
+ if (!checkPrepared(preparedReleases, (LockDecree)decree))
+ // there is a prepared release owned by third party
+ return false;
+
+ if (localRelease((LockDecree)decree)) {
+ preparedReleases.remove(((LockDecree)decree).getKey());
+ return true;
+ } else
+ return false;
+ } else
+ if (decree instanceof MultiLockDecree) {
+ return true;
+ }
+
+ // we should not be here
+ return false;
+ }
+
+ /**
+ * Abort phase for the lock acquisition or release.
+ *
+ * @param decree should be an instance LockDecree
, if not,
+ * we throw VoteException
to be ignored by the
+ * VoteChannel
.
+ *
+ * @throws VoteException if we should be ignored during voting.
+ */
+ public synchronized void abort(Object decree) throws VoteException {
+ if (!(decree instanceof LockDecree))
+ throw new VoteException("Uknown decree type. Ignore me.");
+
+ if (decree instanceof AcquireLockDecree) {
+
+
+ if(log.isDebugEnabled()) log.debug("Aborting decree acquisition " + ((LockDecree)decree).lockId);
+
+ if (!checkPrepared(preparedLocks, (LockDecree)decree))
+ // there is a prepared lock owned by third party
+ return;
+
+ preparedLocks.remove(((LockDecree)decree).getKey());
+ } else
+ if (decree instanceof ReleaseLockDecree) {
+
+
+ if(log.isDebugEnabled()) log.debug("Aborting decree release " + ((LockDecree)decree).lockId);
+
+ if (!checkPrepared(preparedReleases, (LockDecree)decree))
+ // there is a prepared release owned by third party
+ return;
+
+ preparedReleases.remove(((LockDecree)decree).getKey());
+ }
+
+ }
+
+
+ /**
+ * Processes the response list and votes like the default processResponses method with the consensusType VOTE_ALL
+ * If the result of the voting is false, but this DistributedLockManager owns the lock, the result is changed to
+ * true and the lock is released, but marked as multiple locked. (only in the prepare state to reduce traffic)
+ *
+ * Note: we do not support voting in case of Byzantine failures, i.e.
+ * when the node responds with the fault message.
+ */
+ public boolean processResponses(RspList responses, int consensusType, Object decree) throws ChannelException {
+ if (responses == null) {
+ return false;
+ }
+
+ int totalPositiveVotes = 0;
+ int totalNegativeVotes = 0;
+
+ for (int i = 0; i < responses.size(); i++) {
+ Rsp response = (Rsp) responses.elementAt(i);
+
+ switch (checkResponse(response)) {
+ case PROCESS_SKIP:
+ continue;
+ case PROCESS_BREAK:
+ return false;
+ }
+
+ VoteResult result = (VoteResult) response.getValue();
+
+ totalPositiveVotes += result.getPositiveVotes();
+ totalNegativeVotes += result.getNegativeVotes();
+ }
+
+ boolean voteResult = (totalNegativeVotes == 0 && totalPositiveVotes > 0);
+
+ if (decree instanceof TwoPhaseVotingAdapter.TwoPhaseWrapper) {
+ TwoPhaseVotingAdapter.TwoPhaseWrapper wrappedDecree = (TwoPhaseVotingAdapter.TwoPhaseWrapper)decree;
+ if (wrappedDecree.isPrepare()) {
+ Object unwrappedDecree = wrappedDecree.getDecree();
+ if (unwrappedDecree instanceof ReleaseLockDecree) {
+ ReleaseLockDecree releaseLockDecree = (ReleaseLockDecree)unwrappedDecree;
+ LockDecree lock = null;
+ if ((lock = (LockDecree)heldLocks.get(releaseLockDecree.getKey())) != null) {
+ // If there is a local lock...
+ if (!voteResult) {
+ // ... and another DLM voted negatively, but this DLM owns the lock
+ // we inform the other node, that it's lock is multiple locked
+ if (informLockingNodes(releaseLockDecree)) {
+
+ // we set the local lock to multiple locked
+ lock.setMultipleLocked(true);
+
+ voteResult = true;
+ }
+ }
+ if (lock.isMultipleLocked()) {
+ //... and the local lock is marked as multilocked
+ // we mark the releaseLockDecree als multiple locked for evaluation when unlock returns
+ releaseLockDecree.setMultipleLocked(true);
+ }
+ }
+ }
+ }
+ }
+
+ return voteResult;
+ }
+
+ /**
+ * This method checks the response and says the processResponses() method
+ * what to do.
+ * @return PROCESS_CONTINUE to continue calculating votes,
+ * PROCESS_BREAK to stop calculating votes from the nodes,
+ * PROCESS_SKIP to skip current response.
+ * @throws ChannelException when the response is fatal to the
+ * current voting process.
+ */
+ private int checkResponse(Rsp response) throws ChannelException {
+
+ if (!response.wasReceived()) {
+
+ if (log.isDebugEnabled())
+ log.debug("Response from node " + response.getSender() + " was not received.");
+
+ throw new ChannelException("Node " + response.getSender() + " failed to respond.");
+ }
+
+ if (response.wasSuspected()) {
+
+ if (log.isDebugEnabled())
+ log.debug("Node " + response.getSender() + " was suspected.");
+
+ return PROCESS_SKIP;
+ }
+
+ Object object = response.getValue();
+
+ // we received exception/error, something went wrong
+ // on one of the nodes... and we do not handle such faults
+ if (object instanceof Throwable) {
+ throw new ChannelException("Node " + response.getSender() + " is faulty.");
+ }
+
+ if (object == null) {
+ return PROCESS_SKIP;
+ }
+
+ // it is always interesting to know the class that caused failure...
+ if (!(object instanceof VoteResult)) {
+ String faultClass = object.getClass().getName();
+
+ // ...but we do not handle byzantine faults
+ throw new ChannelException("Node " + response.getSender() + " generated fault (class " + faultClass + ')');
+ }
+
+ // what if we received the response from faulty node?
+ if (object instanceof FailureVoteResult) {
+
+ if (log.isErrorEnabled())
+ log.error(((FailureVoteResult) object).getReason());
+
+ return PROCESS_BREAK;
+ }
+
+ // everything is fine :)
+ return PROCESS_CONTINUE;
+ }
+
+ private boolean informLockingNodes(ReleaseLockDecree releaseLockDecree) throws ChannelException {
+ return votingAdapter.vote(new MultiLockDecree(releaseLockDecree), VOTE_TIMEOUT);
+ }
+
+ /** Remove all locks held by members who left the previous view */
+ public void viewAccepted(View new_view) {
+ Vector prev_view=new Vector(current_members);
+ current_members.clear();
+ current_members.addAll(new_view.getMembers());
+
+ if(log.isDebugEnabled())
+ log.debug("-- VIEW: " + current_members + ", old view: " + prev_view);
+
+ prev_view.removeAll(current_members);
+ if(!prev_view.isEmpty()) { // we have left members, so we need to check for locks which are still held by them
+ for(Iterator it=prev_view.iterator(); it.hasNext();) {
+ Object mbr=it.next();
+ removeLocksHeldBy(preparedLocks, mbr);
+ removeLocksHeldBy(preparedReleases, mbr);
+ removeLocksHeldBy(heldLocks, mbr);
+ }
+ }
+ }
+
+ /** Remove from preparedLocks, preparedReleases and heldLocks */
+ private void removeLocksHeldBy(Map lock_table, Object mbr) {
+ Map.Entry entry;
+ LockDecree val;
+ Object holder;
+ for(Iterator it=lock_table.entrySet().iterator(); it.hasNext();) {
+ entry=(Map.Entry)it.next();
+ val=(LockDecree)entry.getValue();
+ holder=val.requester;
+ if(holder != null && holder.equals(mbr)) {
+ if(log.isTraceEnabled())
+ log.trace("removing a leftover lock held by " + mbr + " for " + entry.getKey() + ": " + val);
+ it.remove();
+ }
+ }
+ }
+
+ public void suspect(Address suspected_mbr) {
+ }
+
+ public void block() {
+ }
+
+ /**
+ * This class represents the lock
+ */
+ public static class LockDecree implements Serializable {
+
+ protected final Object lockId;
+ protected final Object requester;
+ protected final Object managerId;
+
+ protected boolean commited;
+
+ private boolean multipleLocked = false;
+ private static final long serialVersionUID = 7264104838035219212L;
+
+ private LockDecree(Object lockId, Object requester, Object managerId) {
+ this.lockId = lockId;
+ this.requester = requester;
+ this.managerId = managerId;
+ }
+
+ /**
+ * Returns the key that should be used for Map lookup.
+ */
+ public Object getKey() { return lockId; }
+
+ /**
+ * This is a place-holder for future lock expiration code.
+ */
+ public boolean isValid() { return true; }
+
+ public void commit() { this.commited = true; }
+
+ /**
+ * @return Returns the multipleLocked.
+ */
+ public boolean isMultipleLocked() {
+ return multipleLocked;
+ }
+ /**
+ * @param multipleLocked The multipleLocked to set.
+ */
+ public void setMultipleLocked(boolean multipleLocked) {
+ this.multipleLocked = multipleLocked;
+ }
+ /**
+ * This is hashcode from the java.lang.Long class.
+ */
+ public int hashCode() {
+ return lockId.hashCode();
+ }
+
+ public boolean equals(Object other) {
+
+ return other instanceof LockDecree && ((LockDecree)other).lockId.equals(this.lockId);
+ }
+ }
+
+
+ /**
+ * This class represents the lock to be released.
+ */
+ public static class AcquireLockDecree extends LockDecree {
+ private final long creationTime;
+
+ private AcquireLockDecree(Object lockId, Object requester, Object managerId) {
+ super(lockId, requester, managerId);
+ this.creationTime = System.currentTimeMillis();
+ }
+
+ /**
+ * Lock aquire decree is valid for a ACQUIRE_EXPIRATION
+ * time after creation and if the lock is still valid (in the
+ * future locks will be leased for a predefined period of time).
+ */
+ public boolean isValid() {
+ boolean result = super.isValid();
+
+ if (!commited && result)
+ result = ((creationTime + ACQUIRE_EXPIRATION) > System.currentTimeMillis());
+
+ return result;
+ }
+
+ }
+
+ /**
+ * This class represents the lock to be released.
+ */
+ public static class ReleaseLockDecree extends LockDecree {
+ ReleaseLockDecree(Object lockId, Object requester, Object managerId) {
+ super(lockId, requester, managerId);
+ }
+ }
+
+ /**
+ * This class represents the lock that has to be marked as multilocked
+ */
+ public static class MultiLockDecree extends LockDecree {
+ MultiLockDecree(Object lockId, Object requester, Object managerId) {
+ super(lockId, requester, managerId);
+ }
+
+ MultiLockDecree(ReleaseLockDecree releaseLockDecree) {
+ super(releaseLockDecree.lockId, releaseLockDecree.requester, releaseLockDecree.managerId);
+ }
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/DistributedQueue.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/DistributedQueue.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/DistributedQueue.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,732 @@
+// $Id: DistributedQueue.java,v 1.1 2012/08/17 14:51:18 marcin Exp $
+package org.jgroups.blocks;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jgroups.*;
+import org.jgroups.util.RspList;
+import org.jgroups.util.Util;
+
+import java.io.Serializable;
+import java.util.*;
+
+
+/**
+ * Provides the abstraction of a java.util.LinkedList that is replicated at several
+ * locations. Any change to the list (reset, add, remove, etc.) will transparently be
+ * propagated to all replicas in the group. All read-only methods will always access the
+ * local replica.
+ * Both keys and values added to the list must be serializable , the reason
+ * being that they will be sent across the network to all replicas of the group.
+ * An instance of this class will contact an existing member of the group to fetch its
+ * initial state.
+ * Beware to use a total protocol on initialization or elements would not be in same
+ * order on all replicas.
+ * @author Romuald du Song
+ */
+public class DistributedQueue implements MessageListener, MembershipListener, Cloneable
+{
+ public interface Notification
+ {
+ void entryAdd(Object value);
+
+ void entryRemoved(Object key);
+
+ void viewChange(Vector new_mbrs, Vector old_mbrs);
+
+ void contentsCleared();
+
+ void contentsSet(Collection new_entries);
+ }
+
+ protected Log logger = LogFactory.getLog(getClass());
+ private long internal_timeout = 10000; // 10 seconds to wait for a response
+
+ /*lock object for synchronization*/
+ protected final Object mutex = new Object();
+ protected boolean stopped = false; // whether to we are stopped !
+ protected LinkedList internalQueue;
+ protected Channel channel;
+ protected RpcDispatcher disp = null;
+ protected String groupname = null;
+ protected Vector notifs = new Vector(); // to be notified when mbrship changes
+ protected Vector members = new Vector(); // keeps track of all DHTs
+ private Class[] add_signature = null;
+ private Class[] addAtHead_signature = null;
+ private Class[] addAll_signature = null;
+ private Class[] reset_signature = null;
+ private Class[] remove_signature = null;
+
+ /**
+ * Creates a DistributedQueue
+ * @param groupname The name of the group to join
+ * @param factory The ChannelFactory which will be used to create a channel
+ * @param properties The property string to be used to define the channel
+ * @param state_timeout The time to wait until state is retrieved in milliseconds. A value of 0 means wait forever.
+ */
+ public DistributedQueue(String groupname, ChannelFactory factory, String properties, long state_timeout)
+ throws ChannelException
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("DistributedQueue(" + groupname + ',' + properties + ',' + state_timeout);
+ }
+
+ this.groupname = groupname;
+ initSignatures();
+ internalQueue = new LinkedList();
+ channel = (factory != null) ? factory.createChannel((Object)properties) : new JChannel(properties);
+ disp = new RpcDispatcher(channel, this, this, this);
+ disp.setDeadlockDetection(false); // To ensure strict FIFO MethodCall
+ channel.connect(groupname);
+ start(state_timeout);
+ }
+
+ public DistributedQueue(JChannel channel)
+ {
+ this.groupname = channel.getClusterName();
+ this.channel = channel;
+ init();
+ }
+
+ /**
+ * Uses a user-provided PullPushAdapter to create the dispatcher rather than a Channel. If id is non-null, it will be
+ * used to register under that id. This is typically used when another building block is already using
+ * PullPushAdapter, and we want to add this building block in addition. The id is the used to discriminate
+ * between messages for the various blocks on top of PullPushAdapter. If null, we will assume we are the
+ * first block created on PullPushAdapter.
+ * The caller needs to call start(), before using the this block. It gives the opportunity for the caller
+ * to register as a lessoner for Notifications events.
+ * @param adapter The PullPushAdapter which to use as underlying transport
+ * @param id A serializable object (e.g. an Integer) used to discriminate (multiplex/demultiplex) between
+ * requests/responses for different building blocks on top of PullPushAdapter.
+ */
+ public DistributedQueue(PullPushAdapter adapter, Serializable id)
+ {
+ this.channel = (Channel)adapter.getTransport();
+ this.groupname = this.channel.getClusterName();
+
+ initSignatures();
+ internalQueue = new LinkedList();
+
+ disp = new RpcDispatcher(adapter, id, this, this, this);
+ disp.setDeadlockDetection(false); // To ensure strict FIFO MethodCall
+ }
+
+ protected final void init()
+ {
+ initSignatures();
+ internalQueue = new LinkedList();
+ disp = new RpcDispatcher(channel, this, this, this);
+ disp.setDeadlockDetection(false); // To ensure strict FIFO MethodCall
+ }
+
+ public final void start(long state_timeout) throws ChannelClosedException, ChannelNotConnectedException
+ {
+ boolean rc;
+ logger.debug("DistributedQueue.initState(" + groupname + "): starting state retrieval");
+
+ rc = channel.getState(null, state_timeout);
+
+ if (rc)
+ {
+ logger.info("DistributedQueue.initState(" + groupname + "): state was retrieved successfully");
+ }
+ else
+ {
+ logger.info("DistributedQueue.initState(" + groupname + "): state could not be retrieved (first member)");
+ }
+ }
+
+ public Address getLocalAddress()
+ {
+ return (channel != null) ? channel.getLocalAddress() : null;
+ }
+
+ public Channel getChannel()
+ {
+ return channel;
+ }
+
+ public void addNotifier(Notification n)
+ {
+ if (n != null && !notifs.contains(n))
+ {
+ notifs.addElement(n);
+ }
+ }
+
+ public void removeNotifier(Notification n)
+ {
+ notifs.removeElement(n);
+ }
+
+ public void stop()
+ {
+ /*lock the queue from other threads*/
+ synchronized (mutex)
+ {
+ internalQueue.clear();
+
+ if (disp != null)
+ {
+ disp.stop();
+ disp = null;
+ }
+
+ if (channel != null)
+ {
+ channel.close();
+ channel = null;
+ }
+
+ stopped = true;
+ }
+ }
+
+ /**
+ * Add the speficied element at the bottom of the queue
+ * @param value
+ */
+ public void add(Object value)
+ {
+ try
+ {
+ Object retval = null;
+
+ RspList rsp = disp.callRemoteMethods(null, "_add", new Object[]{value}, add_signature, GroupRequest.GET_ALL, 0);
+ Vector results = rsp.getResults();
+
+ if (results.size() > 0)
+ {
+ retval = results.elementAt(0);
+
+ if (logger.isDebugEnabled())
+ {
+ checkResult(rsp, retval);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ logger.error("Unable to add value " + value, e);
+ }
+
+ }
+
+ /**
+ * Add the speficied element at the top of the queue
+ * @param value
+ */
+ public void addAtHead(Object value)
+ {
+ try
+ {
+ disp.callRemoteMethods(null, "_addAtHead", new Object[]{value}, addAtHead_signature, GroupRequest.GET_ALL, 0);
+ }
+ catch (Exception e)
+ {
+ logger.error("Unable to addAtHead value " + value, e);
+ }
+
+ }
+
+ /**
+ * Add the speficied collection to the top of the queue.
+ * Elements are added in the order that they are returned by the specified
+ * collection's iterator.
+ * @param values
+ */
+ public void addAll(Collection values)
+ {
+ try
+ {
+ disp.callRemoteMethods(null, "_addAll", new Object[]{values}, addAll_signature, GroupRequest.GET_ALL, 0);
+ }
+ catch (Exception e)
+ {
+ logger.error("Unable to addAll value: " + values, e);
+ }
+
+ }
+
+ public Vector getContents()
+ {
+ Vector result = new Vector();
+
+ for (Iterator e = internalQueue.iterator(); e.hasNext();)
+ result.add(e.next());
+
+ return result;
+ }
+
+ public int size()
+ {
+ return internalQueue.size();
+ }
+
+ /**
+ * returns the first object on the queue, without removing it.
+ * If the queue is empty this object blocks until the first queue object has
+ * been added
+ * @return the first object on the queue
+ */
+ public Object peek()
+ {
+ Object retval = null;
+
+ try
+ {
+ retval = internalQueue.getFirst();
+ }
+ catch (NoSuchElementException e)
+ {
+ }
+
+ return retval;
+ }
+
+ public void reset()
+ {
+ try
+ {
+ disp.callRemoteMethods(null, "_reset", null, reset_signature, GroupRequest.GET_ALL, 0);
+ }
+ catch (Exception e)
+ {
+ logger.error("DistributedQueue.reset(" + groupname + ')', e);
+ }
+ }
+
+ protected void checkResult(RspList rsp, Object retval)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Value updated from " + groupname + " :" + retval);
+ }
+
+ Vector results = rsp.getResults();
+
+ for (int i = 0; i < results.size(); i++)
+ {
+ Object data = results.elementAt(i);
+
+ if (!data.equals(retval))
+ {
+ logger.error("Reference value differs from returned value " + retval + " != " + data);
+ }
+ }
+ }
+
+ /**
+ * Try to return the first objet in the queue.It does not wait for an object.
+ * @return the first object in the queue or null if none were found.
+ */
+ public Object remove()
+ {
+ Object retval = null;
+ RspList rsp = disp.callRemoteMethods(null, "_remove", null, remove_signature, GroupRequest.GET_ALL, internal_timeout);
+ Vector results = rsp.getResults();
+
+ if (results.size() > 0)
+ {
+ retval = results.elementAt(0);
+
+ if (logger.isDebugEnabled())
+ {
+ checkResult(rsp, retval);
+ }
+ }
+
+ return retval;
+ }
+
+ /**
+ * @param timeout The time to wait until an entry is retrieved in milliseconds. A value of 0 means wait forever.
+ * @return the first object in the queue or null if none were found
+ */
+ public Object remove(long timeout)
+ {
+ Object retval = null;
+ long start = System.currentTimeMillis();
+
+ if (timeout <= 0)
+ {
+ while (!stopped && (retval == null))
+ {
+ RspList rsp = disp.callRemoteMethods(null, "_remove", null, remove_signature, GroupRequest.GET_ALL, internal_timeout);
+ Vector results = rsp.getResults();
+
+ if (results.size() > 0)
+ {
+ retval = results.elementAt(0);
+
+ if (logger.isDebugEnabled())
+ {
+ checkResult(rsp, retval);
+ }
+ }
+
+ if (retval == null)
+ {
+ try
+ {
+ synchronized (mutex)
+ {
+ mutex.wait();
+ }
+ }
+ catch (InterruptedException e)
+ {
+ }
+ }
+ }
+ }
+ else
+ {
+ while (((System.currentTimeMillis() - start) < timeout) && !stopped && (retval == null))
+ {
+ RspList rsp = disp.callRemoteMethods(null, "_remove", null, remove_signature, GroupRequest.GET_ALL, internal_timeout);
+ Vector results = rsp.getResults();
+
+ if (results.size() > 0)
+ {
+ retval = results.elementAt(0);
+
+ if (logger.isDebugEnabled())
+ {
+ checkResult(rsp, retval);
+ }
+ }
+
+ if (retval == null)
+ {
+ try
+ {
+ long delay = timeout - (System.currentTimeMillis() - start);
+
+ synchronized (mutex)
+ {
+ if (delay > 0)
+ {
+ mutex.wait(delay);
+ }
+ }
+ }
+ catch (InterruptedException e)
+ {
+ }
+ }
+ }
+ }
+
+ return retval;
+ }
+
+ public String toString()
+ {
+ return internalQueue.toString();
+ }
+
+ /*------------------------ Callbacks -----------------------*/
+ public void _add(Object value)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(groupname + '@' + getLocalAddress() + " _add(" + value + ')');
+ }
+
+ /*lock the queue from other threads*/
+ synchronized (mutex)
+ {
+ internalQueue.add(value);
+
+ /*wake up all the threads that are waiting for the lock to be released*/
+ mutex.notifyAll();
+ }
+
+ for (int i = 0; i < notifs.size(); i++)
+ ((Notification)notifs.elementAt(i)).entryAdd(value);
+ }
+
+ public void _addAtHead(Object value)
+ {
+ /*lock the queue from other threads*/
+ synchronized (mutex)
+ {
+ internalQueue.addFirst(value);
+
+ /*wake up all the threads that are waiting for the lock to be released*/
+ mutex.notifyAll();
+ }
+
+ for (int i = 0; i < notifs.size(); i++)
+ ((Notification)notifs.elementAt(i)).entryAdd(value);
+ }
+
+ public void _reset()
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(groupname + '@' + getLocalAddress() + " _reset()");
+ }
+
+ _private_reset();
+
+ for (int i = 0; i < notifs.size(); i++)
+ ((Notification)notifs.elementAt(i)).contentsCleared();
+ }
+
+ protected void _private_reset()
+ {
+ /*lock the queue from other threads*/
+ synchronized (mutex)
+ {
+ internalQueue.clear();
+
+ /*wake up all the threads that are waiting for the lock to be released*/
+ mutex.notifyAll();
+ }
+ }
+
+ public Object _remove()
+ {
+ Object retval = null;
+
+ try
+ {
+ /*lock the queue from other threads*/
+ synchronized (mutex)
+ {
+ retval = internalQueue.removeFirst();
+
+ /*wake up all the threads that are waiting for the lock to be released*/
+ mutex.notifyAll();
+ }
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(groupname + '@' + getLocalAddress() + "_remove(" + retval + ')');
+ }
+
+ for (int i = 0; i < notifs.size(); i++)
+ ((Notification)notifs.elementAt(i)).entryRemoved(retval);
+ }
+ catch (NoSuchElementException e)
+ {
+ logger.debug(groupname + '@' + getLocalAddress() + "_remove(): nothing to remove");
+ }
+
+ return retval;
+ }
+
+ public void _addAll(Collection c)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(groupname + '@' + getLocalAddress() + " _addAll(" + c + ')');
+ }
+
+ /*lock the queue from other threads*/
+ synchronized (mutex)
+ {
+ internalQueue.addAll(c);
+
+ /*wake up all the threads that are waiting for the lock to be released*/
+ mutex.notifyAll();
+ }
+
+ for (int i = 0; i < notifs.size(); i++)
+ ((Notification)notifs.elementAt(i)).contentsSet(c);
+ }
+
+ /*----------------------------------------------------------*/
+ /*-------------------- State Exchange ----------------------*/
+ public void receive(Message msg)
+ {
+ }
+
+ public byte[] getState()
+ {
+ Vector copy = (Vector)getContents().clone();
+
+ try
+ {
+ return Util.objectToByteBuffer(copy);
+ }
+ catch (Throwable ex)
+ {
+ logger.error("DistributedQueue.getState(): exception marshalling state.", ex);
+
+ return null;
+ }
+ }
+
+ public void setState(byte[] new_state)
+ {
+ Vector new_copy;
+
+ try
+ {
+ new_copy = (Vector)Util.objectFromByteBuffer(new_state);
+
+ if (new_copy == null)
+ {
+ return;
+ }
+ }
+ catch (Throwable ex)
+ {
+ logger.error("DistributedQueue.setState(): exception unmarshalling state.", ex);
+
+ return;
+ }
+
+ _private_reset(); // remove all elements
+ _addAll(new_copy);
+ }
+
+ /*------------------- Membership Changes ----------------------*/
+ public void viewAccepted(View new_view)
+ {
+ Vector new_mbrs = new_view.getMembers();
+
+ if (new_mbrs != null)
+ {
+ sendViewChangeNotifications(new_mbrs, members); // notifies observers (joined, left)
+ members.removeAllElements();
+
+ for (int i = 0; i < new_mbrs.size(); i++)
+ members.addElement(new_mbrs.elementAt(i));
+ }
+ }
+
+ /** Called when a member is suspected */
+ public void suspect(Address suspected_mbr)
+ {
+ ;
+ }
+
+ /** Block sending and receiving of messages until ViewAccepted is called */
+ public void block()
+ {
+ }
+
+ void sendViewChangeNotifications(Vector new_mbrs, Vector old_mbrs)
+ {
+ Vector joined;
+ Vector left;
+ Object mbr;
+ Notification n;
+
+ if ((notifs.size() == 0) || (old_mbrs == null) || (new_mbrs == null) || (old_mbrs.size() == 0) ||
+ (new_mbrs.size() == 0))
+ {
+ return;
+ }
+
+ // 1. Compute set of members that joined: all that are in new_mbrs, but not in old_mbrs
+ joined = new Vector();
+
+ for (int i = 0; i < new_mbrs.size(); i++)
+ {
+ mbr = new_mbrs.elementAt(i);
+
+ if (!old_mbrs.contains(mbr))
+ {
+ joined.addElement(mbr);
+ }
+ }
+
+ // 2. Compute set of members that left: all that were in old_mbrs, but not in new_mbrs
+ left = new Vector();
+
+ for (int i = 0; i < old_mbrs.size(); i++)
+ {
+ mbr = old_mbrs.elementAt(i);
+
+ if (!new_mbrs.contains(mbr))
+ {
+ left.addElement(mbr);
+ }
+ }
+
+ for (int i = 0; i < notifs.size(); i++)
+ {
+ n = (Notification)notifs.elementAt(i);
+ n.viewChange(joined, left);
+ }
+ }
+
+ final void initSignatures()
+ {
+ try
+ {
+ if (add_signature == null)
+ {
+ add_signature = new Class[] { Object.class };
+ }
+
+ if (addAtHead_signature == null)
+ {
+ addAtHead_signature = new Class[] { Object.class };
+ }
+
+ if (addAll_signature == null)
+ {
+ addAll_signature = new Class[] { Collection.class };
+ }
+
+ if (reset_signature == null)
+ {
+ reset_signature = new Class[0];
+ }
+
+ if (remove_signature == null)
+ {
+ remove_signature = new Class[0];
+ }
+ }
+ catch (Throwable ex)
+ {
+ logger.error("DistributedQueue.initMethods()", ex);
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ try
+ {
+ // The setup here is kind of weird:
+ // 1. Create a channel
+ // 2. Create a DistributedQueue (on the channel)
+ // 3. Connect the channel (so the HT gets a VIEW_CHANGE)
+ // 4. Start the HT
+ //
+ // A simpler setup is
+ // DistributedQueue ht = new DistributedQueue("demo", null,
+ // "file://c:/JGroups-2.0/conf/total-token.xml", 5000);
+ JChannel c = new JChannel("file:/c:/JGroups-2.0/conf/conf/total-token.xml");
+
+ DistributedQueue ht = new DistributedQueue(c);
+ c.connect("demo");
+ ht.start(5000);
+
+ ht.add("name");
+ ht.add("Michelle Ban");
+
+ Object old_key = ht.remove();
+ System.out.println("old key was " + old_key);
+ old_key = ht.remove();
+ System.out.println("old value was " + old_key);
+
+ ht.add("name 'Michelle Ban'");
+
+ System.out.println("queue is " + ht);
+ }
+ catch (Throwable t)
+ {
+ t.printStackTrace();
+ }
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/DistributedTree.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/DistributedTree.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/DistributedTree.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,747 @@
+// $Id: DistributedTree.java,v 1.1 2012/08/17 14:51:18 marcin Exp $
+
+package org.jgroups.blocks;
+
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jgroups.*;
+import org.jgroups.util.Util;
+
+import java.io.Serializable;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+
+
+
+/**
+ * A tree-like structure that is replicated across several members. Updates will be multicast to all group
+ * members reliably and in the same order.
+ * @author Bela Ban
+ * @author Alfonso Olias-Sanz
+ */
+public class DistributedTree implements MessageListener, MembershipListener {
+ private Node root=null;
+ final Vector listeners=new Vector();
+ final Vector view_listeners=new Vector();
+ final Vector members=new Vector();
+ protected Channel channel=null;
+ protected RpcDispatcher disp=null;
+ // rc is global and protected so that extensions can detect when
+ // state has been transferred
+ protected boolean rc = false;
+ String groupname="DistributedTreeGroup";
+ String channel_properties="udp.xml";
+ static final long state_timeout=5000; // wait 5 secs max to obtain state
+
+ /** Determines when the updates have to be sent across the network, avoids sending unnecessary
+ * messages when there are no member in the group */
+
+ // Make this protected so that extensions
+ // can control whether or not to send
+ protected boolean send_message = false;
+
+ protected static final Log log=LogFactory.getLog(DistributedTree.class);
+
+
+
+ public interface DistributedTreeListener {
+ void nodeAdded(String fqn, Serializable element);
+
+ void nodeRemoved(String fqn);
+
+ void nodeModified(String fqn, Serializable old_element, Serializable new_element);
+ }
+
+
+ public interface ViewListener {
+ void viewChange(Vector new_mbrs, Vector old_mbrs);
+ }
+
+
+ public DistributedTree() {
+ }
+
+
+ public DistributedTree(String groupname, String channel_properties) {
+ this.groupname=groupname;
+ if(channel_properties != null)
+ this.channel_properties=channel_properties;
+ }
+
+ /*
+ * Uses a user-provided PullPushAdapter to create the dispatcher rather than a Channel. If id is non-null, it will be
+ * used to register under that id. This is typically used when another building block is already using
+ * PullPushAdapter, and we want to add this building block in addition. The id is the used to discriminate
+ * between messages for the various blocks on top of PullPushAdapter. If null, we will assume we are the
+ * first block created on PullPushAdapter.
+ * @param adapter The PullPushAdapter which to use as underlying transport
+ * @param id A serializable object (e.g. an Integer) used to discriminate (multiplex/demultiplex) between
+ * requests/responses for different building blocks on top of PullPushAdapter.
+ * @param state_timeout Max number of milliseconds to wait until state is
+ * retrieved
+ */
+ public DistributedTree(PullPushAdapter adapter, Serializable id, long state_timeout)
+ throws ChannelException {
+ channel = (Channel)adapter.getTransport();
+ disp=new RpcDispatcher(adapter, id, this, this, this);
+ boolean flag = channel.getState(null, state_timeout);
+ if(flag) {
+ if(log.isInfoEnabled()) log.info("state was retrieved successfully");
+ }
+ else
+ if(log.isInfoEnabled()) log.info("state could not be retrieved (must be first member in group)");
+ }
+
+ public Object getLocalAddress() {
+ return channel != null? channel.getLocalAddress() : null;
+ }
+
+ public void setDeadlockDetection(boolean flag) {
+ if(disp != null)
+ disp.setDeadlockDetection(flag);
+ }
+
+ public void start() throws Exception {
+ start(8000);
+ }
+
+
+ public void start(long timeout) throws Exception {
+ if(channel != null) // already started
+ return;
+ channel=new JChannel(channel_properties);
+ disp=new RpcDispatcher(channel, this, this, this);
+ channel.connect(groupname);
+ rc=channel.getState(null, timeout);
+ if(rc) {
+ if(log.isInfoEnabled()) log.info("state was retrieved successfully");
+ }
+ else
+ if(log.isInfoEnabled()) log.info("state could not be retrieved (must be first member in group)");
+ }
+
+
+ public void stop() {
+ if(channel != null) {
+ channel.close();
+ disp.stop();
+ }
+ channel=null;
+ disp=null;
+ }
+
+
+ public void addDistributedTreeListener(DistributedTreeListener listener) {
+ if(!listeners.contains(listener))
+ listeners.addElement(listener);
+ }
+
+
+ public void removeDistributedTreeListener(DistributedTreeListener listener) {
+ listeners.removeElement(listener);
+ }
+
+
+ public void addViewListener(ViewListener listener) {
+ if(!view_listeners.contains(listener))
+ view_listeners.addElement(listener);
+ }
+
+
+ public void removeViewListener(ViewListener listener) {
+ view_listeners.removeElement(listener);
+ }
+
+
+ public void add(String fqn) {
+ //Changes done by
+ //if true, propagate action to the group
+ if(send_message == true) {
+ try {
+ MethodCall call = new MethodCall("_add", new Object[] {fqn}, new String[] {String.class.getName()});
+ disp.callRemoteMethods(null, call, GroupRequest.GET_ALL, 0);
+ }
+ catch(Exception ex) {
+ if(log.isErrorEnabled()) log.error("exception=" + ex);
+ }
+ }
+ else {
+ _add(fqn);
+ }
+ }
+
+ public void add(String fqn, Serializable element) {
+ add(fqn, element, 0);
+ }
+
+ /** resets an existing node, useful after a merge when you want to tell other
+ * members of your state, but do not wish to remove and then add as two separate calls */
+ public void reset(String fqn, Serializable element)
+ {
+ reset(fqn, element, 0);
+ }
+
+ public void remove(String fqn) {
+ remove(fqn, 0);
+ }
+
+ public void add(String fqn, Serializable element, int timeout) {
+ //Changes done by
+ //if true, propagate action to the group
+ if(send_message == true) {
+ try {
+ MethodCall call = new MethodCall("_add", new Object[] {fqn, element},
+ new String[] {String.class.getName(), Serializable.class.getName()});
+ disp.callRemoteMethods(null, call, GroupRequest.GET_ALL, timeout);
+ }
+ catch(Exception ex) {
+ if(log.isErrorEnabled()) log.error("exception=" + ex);
+ }
+ }
+ else {
+ _add(fqn, element);
+ }
+ }
+
+ /** resets an existing node, useful after a merge when you want to tell other
+ * members of your state, but do not wish to remove and then add as two separate calls */
+ public void reset(String fqn, Serializable element, int timeout)
+ {
+ //Changes done by
+ //if true, propagate action to the group
+ if(send_message == true) {
+ try {
+ MethodCall call = new MethodCall("_reset", new Object[] {fqn, element},
+ new String[] {String.class.getName(), Serializable.class.getName()});
+ disp.callRemoteMethods(null, call, GroupRequest.GET_ALL, timeout);
+ }
+ catch(Exception ex) {
+ if(log.isErrorEnabled()) log.error("exception=" + ex);
+ }
+ }
+ else {
+ _add(fqn, element);
+ }
+ }
+
+ public void remove(String fqn, int timeout) {
+ //Changes done by
+ //if true, propagate action to the group
+ if(send_message == true) {
+ try {
+ MethodCall call = new MethodCall("_remove", new Object[] {fqn}, new String[] {String.class.getName()});
+ disp.callRemoteMethods(null, call, GroupRequest.GET_ALL, timeout);
+ }
+ catch(Exception ex) {
+ if(log.isErrorEnabled()) log.error("exception=" + ex);
+ }
+ }
+ else {
+ _remove(fqn);
+ }
+ }
+
+
+ public boolean exists(String fqn) {
+ return fqn != null && (findNode(fqn) != null);
+ }
+
+
+ public Serializable get(String fqn) {
+ Node n=null;
+
+ if(fqn == null) return null;
+ n=findNode(fqn);
+ if(n != null) {
+ return n.element;
+ }
+ return null;
+ }
+
+
+ public void set(String fqn, Serializable element) {
+ set(fqn, element, 0);
+ }
+
+ public void set(String fqn, Serializable element, int timeout) {
+ //Changes done by
+ //if true, propagate action to the group
+ if(send_message == true) {
+ try {
+ MethodCall call = new MethodCall("_set", new Object[] {fqn, element},
+ new String[] {String.class.getName(), Serializable.class.getName()});
+ disp.callRemoteMethods(null, call, GroupRequest.GET_ALL, timeout);
+ }
+ catch(Exception ex) {
+ if(log.isErrorEnabled()) log.error("exception=" + ex);
+ }
+ }
+ else {
+ _set(fqn, element);
+ }
+ }
+
+
+ /** Returns all children of a Node as strings */
+ public Vector getChildrenNames(String fqn) {
+ Vector ret=new Vector();
+ Node n;
+
+ if(fqn == null) return ret;
+ n=findNode(fqn);
+ if(n == null || n.children == null) return ret;
+ for(int i=0; i < n.children.size(); i++)
+ ret.addElement(((Node)n.children.elementAt(i)).name);
+ return ret;
+ }
+
+
+ public String print() {
+ StringBuilder sb=new StringBuilder();
+ int indent=0;
+
+ if(root == null)
+ return "/";
+
+ sb.append(root.print(indent));
+ return sb.toString();
+ }
+
+
+ /** Returns all children of a Node as Nodes */
+ Vector getChildren(String fqn) {
+ Node n;
+
+ if(fqn == null) return null;
+ n=findNode(fqn);
+ if(n == null) return null;
+ return n.children;
+ }
+
+ /**
+ * Returns the name of the group that the DistributedTree is connected to
+ * @return String
+ */
+ public String getGroupName() {return groupname;}
+
+ /**
+ * Returns the Channel the DistributedTree is connected to
+ * @return Channel
+ */
+ public Channel getChannel() {return channel;}
+
+ /**
+ * Returns the number of current members joined to the group
+ * @return int
+ */
+ public int getGroupMembersNumber() {return members.size();}
+
+
+
+
+ /*--------------------- Callbacks --------------------------*/
+
+ public void _add(String fqn) {
+ _add(fqn, null);
+ }
+
+
+ public void _add(String fqn, Serializable element) {
+ Node curr, n;
+ StringTokenizer tok;
+ String child_name;
+ String tmp_fqn="";
+
+ if(root == null) {
+ root=new Node("/", null);
+ notifyNodeAdded("/", null);
+ }
+ if(fqn == null)
+ return;
+ curr=root;
+ tok=new StringTokenizer(fqn, "/");
+
+ while(tok.hasMoreTokens()) {
+ child_name=tok.nextToken();
+ tmp_fqn=tmp_fqn + '/' + child_name;
+ n=curr.findChild(child_name);
+ if(n == null) {
+ n=new Node(child_name, null);
+ curr.addChild(n);
+ if(!tok.hasMoreTokens()) {
+ n.element=element;
+ notifyNodeAdded(tmp_fqn, element);
+ return;
+ }
+ else
+ notifyNodeAdded(tmp_fqn, null);
+ }
+ curr=n;
+ }
+ // If the element is not null, we install it and notify the
+ // listener app that the node is modified.
+ if(element != null){
+ curr.element=element;
+ notifyNodeModified(fqn, null, element);
+ }
+ }
+
+
+ public void _remove(String fqn) {
+ Node curr, n;
+ StringTokenizer tok;
+ String child_name=null;
+
+ if(fqn == null || root == null)
+ return;
+ curr=root;
+ tok=new StringTokenizer(fqn, "/");
+
+ while(tok.countTokens() > 1) {
+ child_name=tok.nextToken();
+ n=curr.findChild(child_name);
+ if(n == null) // node does not exist
+ return;
+ curr=n;
+ }
+ try {
+ child_name=tok.nextToken();
+ if(child_name != null) {
+ n=curr.removeChild(child_name);
+ if(n != null)
+ notifyNodeRemoved(fqn);
+ }
+ }
+ catch(Exception ex) {
+ }
+ }
+
+
+ public void _set(String fqn, Serializable element) {
+ Node n;
+ Serializable old_el=null;
+
+ if(fqn == null || element == null) return;
+ n=findNode(fqn);
+ if(n == null) {
+ if(log.isErrorEnabled()) log.error("node " + fqn + " not found");
+ return;
+ }
+ old_el=n.element;
+ n.element=element;
+ notifyNodeModified(fqn, old_el, element);
+ }
+
+ /** similar to set, but does not error if node does not exist, but rather does an add instead */
+ public void _reset(String fqn, Serializable element) {
+ Node n;
+ Serializable old_el=null;
+
+ if(fqn == null || element == null) return;
+ n=findNode(fqn);
+ if(n == null) {
+ _add(fqn, element);
+ }
+ else {
+ old_el=n.element;
+ n.element=element;
+ }
+ notifyNodeModified(fqn, old_el, element);
+ }
+
+ /*----------------- End of Callbacks ----------------------*/
+
+
+
+
+
+
+ /*-------------------- State Exchange ----------------------*/
+
+ public void receive(Message msg) {
+ }
+
+ /** Return a copy of the tree */
+ public byte[] getState() {
+ Object copy=root != null? root.copy() : null;
+ try {
+ return Util.objectToByteBuffer(copy);
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) log.error("exception marshalling state: " + ex);
+ return null;
+ }
+ }
+
+ public void setState(byte[] data) {
+ Object new_state;
+
+ try {
+ new_state=Util.objectFromByteBuffer(data);
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) log.error("exception unmarshalling state: " + ex);
+ return;
+ }
+ if(new_state == null) return;
+ if(!(new_state instanceof Node)) {
+ if(log.isErrorEnabled()) log.error("object is not of type 'Node'");
+ return;
+ }
+ root=((Node)new_state).copy();
+
+ // State transfer needs to notify listeners in the new
+ // cluster member about everything that exists. This
+ // is working ok now.
+ this.notifyAllNodesCreated(root, "");
+ }
+
+
+
+ /*------------------- Membership Changes ----------------------*/
+
+ public void viewAccepted(View new_view) {
+ Vector new_mbrs=new_view.getMembers();
+
+ if(new_mbrs != null) {
+ sendViewChangeNotifications(new_mbrs, members); // notifies observers (joined, left)
+ members.removeAllElements();
+ for(int i=0; i < new_mbrs.size(); i++)
+ members.addElement(new_mbrs.elementAt(i));
+ }
+ //if size is bigger than one, there are more peers in the group
+ //otherwise there is only one server.
+ send_message=true;
+ send_message=members.size() > 1;
+ }
+
+
+ /** Called when a member is suspected */
+ public void suspect(Address suspected_mbr) {
+ }
+
+
+ /** Block sending and receiving of messages until ViewAccepted is called */
+ public void block() {
+ }
+
+
+ void sendViewChangeNotifications(Vector new_mbrs, Vector old_mbrs) {
+ Vector joined, left;
+ Object mbr;
+
+ if(view_listeners.isEmpty() || old_mbrs == null || new_mbrs == null)
+ return;
+
+
+ // 1. Compute set of members that joined: all that are in new_mbrs, but not in old_mbrs
+ joined=new Vector();
+ for(int i=0; i < new_mbrs.size(); i++) {
+ mbr=new_mbrs.elementAt(i);
+ if(!old_mbrs.contains(mbr))
+ joined.addElement(mbr);
+ }
+
+
+ // 2. Compute set of members that left: all that were in old_mbrs, but not in new_mbrs
+ left=new Vector();
+ for(int i=0; i < old_mbrs.size(); i++) {
+ mbr=old_mbrs.elementAt(i);
+ if(!new_mbrs.contains(mbr))
+ left.addElement(mbr);
+ }
+ notifyViewChange(joined, left);
+ }
+
+
+ private Node findNode(String fqn) {
+ Node curr=root;
+ StringTokenizer tok;
+ String child_name;
+
+ if(fqn == null || root == null) return null;
+ if("/".equals(fqn) || "".equals(fqn))
+ return root;
+
+ tok=new StringTokenizer(fqn, "/");
+ while(tok.hasMoreTokens()) {
+ child_name=tok.nextToken();
+ curr=curr.findChild(child_name);
+ if(curr == null) return null;
+ }
+ return curr;
+ }
+
+
+ void notifyNodeAdded(String fqn, Serializable element) {
+ for(int i=0; i < listeners.size(); i++)
+ ((DistributedTreeListener)listeners.elementAt(i)).nodeAdded(fqn, element);
+ }
+
+ void notifyNodeRemoved(String fqn) {
+ for(int i=0; i < listeners.size(); i++)
+ ((DistributedTreeListener)listeners.elementAt(i)).nodeRemoved(fqn);
+ }
+
+ void notifyNodeModified(String fqn, Serializable old_element, Serializable new_element) {
+ for(int i=0; i < listeners.size(); i++)
+ ((DistributedTreeListener)listeners.elementAt(i)).nodeModified(fqn, old_element, new_element);
+ }
+
+ /** Generates NodeAdded notifications for all nodes of the tree. This is called whenever the tree is
+ initially retrieved (state transfer) */
+ void notifyAllNodesCreated(Node curr, String tmp_fqn) {
+ Node n;
+ // We need a local string here to handle the empty string (root)
+ // otherwise, we start off with two slashes in the path.
+ String path = "";
+ if(curr == null) return;
+ if(curr.name == null) {
+ if(log.isErrorEnabled()) log.error("curr.name is null");
+ return;
+ }
+ // If we're the root node, then we supply a "starter" slash.
+ // This lets us properly initiate the recursion with an empty
+ // string, and then prepend a slash for each additional depth
+ path = (curr.equals(root)) ? "/" : tmp_fqn;
+
+ // Recursion must occur _before_ we look for children, or we
+ // never notifyNodeAdded() for leaf nodes.
+ notifyNodeAdded(path, curr.element);
+ if(curr.children != null) {
+ for(int i=0; i < curr.children.size(); i++) {
+ n=(Node)curr.children.elementAt(i);
+ notifyAllNodesCreated(n, tmp_fqn + '/' + n.name);
+ }
+ }
+ }
+
+
+ void notifyViewChange(Vector new_mbrs, Vector old_mbrs) {
+ for(int i=0; i < view_listeners.size(); i++)
+ ((ViewListener)view_listeners.elementAt(i)).viewChange(new_mbrs, old_mbrs);
+ }
+
+
+ private static class Node implements Serializable {
+ String name=null;
+ Vector children=null;
+ Serializable element=null;
+ private static final long serialVersionUID=-635336369135391033L;
+
+
+ Node() {
+ }
+
+ Node(String name, Serializable element) {
+ this.name=name;
+ this.element=element;
+ }
+
+
+ void addChild(String relative_name, Serializable element) {
+ if(relative_name == null)
+ return;
+ if(children == null)
+ children=new Vector();
+ else {
+ if(!children.contains(relative_name))
+ children.addElement(new Node(relative_name, element));
+ }
+ }
+
+
+ void addChild(Node n) {
+ if(n == null) return;
+ if(children == null)
+ children=new Vector();
+ if(!children.contains(n))
+ children.addElement(n);
+ }
+
+
+ Node removeChild(String rel_name) {
+ Node n=findChild(rel_name);
+
+ if(n != null)
+ children.removeElement(n);
+ return n;
+ }
+
+
+ Node findChild(String relative_name) {
+ Node child;
+
+ if(children == null || relative_name == null)
+ return null;
+ for(int i=0; i < children.size(); i++) {
+ child=(Node)children.elementAt(i);
+ if(child.name == null) {
+ if(log.isErrorEnabled()) log.error("child.name is null for " + relative_name);
+ continue;
+ }
+
+ if(child.name.equals(relative_name))
+ return child;
+ }
+
+ return null;
+ }
+
+
+ public boolean equals(Object other) {
+ return other != null && ((Node)other).name != null && name != null && name.equals(((Node)other).name);
+ }
+
+
+ Node copy() {
+ Node ret=new Node(name, element);
+
+ if(children != null)
+ ret.children=(Vector)children.clone();
+ return ret;
+ }
+
+
+ String print(int indent) {
+ StringBuilder sb=new StringBuilder();
+ boolean is_root=name != null && "/".equals(name);
+
+ for(int i=0; i < indent; i++)
+ sb.append(' ');
+ if(!is_root) {
+ if(name == null)
+ sb.append("/");
+ else {
+ sb.append('/' + name);
+ // if(element != null) sb.append(" --> " + element);
+ }
+ }
+ sb.append('\n');
+ if(children != null) {
+ if(is_root)
+ indent=0;
+ else
+ indent+=4;
+ for(int i=0; i < children.size(); i++)
+ sb.append(((Node)children.elementAt(i)).print(indent));
+ }
+ return sb.toString();
+ }
+
+
+ public String toString() {
+ if(element != null)
+ return "[name: " + name + ", element: " + element + ']';
+ else
+ return "[name: " + name + ']';
+ }
+
+ }
+
+
+}
+
+
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/GroupRequest.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/GroupRequest.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/GroupRequest.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,678 @@
+package org.jgroups.blocks;
+
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jgroups.Address;
+import org.jgroups.Message;
+import org.jgroups.Transport;
+import org.jgroups.View;
+import org.jgroups.annotations.GuardedBy;
+import org.jgroups.util.Command;
+import org.jgroups.util.Rsp;
+import org.jgroups.util.RspList;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+
+/**
+ * Sends a message to all members of the group and waits for all responses (or timeout). Returns a
+ * boolean value (success or failure). Results (if any) can be retrieved when done.
+ * The supported transport to send requests is currently either a RequestCorrelator or a generic
+ * Transport. One of them has to be given in the constructor. It will then be used to send a
+ * request. When a message is received by either one, the receiveResponse() of this class has to
+ * be called (this class does not actively receive requests/responses itself). Also, when a view change
+ * or suspicion is received, the methods viewChange() or suspect() of this class have to be called.
+ * When started, an array of responses, correlating to the membership, is created. Each response
+ * is added to the corresponding field in the array. When all fields have been set, the algorithm
+ * terminates.
+ * This algorithm can optionally use a suspicion service (failure detector) to detect (and
+ * exclude from the membership) fauly members. If no suspicion service is available, timeouts
+ * can be used instead (see execute()
). When done, a list of suspected members
+ * can be retrieved.
+ * Because a channel might deliver requests, and responses to different requests, the
+ * GroupRequest
class cannot itself receive and process requests/responses from the
+ * channel. A mechanism outside this class has to do this; it has to determine what the responses
+ * are for the message sent by the execute()
method and call receiveResponse()
+ * to do so.
+ * Requirements : lossless delivery, e.g. acknowledgment-based message confirmation.
+ * @author Bela Ban
+ * @version $Id: GroupRequest.java,v 1.1 2012/08/17 14:51:18 marcin Exp $
+ */
+public class GroupRequest implements RspCollector, Command {
+ /** return only first response */
+ public static final int GET_FIRST=1;
+
+ /** return all responses */
+ public static final int GET_ALL=2;
+
+ /** return majority (of all non-faulty members) */
+ public static final int GET_MAJORITY=3;
+
+ /** return majority (of all members, may block) */
+ public static final int GET_ABS_MAJORITY=4;
+
+ /** return n responses (may block) */
+ public static final int GET_N=5;
+
+ /** return no response (async call) */
+ public static final int GET_NONE=6;
+
+ private Address caller;
+
+ private final Lock lock=new ReentrantLock();
+
+ /** Is set as soon as the request has received all required responses */
+ private final Condition completed=lock.newCondition();
+
+ /** Map
. Maps requests and responses */
+ @GuardedBy("lock")
+ private final Map requests=new HashMap();
+
+
+ /** bounded queue of suspected members */
+ @GuardedBy("lock")
+ private final List suspects=new ArrayList();
+
+ /** list of members, changed by viewChange() */
+ @GuardedBy("lock")
+ private final Collection members=new TreeSet();
+
+ /** keep suspects vector bounded */
+ private static final int max_suspects=40;
+ final protected Message request_msg;
+ final protected RequestCorrelator corr; // either use RequestCorrelator or ...
+ protected Transport transport; // Transport (one of them has to be non-null)
+
+ protected RspFilter rsp_filter=null;
+
+ protected int rsp_mode=GET_ALL;
+ protected boolean done=false;
+ protected long timeout=0;
+ protected int expected_mbrs=0;
+
+ private static final Log log=LogFactory.getLog(GroupRequest.class);
+
+ /** to generate unique request IDs (see getRequestId()) */
+ private static long last_req_id=1;
+
+ private long req_id=-1; // request ID for this request
+
+
+
+
+ /**
+ @param m The message to be sent
+ @param corr The request correlator to be used. A request correlator sends requests tagged with
+ a unique ID and notifies the sender when matching responses are received. The
+ reason GroupRequest
uses it instead of a Transport
is
+ that multiple requests/responses might be sent/received concurrently.
+ @param members The initial membership. This value reflects the membership to which the request
+ is sent (and from which potential responses are expected). Is reset by reset().
+ @param rsp_mode How many responses are expected. Can be
+
+ GET_ALL
: wait for all responses from non-suspected members.
+ A suspicion service might warn
+ us when a member from which a response is outstanding has crashed, so it can
+ be excluded from the responses. If no suspision service is available, a
+ timeout can be used (a value of 0 means wait forever). If a timeout of
+ 0 is used, no suspicion service is available and a member from which we
+ expect a response has crashed, this methods blocks forever ! .
+ GET_FIRST
: wait for the first available response.
+ GET_MAJORITY
: wait for the majority of all responses. The
+ majority is re-computed when a member is suspected.
+ GET_ABS_MAJORITY
: wait for the majority of
+ all members.
+ This includes failed members, so it may block if no timeout is specified.
+ GET_N
: wait for N members.
+ Return if n is >= membership+suspects.
+ GET_NONE
: don't wait for any response. Essentially send an
+ asynchronous message to the group members.
+
+ */
+ public GroupRequest(Message m, RequestCorrelator corr, Vector members, int rsp_mode) {
+ request_msg=m;
+ this.corr=corr;
+ this.rsp_mode=rsp_mode;
+ reset(members);
+ // suspects.removeAllElements(); // bela Aug 23 2002: made suspects bounded
+ }
+
+
+ /**
+ @param timeout Time to wait for responses (ms). A value of <= 0 means wait indefinitely
+ (e.g. if a suspicion service is available; timeouts are not needed).
+ */
+ public GroupRequest(Message m, RequestCorrelator corr, Vector members, int rsp_mode,
+ long timeout, int expected_mbrs) {
+ this(m, corr, members, rsp_mode);
+ if(timeout > 0)
+ this.timeout=timeout;
+ this.expected_mbrs=expected_mbrs;
+ }
+
+
+ public GroupRequest(Message m, Transport transport, Vector members, int rsp_mode) {
+ corr = null;
+ request_msg=m;
+ this.transport=transport;
+ this.rsp_mode=rsp_mode;
+ reset(members);
+ // suspects.removeAllElements(); // bela Aug 23 2002: make suspects bounded
+ }
+
+
+ /**
+ * @param timeout Time to wait for responses (ms). A value of <= 0 means wait indefinitely
+ * (e.g. if a suspicion service is available; timeouts are not needed).
+ */
+ public GroupRequest(Message m, Transport transport, Vector members,
+ int rsp_mode, long timeout, int expected_mbrs) {
+ this(m, transport, members, rsp_mode);
+ if(timeout > 0)
+ this.timeout=timeout;
+ this.expected_mbrs=expected_mbrs;
+ }
+
+ public Address getCaller() {
+ return caller;
+ }
+
+ public void setCaller(Address caller) {
+ this.caller=caller;
+ }
+
+ public void setResponseFilter(RspFilter filter) {
+ rsp_filter=filter;
+ }
+
+ public boolean execute() throws Exception {
+ return execute(false);
+ }
+
+ /**
+ * Sends the message. Returns when n responses have been received, or a
+ * timeout has occurred. n can be the first response, all
+ * responses, or a majority of the responses.
+ */
+ public boolean execute(boolean use_anycasting) throws Exception {
+ if(corr == null && transport == null) {
+ if(log.isErrorEnabled()) log.error("both corr and transport are null, cannot send group request");
+ return false;
+ }
+
+ Vector targets=null;
+ lock.lock();
+ try {
+ targets=new Vector(members);
+ req_id=getRequestId();
+ // reset(null); // clear 'responses' array
+
+ for(Address suspect: suspects) { // mark all suspects in 'received' array
+ Rsp rsp=requests.get(suspect);
+ if(rsp != null) {
+ rsp.setSuspected(true);
+ break; // we can break here because we ensure there are no duplicate members
+ }
+ }
+ }
+ finally {
+ lock.unlock();
+ }
+
+ sendRequest(targets, req_id, use_anycasting);
+
+ lock.lock();
+ try {
+ done=false;
+ boolean retval=collectResponses(timeout);
+ if(retval == false && log.isTraceEnabled())
+ log.trace("call did not execute correctly, request is " + this.toString());
+ return retval;
+ }
+ finally {
+ done=true;
+ lock.unlock();
+ }
+ }
+
+
+
+ /**
+ * This method sets the membership
variable to the value of
+ * members
. It requires that the caller already hold the
+ * rsp_mutex
lock.
+ * @param mbrs The new list of members
+ */
+ public final void reset(Vector mbrs) {
+ lock.lock();
+ try {
+ if(mbrs != null) {
+ requests.clear();
+ for(Address mbr: mbrs) {
+ requests.put(mbr, new Rsp(mbr));
+ }
+ // maintain local membership
+ this.members.clear();
+ this.members.addAll(mbrs);
+ }
+ else {
+ for(Rsp rsp: requests.values()) {
+ rsp.setReceived(false);
+ rsp.setValue(null);
+ }
+ }
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+
+ /* ---------------------- Interface RspCollector -------------------------- */
+ /**
+ * Callback (called by RequestCorrelator or Transport).
+ * Adds a response to the response table. When all responses have been received,
+ * execute()
returns.
+ */
+ public void receiveResponse(Object response_value, Address sender) {
+ lock.lock();
+ try {
+ if(done) {
+ if(log.isTraceEnabled()) log.trace("command is done; cannot add response !");
+ return;
+ }
+ if(suspects.contains(sender)) {
+ if(log.isWarnEnabled()) log.warn("received response from suspected member " + sender + "; discarding");
+ return;
+ }
+
+ if(rsp_filter != null && !rsp_filter.isAcceptable(response_value, sender)) {
+ if(!rsp_filter.needMoreResponses()) {
+ done=true;
+ completed.signalAll(); // we're done as we don't need more responses
+ }
+ return;
+ }
+
+
+ Rsp rsp=requests.get(sender);
+ if(rsp != null) {
+ if(rsp.wasReceived() == false) {
+ rsp.setValue(response_value);
+ rsp.setReceived(true);
+ if(log.isTraceEnabled())
+ log.trace(new StringBuilder("received response for request ").append(req_id).append(", sender=").
+ append(sender).append(", val=").append(response_value));
+ if(rsp_filter != null && !rsp_filter.needMoreResponses())
+ done=true;
+ completed.signalAll(); // wakes up execute()
+ }
+ }
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+
+ /**
+ * Callback (called by RequestCorrelator or Transport).
+ * Report to GroupRequest
that a member is reported as faulty (suspected).
+ * This method would probably be called when getting a suspect message from a failure detector
+ * (where available). It is used to exclude faulty members from the response list.
+ */
+ public void suspect(Address suspected_member) {
+ if(suspected_member == null)
+ return;
+
+ lock.lock();
+ try {
+ addSuspect(suspected_member);
+ Rsp rsp=requests.get(suspected_member);
+ if(rsp != null) {
+ rsp.setSuspected(true);
+ rsp.setValue(null);
+ completed.signalAll();
+ }
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+
+ /**
+ * Any member of 'membership' that is not in the new view is flagged as
+ * SUSPECTED. Any member in the new view that is not in the
+ * membership (ie, the set of responses expected for the current RPC) will
+ * not be added to it. If we did this we might run into the
+ * following problem:
+ *
+ * Membership is {A,B}
+ * A sends a synchronous group RPC (which sleeps for 60 secs in the
+ * invocation handler)
+ * C joins while A waits for responses from A and B
+ * If this would generate a new view {A,B,C} and if this expanded the
+ * response set to {A,B,C}, A would wait forever on C's response because C
+ * never received the request in the first place, therefore won't send a
+ * response.
+ *
+ */
+ public void viewChange(View new_view) {
+ Address mbr;
+ Vector mbrs=new_view != null? new_view.getMembers() : null;
+
+ lock.lock();
+ try {
+ if(requests == null || requests.isEmpty() || mbrs == null)
+ return;
+
+ this.members.clear();
+ this.members.addAll(mbrs);
+
+ Rsp rsp;
+ Set tmp=null;
+ for(Map.Entry entry: requests.entrySet()) {
+ mbr=entry.getKey();
+ if(!mbrs.contains(mbr)) {
+ if(tmp == null)
+ tmp=new HashSet();
+ tmp.add(mbr);
+ addSuspect(mbr);
+ rsp=entry.getValue();
+ rsp.setValue(null);
+ rsp.setSuspected(true);
+ }
+ }
+
+ if(tmp != null) {
+ for(Address suspect: tmp) {
+ addSuspect(suspect);
+ }
+ completed.signalAll();
+ }
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+
+ /* -------------------- End of Interface RspCollector ----------------------------------- */
+
+
+
+ /** Returns the results as a RspList */
+ public RspList getResults() {
+ lock.lock();
+ try {
+ Collection rsps=requests.values();
+ return new RspList(rsps);
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+
+ public String toString() {
+ StringBuilder ret=new StringBuilder(128);
+ ret.append("[req_id=").append(req_id).append('\n');
+ if(caller != null)
+ ret.append("caller=").append(caller).append("\n");
+
+ Address mbr;
+ Rsp rsp;
+ lock.lock();
+ try {
+ if(!requests.isEmpty()) {
+ ret.append("entries:\n");
+ for(Map.Entry entry: requests.entrySet()) {
+ mbr=entry.getKey();
+ rsp=entry.getValue();
+ ret.append(mbr).append(": ").append(rsp).append("\n");
+ }
+ }
+ }
+ finally {
+ lock.unlock();
+ }
+ return ret.toString();
+ }
+
+
+ public int getNumSuspects() {
+ return suspects.size();
+ }
+
+ /** Returns the list of suspected members. An attempt to modify the return value will throw an excxeption */
+ public Vector getSuspects() {
+ return new Vector(suspects);
+ }
+
+
+ public boolean isDone() {
+ return done;
+ }
+
+
+
+ /* --------------------------------- Private Methods -------------------------------------*/
+
+ private static int determineMajority(int i) {
+ return i < 2? i : (i / 2) + 1;
+ }
+
+ /** Generates a new unique request ID */
+ private static synchronized long getRequestId() {
+ long result=System.currentTimeMillis();
+ if(result <= last_req_id) {
+ result=last_req_id + 1;
+ }
+ last_req_id=result;
+ return result;
+ }
+
+ /** This method runs with lock locked (called by execute()
). */
+ @GuardedBy("lock")
+ private boolean collectResponses(long timeout) throws Exception {
+ if(timeout <= 0) {
+ while(true) { /* Wait for responses: */
+ adjustMembership(); // may not be necessary, just to make sure...
+ if(responsesComplete()) {
+ if(corr != null) {
+ corr.done(req_id);
+ }
+ if(log.isTraceEnabled() && rsp_mode != GET_NONE) {
+ log.trace("received all responses: " + toString());
+ }
+ return true;
+ }
+ try {
+ completed.await();
+ }
+ catch(Exception e) {
+ }
+ }
+ }
+ else {
+ long start_time=System.currentTimeMillis();
+ long timeout_time=start_time + timeout;
+ while(timeout > 0) { /* Wait for responses: */
+ if(responsesComplete()) {
+ if(corr != null)
+ corr.done(req_id);
+ if(log.isTraceEnabled() && rsp_mode != GET_NONE) {
+ log.trace("received all responses: " + toString());
+ }
+ return true;
+ }
+ timeout=timeout_time - System.currentTimeMillis();
+ if(timeout > 0) {
+ try {
+ completed.await(timeout, TimeUnit.MILLISECONDS);
+ }
+ catch(Exception e) {
+ }
+ }
+ }
+ if(corr != null) {
+ corr.done(req_id);
+ }
+ if(log.isTraceEnabled())
+ log.trace("timed out waiting for responses");
+
+ return false;
+ }
+ }
+
+
+ private void sendRequest(Vector targetMembers, long requestId,boolean use_anycasting) throws Exception {
+ try {
+ if(log.isTraceEnabled()) log.trace(new StringBuilder("sending request (id=").append(req_id).append(')'));
+ if(corr != null) {
+ corr.sendRequest(requestId, targetMembers, request_msg, rsp_mode == GET_NONE? null : this, use_anycasting);
+ }
+ else {
+ if(use_anycasting) {
+ for(Address mbr: targetMembers) {
+ Message copy=request_msg.copy(true);
+ copy.setDest(mbr);
+ transport.send(copy);
+ }
+ }
+ else {
+ transport.send(request_msg);
+ }
+ }
+ }
+ catch(Exception ex) {
+ if(corr != null)
+ corr.done(requestId);
+ throw ex;
+ }
+ }
+
+
+ @GuardedBy("lock")
+ private boolean responsesComplete() {
+ int num_received=0, num_not_received=0, num_suspected=0;
+ final int num_total=requests.size();
+
+ if(done)
+ return true;
+
+ for(Rsp rsp: requests.values()) {
+ if(rsp.wasReceived()) {
+ num_received++;
+ }
+ else {
+ if(rsp.wasSuspected()) {
+ num_suspected++;
+ }
+ else {
+ num_not_received++;
+ }
+ }
+ }
+
+ switch(rsp_mode) {
+ case GET_FIRST:
+ if(num_received > 0)
+ return true;
+ if(num_suspected >= num_total)
+ // e.g. 2 members, and both suspected
+ return true;
+ break;
+ case GET_ALL:
+ return num_received + num_suspected >= num_total;
+ case GET_MAJORITY:
+ int majority=determineMajority(num_total);
+ if(num_received + num_suspected >= majority)
+ return true;
+ break;
+ case GET_ABS_MAJORITY:
+ majority=determineMajority(num_total);
+ if(num_received >= majority)
+ return true;
+ break;
+ case GET_N:
+ if(expected_mbrs >= num_total) {
+ rsp_mode=GET_ALL;
+ return responsesComplete();
+ }
+ return num_received >= expected_mbrs || num_received + num_not_received < expected_mbrs && num_received + num_suspected >= expected_mbrs;
+ case GET_NONE:
+ return true;
+ default :
+ if(log.isErrorEnabled()) log.error("rsp_mode " + rsp_mode + " unknown !");
+ break;
+ }
+ return false;
+ }
+
+
+
+
+
+ /**
+ * Adjusts the 'received' array in the following way:
+ *
+ * if a member P in 'membership' is not in 'members', P's entry in the 'received' array
+ * will be marked as SUSPECTED
+ * if P is 'suspected_mbr', then P's entry in the 'received' array will be marked
+ * as SUSPECTED
+ *
+ * This call requires exclusive access to rsp_mutex (called by getResponses() which has
+ * a the rsp_mutex locked, so this should not be a problem). This method needs to have lock held.
+ */
+ @GuardedBy("lock")
+ private void adjustMembership() {
+ if(requests.isEmpty())
+ return;
+
+ Address mbr;
+ Rsp rsp;
+ for(Map.Entry entry: requests.entrySet()) {
+ mbr=entry.getKey();
+ if((!this.members.contains(mbr)) || suspects.contains(mbr)) {
+ addSuspect(mbr);
+ rsp=entry.getValue();
+ rsp.setValue(null);
+ rsp.setSuspected(true);
+ }
+ }
+ }
+
+ /**
+ * Adds a member to the 'suspects' list. Removes oldest elements from 'suspects' list
+ * to keep the list bounded ('max_suspects' number of elements), Requires lock to be held
+ */
+ @GuardedBy("lock")
+ private void addSuspect(Address suspected_mbr) {
+ if(!suspects.contains(suspected_mbr)) {
+ suspects.add(suspected_mbr);
+ while(suspects.size() >= max_suspects && !suspects.isEmpty())
+ suspects.remove(0); // keeps queue bounded
+ }
+ }
+
+ private static String modeToString(int m) {
+ switch(m) {
+ case GET_FIRST: return "GET_FIRST";
+ case GET_ALL: return "GET_ALL";
+ case GET_MAJORITY: return "GET_MAJORITY";
+ case GET_ABS_MAJORITY: return "GET_ABS_MAJORITY";
+ case GET_N: return "GET_N";
+ case GET_NONE: return "GET_NONE";
+ default: return " (" + m + ")";
+ }
+ }
+
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/LockManager.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/LockManager.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/LockManager.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,87 @@
+package org.jgroups.blocks;
+
+import org.jgroups.ChannelException;
+
+/**
+ * LockManager
represents generic lock manager that allows
+ * obtaining and releasing locks on objects.
+ *
+ * @author Roman Rokytskyy (rrokytskyy@acm.org)
+ * @author Robert Schaffar-Taurok (robert@fusion.at)
+ * @version $Id: LockManager.java,v 1.1 2012/08/17 14:51:17 marcin Exp $
+ */
+public interface LockManager {
+
+ /**
+ * Obtain lock on obj
for specified owner
.
+ * Implementation should try to obtain lock few times within the
+ * specified timeout.
+ *
+ * @param obj obj to lock, usually not full object but object's ID.
+ * @param owner object identifying entity that will own the lock.
+ * @param timeout maximum time that we grant to obtain a lock.
+ *
+ * @throws LockNotGrantedException if lock is not granted within
+ * specified period.
+ *
+ * @throws ClassCastException if obj
and/or
+ * owner
is not of type that implementation expects to get
+ * (for example, when distributed lock manager obtains non-serializable
+ * obj
or owner
).
+ *
+ * @throws ChannelException if something bad happened to communication
+ * channel.
+ */
+ void lock(Object obj, Object owner, int timeout)
+ throws LockNotGrantedException, ClassCastException, ChannelException;
+
+ /**
+ * Release lock on obj
owned by specified owner
.
+ *
+ * since 2.2.9 this method is only a wrapper for
+ * unlock(Object lockId, Object owner, boolean releaseMultiLocked).
+ * Use that with releaseMultiLocked set to true if you want to be able to
+ * release multiple locked locks (for example after a merge)
+ *
+ * @param obj obj to lock, usually not full object but object's ID.
+ * @param owner object identifying entity that will own the lock.
+ *
+ * @throws LockOwnerMismatchException if lock is owned by another object.
+ *
+ * @throws ClassCastException if obj
and/or
+ * owner
is not of type that implementation expects to get
+ * (for example, when distributed lock manager obtains non-serializable
+ * obj
or owner
).
+ *
+ * @throws ChannelException if something bad happened to communication
+ * channel.
+ */
+ void unlock(Object obj, Object owner)
+ throws LockNotReleasedException, ClassCastException, ChannelException;
+
+ /**
+ * Release lock on obj
owned by specified owner
.
+ *
+ * @param obj obj to lock, usually not full object but object's ID.
+ * @param owner object identifying entity that will own the lock.
+ * @param releaseMultiLocked force unlocking of the lock if the local
+ * lockManager owns the lock even if another lockManager owns the same lock
+ *
+ * @throws LockOwnerMismatchException if lock is owned by another object.
+ *
+ * @throws ClassCastException if obj
and/or
+ * owner
is not of type that implementation expects to get
+ * (for example, when distributed lock manager obtains non-serializable
+ * obj
or owner
).
+ *
+ * @throws ChannelException if something bad happened to communication
+ * channel.
+ *
+ * @throws LockMultiLockedException if the lock was unlocked, but another
+ * node already held the lock
+ */
+ void unlock(Object obj, Object owner, boolean releaseMultiLocked)
+ throws LockNotReleasedException, ClassCastException, ChannelException, LockMultiLockedException;
+
+
+}
\ No newline at end of file
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/LockMultiLockedException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/LockMultiLockedException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/LockMultiLockedException.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,23 @@
+package org.jgroups.blocks;
+
+
+/**
+ * Thrown by the {@link org.jgroups.blocks.DistributedLockManager#unlock(Object, Object, boolean)} method if a lock is only locally released, because it is locked
+ * by multiple DistributedLockManagers. This can happen after a merge for example.
+ *
+ * @author Robert Schaffar-Taurok (robert@fusion.at)
+ * @version $Id: LockMultiLockedException.java,v 1.1 2012/08/17 14:51:17 marcin Exp $
+ */
+public class LockMultiLockedException extends Exception {
+
+ private static final long serialVersionUID = 3719208228960070835L;
+
+ public LockMultiLockedException() {
+ super();
+ }
+
+ public LockMultiLockedException(String s) {
+ super(s);
+ }
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/LockNotGrantedException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/LockNotGrantedException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/LockNotGrantedException.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,21 @@
+package org.jgroups.blocks;
+
+/**
+ * This exception indicated that lock manager refused to give a lock on
+ * some resource.
+ *
+ * @author Roman Rokytskyy (rrokytskyy@acm.org)
+ */
+public class LockNotGrantedException extends Exception {
+
+ private static final long serialVersionUID = 4074824788210185433L;
+
+ public LockNotGrantedException() {
+ super();
+ }
+
+ public LockNotGrantedException(String s) {
+ super(s);
+ }
+
+}
\ No newline at end of file
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/LockNotReleasedException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/LockNotReleasedException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/LockNotReleasedException.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,21 @@
+package org.jgroups.blocks;
+
+/**
+ * This exception indicated that lock manager refused to release a lock on
+ * some resource.
+ *
+ * @author Roman Rokytskyy (rrokytskyy@acm.org)
+ */
+public class LockNotReleasedException extends Exception {
+
+ private static final long serialVersionUID = -350403929687059570L;
+
+ public LockNotReleasedException() {
+ super();
+ }
+
+ public LockNotReleasedException(String s) {
+ super(s);
+ }
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/LockingException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/LockingException.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/LockingException.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,35 @@
+// $Id: LockingException.java,v 1.1 2012/08/17 14:51:18 marcin Exp $
+
+
+package org.jgroups.blocks;
+
+import java.util.Map;
+
+
+public class LockingException extends Exception {
+
+ private static final long serialVersionUID = -712594616520011007L;
+
+ Map failed_lockers=null; // list of members who failed acquiring locks (keys=Address, values=exception string)
+
+ public LockingException(String msg) {
+ super(msg);
+ }
+
+ public LockingException(Map m) {
+ super("LockingException");
+ failed_lockers=m;
+ }
+
+
+ public String toString() {
+ StringBuilder sb=new StringBuilder();
+
+ sb.append(super.toString());
+
+ if(failed_lockers != null && failed_lockers.size() > 0)
+ sb.append(" (failed members: ").append(failed_lockers);
+ return sb.toString();
+ }
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/MembershipListenerAdapter.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/MembershipListenerAdapter.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/MembershipListenerAdapter.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,92 @@
+package org.jgroups.blocks;
+
+import org.jgroups.Address;
+import org.jgroups.MembershipListener;
+import org.jgroups.View;
+import org.jgroups.ExtendedMembershipListener;
+
+import java.util.HashSet;
+
+/**
+ * This class provides multiplexing possibilities for {@link MembershipListener}
+ * instances. Usually, we have more than one instance willing to listen to
+ * membership messages. {@link PullPushAdapter} allows only one instance of
+ * {@link MembershipListener} to be registered for message notification. With
+ * help of this class you can overcome this limitation.
+ *
+ * @author Roman Rokytskyy (rrokytskyy@acm.org)
+ */
+
+public class MembershipListenerAdapter implements MembershipListener {
+
+ protected final HashSet membershipListeners = new HashSet();
+ protected MembershipListener[] membershipListenersCache =
+ new MembershipListener[0];
+
+ /**
+ * Notify membership listeners to temporarily stop sending messages into
+ * a channel. This method in turn calls same method of all registered
+ * membership listener.
+ */
+ public void block() {
+ for(int i = 0; i < membershipListenersCache.length; i++)
+ membershipListenersCache[i].block();
+ }
+
+ public void unblock() {
+ for(int i = 0; i < membershipListenersCache.length; i++) {
+ if(membershipListenersCache[i] instanceof ExtendedMembershipListener)
+ ((ExtendedMembershipListener)membershipListenersCache[i]).unblock();
+ }
+ }
+
+
+ /**
+ * Notify membership listener that some node was suspected. This method
+ * in turn passes suspected member address to all registered membership
+ * listeners.
+ */
+ public void suspect(Address suspected_mbr) {
+ for(int i = 0; i < membershipListenersCache.length; i++)
+ membershipListenersCache[i].suspect(suspected_mbr);
+ }
+
+ /**
+ * Notify membership listener that new view was accepted. This method in
+ * turn passes new view to all registered membership listeners.
+ */
+ public void viewAccepted(View new_view) {
+ for(int i = 0; i < membershipListenersCache.length; i++)
+ membershipListenersCache[i].viewAccepted(new_view);
+ }
+
+ /**
+ * Add membership listener to this adapter. This method registers
+ * listener
to be notified when membership event is generated.
+ *
+ * @param listener instance of {@link MembershipListener} that should be
+ * added to this adapter.
+ */
+ public synchronized void addMembershipListener(MembershipListener listener) {
+ if (membershipListeners.add(listener))
+ membershipListenersCache =
+ (MembershipListener[])membershipListeners.toArray(
+ new MembershipListener[membershipListeners.size()]);
+ }
+
+ /**
+ * Remove membership listener from this adapter. This method deregisters
+ * listener
from notification when membership event is generated.
+ *
+ * @param listener instance of {@link MembershipListener} that should be
+ * removed from this adapter.
+ */
+ public synchronized void removeMembershipListener(MembershipListener listener) {
+ if (membershipListeners.remove(listener))
+ membershipListenersCache =
+ (MembershipListener[])membershipListeners.toArray(
+ new MembershipListener[membershipListeners.size()]);
+
+ }
+
+}
\ No newline at end of file
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/MessageDispatcher.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/MessageDispatcher.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/MessageDispatcher.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,956 @@
+
+package org.jgroups.blocks;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jgroups.*;
+import org.jgroups.protocols.TP;
+import org.jgroups.stack.Protocol;
+import org.jgroups.stack.StateTransferInfo;
+import org.jgroups.util.Rsp;
+import org.jgroups.util.RspList;
+import org.jgroups.util.Util;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.TreeSet;
+import java.util.Vector;
+
+
+/**
+ * Provides synchronous and asynchronous message sending with request-response
+ * correlation; i.e., matching responses with the original request.
+ * It also offers push-style message reception (by internally using the PullPushAdapter).
+ *
+ * Channels are simple patterns to asynchronously send a receive messages.
+ * However, a significant number of communication patterns in group communication
+ * require synchronous communication. For example, a sender would like to send a
+ * message to the group and wait for all responses. Or another application would
+ * like to send a message to the group and wait only until the majority of the
+ * receivers have sent a response, or until a timeout occurred. MessageDispatcher
+ * offers a combination of the above pattern with other patterns.
+ *
+ * Used on top of channel to implement group requests. Client's handle()
+ * method is called when request is received. Is the equivalent of RpcProtocol on
+ * the application instead of protocol level.
+ *
+ * @author Bela Ban
+ * @version $Id: MessageDispatcher.java,v 1.1 2012/08/17 14:51:18 marcin Exp $
+ */
+public class MessageDispatcher implements RequestHandler {
+ protected Channel channel=null;
+ protected RequestCorrelator corr=null;
+ protected MessageListener msg_listener=null;
+ protected MembershipListener membership_listener=null;
+ protected RequestHandler req_handler=null;
+ protected ProtocolAdapter prot_adapter=null;
+ protected TransportAdapter transport_adapter=null;
+ protected final Collection members=new TreeSet();
+ protected Address local_addr=null;
+ protected boolean deadlock_detection=false;
+ protected PullPushAdapter adapter=null;
+ protected PullPushHandler handler=null;
+ protected Serializable id=null;
+ protected final Log log=LogFactory.getLog(getClass());
+
+
+ /**
+ * Process items on the queue concurrently (RequestCorrelator). The default is to wait until the processing of an
+ * item has completed before fetching the next item from the queue. Note that setting this to true may destroy the
+ * properties of a protocol stack, e.g total or causal order may not be guaranteed. Set this to true only if you
+ * know what you're doing !
+ */
+ protected boolean concurrent_processing=false;
+
+
+ public MessageDispatcher() {
+ }
+
+ public MessageDispatcher(Channel channel, MessageListener l, MembershipListener l2) {
+ this.channel=channel;
+ prot_adapter=new ProtocolAdapter();
+ if(channel != null) {
+ local_addr=channel.getLocalAddress();
+ }
+ setMessageListener(l);
+ setMembershipListener(l2);
+ if(channel != null) {
+ channel.setUpHandler(prot_adapter);
+ }
+ start();
+ }
+
+
+ public MessageDispatcher(Channel channel, MessageListener l, MembershipListener l2, boolean deadlock_detection) {
+ this.channel=channel;
+ this.deadlock_detection=deadlock_detection;
+ prot_adapter=new ProtocolAdapter();
+ if(channel != null) {
+ local_addr=channel.getLocalAddress();
+ }
+ setMessageListener(l);
+ setMembershipListener(l2);
+ if(channel != null) {
+ channel.setUpHandler(prot_adapter);
+ }
+ start();
+ }
+
+ public MessageDispatcher(Channel channel, MessageListener l, MembershipListener l2,
+ boolean deadlock_detection, boolean concurrent_processing) {
+ this.channel=channel;
+ this.deadlock_detection=deadlock_detection;
+ this.concurrent_processing=concurrent_processing;
+ prot_adapter=new ProtocolAdapter();
+ if(channel != null) {
+ local_addr=channel.getLocalAddress();
+ }
+ setMessageListener(l);
+ setMembershipListener(l2);
+ if(channel != null) {
+ channel.setUpHandler(prot_adapter);
+ }
+ start();
+ }
+
+
+ public MessageDispatcher(Channel channel, MessageListener l, MembershipListener l2, RequestHandler req_handler) {
+ this(channel, l, l2);
+ setRequestHandler(req_handler);
+ }
+
+
+ public MessageDispatcher(Channel channel, MessageListener l, MembershipListener l2, RequestHandler req_handler,
+ boolean deadlock_detection) {
+ this(channel, l, l2, deadlock_detection, false);
+ setRequestHandler(req_handler);
+ }
+
+ public MessageDispatcher(Channel channel, MessageListener l, MembershipListener l2, RequestHandler req_handler,
+ boolean deadlock_detection, boolean concurrent_processing) {
+ this(channel, l, l2, deadlock_detection, concurrent_processing);
+ setRequestHandler(req_handler);
+ }
+
+
+ /*
+ * Uses a user-provided PullPushAdapter rather than a Channel as transport. If id is non-null, it will be
+ * used to register under that id. This is typically used when another building block is already using
+ * PullPushAdapter, and we want to add this building block in addition. The id is the used to discriminate
+ * between messages for the various blocks on top of PullPushAdapter. If null, we will assume we are the
+ * first block created on PullPushAdapter.
+ * @param adapter The PullPushAdapter which to use as underlying transport
+ * @param id A serializable object (e.g. an Integer) used to discriminate (multiplex/demultiplex) between
+ * requests/responses for different building blocks on top of PullPushAdapter.
+ */
+ public MessageDispatcher(PullPushAdapter adapter, Serializable id,
+ MessageListener l, MembershipListener l2) {
+ this.adapter=adapter;
+ this.id=id;
+ setMembers(((Channel) adapter.getTransport()).getView().getMembers());
+ setMessageListener(l);
+ setMembershipListener(l2);
+ handler=new PullPushHandler();
+ transport_adapter=new TransportAdapter();
+ adapter.addMembershipListener(handler); // remove in stop()
+ if(id == null) { // no other building block around, let's become the main consumer of this PullPushAdapter
+ adapter.setListener(handler);
+ }
+ else {
+ adapter.registerListener(id, handler);
+ }
+
+ Transport tp;
+ if((tp=adapter.getTransport()) instanceof Channel) {
+ local_addr=((Channel) tp).getLocalAddress();
+ }
+ start();
+ }
+
+
+ /*
+ * Uses a user-provided PullPushAdapter rather than a Channel as transport. If id is non-null, it will be
+ * used to register under that id. This is typically used when another building block is already using
+ * PullPushAdapter, and we want to add this building block in addition. The id is the used to discriminate
+ * between messages for the various blocks on top of PullPushAdapter. If null, we will assume we are the
+ * first block created on PullPushAdapter.
+ * @param adapter The PullPushAdapter which to use as underlying transport
+ * @param id A serializable object (e.g. an Integer) used to discriminate (multiplex/demultiplex) between
+ * requests/responses for different building blocks on top of PullPushAdapter.
+ * @param req_handler The object implementing RequestHandler. It will be called when a request is received
+ */
+ public MessageDispatcher(PullPushAdapter adapter, Serializable id,
+ MessageListener l, MembershipListener l2,
+ RequestHandler req_handler) {
+ this.adapter=adapter;
+ this.id=id;
+ setMembers(((Channel) adapter.getTransport()).getView().getMembers());
+ setRequestHandler(req_handler);
+ setMessageListener(l);
+ setMembershipListener(l2);
+ handler=new PullPushHandler();
+ transport_adapter=new TransportAdapter();
+ adapter.addMembershipListener(handler);
+ if(id == null) { // no other building block around, let's become the main consumer of this PullPushAdapter
+ adapter.setListener(handler);
+ }
+ else {
+ adapter.registerListener(id, handler);
+ }
+
+ Transport tp;
+ if((tp=adapter.getTransport()) instanceof Channel) {
+ local_addr=((Channel) tp).getLocalAddress(); // fixed bug #800774
+ }
+
+ start();
+ }
+
+
+ public MessageDispatcher(PullPushAdapter adapter, Serializable id,
+ MessageListener l, MembershipListener l2,
+ RequestHandler req_handler, boolean concurrent_processing) {
+ this.concurrent_processing=concurrent_processing;
+ this.adapter=adapter;
+ this.id=id;
+ setMembers(((Channel) adapter.getTransport()).getView().getMembers());
+ setRequestHandler(req_handler);
+ setMessageListener(l);
+ setMembershipListener(l2);
+ handler=new PullPushHandler();
+ transport_adapter=new TransportAdapter();
+ adapter.addMembershipListener(handler);
+ if(id == null) { // no other building block around, let's become the main consumer of this PullPushAdapter
+ adapter.setListener(handler);
+ }
+ else {
+ adapter.registerListener(id, handler);
+ }
+
+ Transport tp;
+ if((tp=adapter.getTransport()) instanceof Channel) {
+ local_addr=((Channel) tp).getLocalAddress(); // fixed bug #800774
+ }
+
+ start();
+ }
+
+ /** Returns a copy of members */
+ protected Collection getMembers() {
+ synchronized(members) {
+ return new ArrayList(members);
+ }
+ }
+
+
+ /**
+ * If this dispatcher is using a user-provided PullPushAdapter, then need to set the members from the adapter
+ * initially since viewChange has most likely already been called in PullPushAdapter.
+ */
+ private void setMembers(Vector new_mbrs) {
+ if(new_mbrs != null) {
+ synchronized(members) {
+ members.clear();
+ members.addAll(new_mbrs);
+ }
+ }
+ }
+
+ public boolean getDeadlockDetection() {return deadlock_detection;}
+
+ public void setDeadlockDetection(boolean flag) {
+ deadlock_detection=flag;
+ if(corr != null)
+ corr.setDeadlockDetection(flag);
+ }
+
+
+ public boolean getConcurrentProcessing() {return concurrent_processing;}
+
+ public void setConcurrentProcessing(boolean flag) {
+ this.concurrent_processing=flag;
+ }
+
+
+ public final void start() {
+ if(corr == null) {
+ if(transport_adapter != null) {
+ corr=new RequestCorrelator("MsgDisp", transport_adapter,
+ this, deadlock_detection, local_addr, concurrent_processing);
+ }
+ else {
+ corr=new RequestCorrelator("MsgDisp", prot_adapter,
+ this, deadlock_detection, local_addr, concurrent_processing);
+ }
+ }
+ correlatorStarted();
+ corr.start();
+
+ if(channel != null) {
+ Vector tmp_mbrs=channel.getView() != null ? channel.getView().getMembers() : null;
+ setMembers(tmp_mbrs);
+ if(channel instanceof JChannel) {
+ TP transport=((JChannel)channel).getProtocolStack().getTransport();
+ corr.registerProbeHandler(transport);
+ }
+ }
+ }
+
+ protected void correlatorStarted() {
+ ;
+ }
+
+
+ public void stop() {
+ if(corr != null) {
+ corr.stop();
+ }
+
+ if(channel instanceof JChannel) {
+ TP transport=((JChannel)channel).getProtocolStack().getTransport();
+ corr.unregisterProbeHandler(transport);
+ }
+
+ // fixes leaks of MembershipListeners (http://jira.jboss.com/jira/browse/JGRP-160)
+ if(adapter != null && handler != null) {
+ adapter.removeMembershipListener(handler);
+ }
+ }
+
+
+ public final void setMessageListener(MessageListener l) {
+ msg_listener=l;
+ }
+
+ /**
+ * Gives access to the currently configured MessageListener. Returns null if there is no
+ * configured MessageListener.
+ */
+ public MessageListener getMessageListener() {
+ return msg_listener;
+ }
+
+ public final void setMembershipListener(MembershipListener l) {
+ membership_listener=l;
+ }
+
+ public final void setRequestHandler(RequestHandler rh) {
+ req_handler=rh;
+ }
+
+ /**
+ * Offers access to the underlying Channel.
+ * @return a reference to the underlying Channel.
+ */
+ public Channel getChannel() {
+ return channel;
+ }
+
+ public void setChannel(Channel ch) {
+ if(ch == null)
+ return;
+ this.channel=ch;
+ local_addr=channel.getLocalAddress();
+ if(prot_adapter == null)
+ prot_adapter=new ProtocolAdapter();
+ channel.setUpHandler(prot_adapter);
+ }
+
+
+ public void send(Message msg) throws ChannelNotConnectedException, ChannelClosedException {
+ if(channel != null) {
+ channel.send(msg);
+ }
+ else
+ if(adapter != null) {
+ try {
+ if(id != null) {
+ adapter.send(id, msg);
+ }
+ else {
+ adapter.send(msg);
+ }
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) {
+ log.error("exception=" + Util.print(ex));
+ }
+ }
+ }
+ else {
+ if(log.isErrorEnabled()) {
+ log.error("channel == null");
+ }
+ }
+ }
+
+
+ public RspList castMessage(final Vector dests, Message msg, int mode, long timeout) {
+ return castMessage(dests, msg, mode, timeout, false);
+ }
+
+
+ /**
+ * Cast a message to all members, and wait for mode
responses. The responses are returned in a response
+ * list, where each response is associated with its sender.
Uses GroupRequest
.
+ *
+ * @param dests The members to which the message is to be sent. If it is null, then the message is sent to all
+ * members
+ * @param msg The message to be sent to n members
+ * @param mode Defined in GroupRequest
. The number of responses to wait for:
GET_FIRST:
+ * return the first response received. GET_ALL: wait for all responses (minus the ones from
+ * suspected members) GET_MAJORITY: wait for a majority of all responses (relative to the grp
+ * size) GET_ABS_MAJORITY: wait for majority (absolute, computed once) GET_N: wait for n
+ * responses (may block if n > group size) GET_NONE: wait for no responses, return immediately
+ * (non-blocking)
+ * @param timeout If 0: wait forever. Otherwise, wait for mode
responses or timeout time.
+ * @return RspList A list of responses. Each response is an Object
and associated to its sender.
+ */
+ public RspList castMessage(final Vector dests, Message msg, int mode, long timeout, boolean use_anycasting) {
+ return castMessage(dests, msg, mode, timeout, use_anycasting, null);
+ }
+
+
+ public RspList castMessage(final Vector dests, Message msg, int mode, long timeout, boolean use_anycasting,
+ RspFilter filter) {
+ GroupRequest _req=null;
+ Vector real_dests;
+ Channel tmp;
+
+ // we need to clone because we don't want to modify the original
+ // (we remove ourselves if LOCAL is false, see below) !
+ // real_dests=dests != null ? (Vector) dests.clone() : (members != null ? new Vector(members) : null);
+ if(dests != null) {
+ real_dests=(Vector)dests.clone();
+ real_dests.retainAll(this.members);
+ }
+ else {
+ synchronized(members) {
+ real_dests=new Vector(members);
+ }
+ }
+
+ // if local delivery is off, then we should not wait for the message from the local member.
+ // therefore remove it from the membership
+ tmp=channel;
+ if(tmp == null) {
+ if(adapter != null && adapter.getTransport() instanceof Channel) {
+ tmp=(Channel) adapter.getTransport();
+ }
+ }
+
+ if(tmp != null && tmp.getOpt(Channel.LOCAL).equals(Boolean.FALSE)) {
+ if(local_addr == null) {
+ local_addr=tmp.getLocalAddress();
+ }
+ if(local_addr != null) {
+ real_dests.removeElement(local_addr);
+ }
+ }
+
+ // don't even send the message if the destination list is empty
+ if(log.isTraceEnabled())
+ log.trace("real_dests=" + real_dests);
+
+ if(real_dests.isEmpty()) {
+ if(log.isTraceEnabled())
+ log.trace("destination list is empty, won't send message");
+ return new RspList(); // return empty response list
+ }
+
+ _req=new GroupRequest(msg, corr, real_dests, mode, timeout, 0);
+ _req.setCaller(this.local_addr);
+ _req.setResponseFilter(filter);
+ try {
+ _req.execute(use_anycasting);
+ }
+ catch(Exception ex) {
+ throw new RuntimeException("failed executing request " + _req, ex);
+ }
+
+ return _req.getResults();
+ }
+
+
+ /**
+ * Multicast a message request to all members in dests
and receive responses via the RspCollector
+ * interface. When done receiving the required number of responses, the caller has to call done(req_id) on the
+ * underlyinh RequestCorrelator, so that the resources allocated to that request can be freed.
+ *
+ * @param dests The list of members from which to receive responses. Null means all members
+ * @param req_id The ID of the request. Used by the underlying RequestCorrelator to correlate responses with
+ * requests
+ * @param msg The request to be sent
+ * @param coll The sender needs to provide this interface to collect responses. Call will return immediately if
+ * this is null
+ */
+ public void castMessage(final Vector dests, long req_id, Message msg, RspCollector coll) {
+ Vector real_dests;
+ Channel tmp;
+
+ if(msg == null) {
+ if(log.isErrorEnabled())
+ log.error("request is null");
+ return;
+ }
+
+ if(coll == null) {
+ if(log.isErrorEnabled())
+ log.error("response collector is null (must be non-null)");
+ return;
+ }
+
+ // we need to clone because we don't want to modify the original
+ // (we remove ourselves if LOCAL is false, see below) !
+ //real_dests=dests != null ? (Vector) dests.clone() : (Vector) members.clone();
+ if(dests != null) {
+ real_dests=(Vector)dests.clone();
+ real_dests.retainAll(this.members);
+ }
+ else {
+ synchronized(members) {
+ real_dests=new Vector(members);
+ }
+ }
+
+ // if local delivery is off, then we should not wait for the message from the local member.
+ // therefore remove it from the membership
+ tmp=channel;
+ if(tmp == null) {
+ if(adapter != null && adapter.getTransport() instanceof Channel) {
+ tmp=(Channel) adapter.getTransport();
+ }
+ }
+
+ if(tmp != null && tmp.getOpt(Channel.LOCAL).equals(Boolean.FALSE)) {
+ if(local_addr == null) {
+ local_addr=tmp.getLocalAddress();
+ }
+ if(local_addr != null) {
+ real_dests.removeElement(local_addr);
+ }
+ }
+
+ // don't even send the message if the destination list is empty
+ if(real_dests.isEmpty()) {
+ if(log.isDebugEnabled())
+ log.debug("destination list is empty, won't send message");
+ return;
+ }
+
+ try {
+ corr.sendRequest(req_id, real_dests, msg, coll);
+ }
+ catch(Exception e) {
+ throw new RuntimeException("failure sending request " + req_id + " to " + real_dests, e);
+ }
+ }
+
+
+ public void done(long req_id) {
+ corr.done(req_id);
+ }
+
+
+ /**
+ * Sends a message to a single member (destination = msg.dest) and returns the response. The message's destination
+ * must be non-zero !
+ */
+ public Object sendMessage(Message msg, int mode, long timeout) throws TimeoutException, SuspectedException {
+ Vector mbrs=new Vector();
+ RspList rsp_list=null;
+ Object dest=msg.getDest();
+ Rsp rsp;
+ GroupRequest _req=null;
+
+ if(dest == null) {
+ if(log.isErrorEnabled())
+ log.error("the message's destination is null, cannot send message");
+ return null;
+ }
+
+ mbrs.addElement(dest); // dummy membership (of destination address)
+
+ _req=new GroupRequest(msg, corr, mbrs, mode, timeout, 0);
+ _req.setCaller(local_addr);
+ try {
+ _req.execute();
+ }
+ catch(Exception t) {
+ throw new RuntimeException("failed executing request " + _req, t);
+ }
+
+ if(mode == GroupRequest.GET_NONE) {
+ return null;
+ }
+
+ rsp_list=_req.getResults();
+
+ if(rsp_list.isEmpty()) {
+ if(log.isWarnEnabled())
+ log.warn(" response list is empty");
+ return null;
+ }
+ if(rsp_list.size() > 1) {
+ if(log.isWarnEnabled())
+ log.warn("response list contains more that 1 response; returning first response !");
+ }
+ rsp=(Rsp)rsp_list.elementAt(0);
+ if(rsp.wasSuspected()) {
+ throw new SuspectedException(dest);
+ }
+ if(!rsp.wasReceived()) {
+ throw new TimeoutException("timeout sending message to " + dest);
+ }
+ return rsp.getValue();
+ }
+
+
+
+ /* ------------------------ RequestHandler Interface ---------------------- */
+ public Object handle(Message msg) {
+ if(req_handler != null) {
+ return req_handler.handle(msg);
+ }
+ else {
+ return null;
+ }
+ }
+ /* -------------------- End of RequestHandler Interface ------------------- */
+
+
+
+
+
+
+ class ProtocolAdapter extends Protocol implements UpHandler {
+
+
+ /* ------------------------- Protocol Interface --------------------------- */
+
+ public String getName() {
+ return "MessageDispatcher";
+ }
+
+
+
+ private Object handleUpEvent(Event evt) {
+ switch(evt.getType()) {
+ case Event.MSG:
+ if(msg_listener != null) {
+ msg_listener.receive((Message) evt.getArg());
+ }
+ break;
+
+ case Event.GET_APPLSTATE: // reply with GET_APPLSTATE_OK
+ StateTransferInfo info=(StateTransferInfo)evt.getArg();
+ String state_id=info.state_id;
+ byte[] tmp_state=null;
+ if(msg_listener != null) {
+ try {
+ if(msg_listener instanceof ExtendedMessageListener && state_id!=null) {
+ tmp_state=((ExtendedMessageListener)msg_listener).getState(state_id);
+ }
+ else {
+ tmp_state=msg_listener.getState();
+ }
+ }
+ catch(Throwable t) {
+ this.log.error("failed getting state from message listener (" + msg_listener + ')', t);
+ }
+ }
+ return new StateTransferInfo(null, state_id, 0L, tmp_state);
+
+ case Event.GET_STATE_OK:
+ if(msg_listener != null) {
+ try {
+ info=(StateTransferInfo)evt.getArg();
+ String id=info.state_id;
+ if(msg_listener instanceof ExtendedMessageListener && id!=null) {
+ ((ExtendedMessageListener)msg_listener).setState(id, info.state);
+ }
+ else {
+ msg_listener.setState(info.state);
+ }
+ }
+ catch(ClassCastException cast_ex) {
+ if(this.log.isErrorEnabled())
+ this.log.error("received SetStateEvent, but argument " +
+ evt.getArg() + " is not serializable. Discarding message.");
+ }
+ }
+ break;
+
+ case Event.STATE_TRANSFER_OUTPUTSTREAM:
+ StateTransferInfo sti=(StateTransferInfo)evt.getArg();
+ OutputStream os=sti.outputStream;
+ if(msg_listener instanceof ExtendedMessageListener) {
+ if(os != null && msg_listener instanceof ExtendedMessageListener) {
+ if(sti.state_id == null)
+ ((ExtendedMessageListener)msg_listener).getState(os);
+ else
+ ((ExtendedMessageListener)msg_listener).getState(sti.state_id, os);
+ }
+ return new StateTransferInfo(null, os, sti.state_id);
+ }
+ else if(msg_listener instanceof MessageListener){
+ if(log.isWarnEnabled()){
+ log.warn("Channel has STREAMING_STATE_TRANSFER, however,"
+ + " application does not implement ExtendedMessageListener. State is not transfered");
+ Util.close(os);
+ }
+ }
+ break;
+
+ case Event.STATE_TRANSFER_INPUTSTREAM:
+ sti=(StateTransferInfo)evt.getArg();
+ InputStream is=sti.inputStream;
+ if(msg_listener instanceof ExtendedMessageListener) {
+ if(is!=null && msg_listener instanceof ExtendedMessageListener) {
+ if(sti.state_id == null)
+ ((ExtendedMessageListener)msg_listener).setState(is);
+ else
+ ((ExtendedMessageListener)msg_listener).setState(sti.state_id, is);
+ }
+ }
+ else if(msg_listener instanceof MessageListener){
+ if(log.isWarnEnabled()){
+ log.warn("Channel has STREAMING_STATE_TRANSFER, however,"
+ + " application does not implement ExtendedMessageListener. State is not transfered");
+ Util.close(is);
+ }
+ }
+ break;
+
+ case Event.VIEW_CHANGE:
+ View v=(View) evt.getArg();
+ Vector new_mbrs=v.getMembers();
+ setMembers(new_mbrs);
+ if(membership_listener != null) {
+ membership_listener.viewAccepted(v);
+ }
+ break;
+
+ case Event.SET_LOCAL_ADDRESS:
+ if(log.isTraceEnabled())
+ log.trace("setting local_addr (" + local_addr + ") to " + evt.getArg());
+ local_addr=(Address)evt.getArg();
+ break;
+
+ case Event.SUSPECT:
+ if(membership_listener != null) {
+ membership_listener.suspect((Address) evt.getArg());
+ }
+ break;
+
+ case Event.BLOCK:
+ if(membership_listener != null) {
+ membership_listener.block();
+ }
+ channel.blockOk();
+ break;
+ case Event.UNBLOCK:
+ if(membership_listener instanceof ExtendedMembershipListener) {
+ ((ExtendedMembershipListener)membership_listener).unblock();
+ }
+ break;
+ }
+
+ return null;
+ }
+
+
+
+
+
+
+ /**
+ * Called by channel (we registered before) when event is received. This is the UpHandler interface.
+ */
+ public Object up(Event evt) {
+ if(corr != null) {
+ if(!corr.receive(evt)) {
+ return handleUpEvent(evt);
+ }
+ }
+ else {
+ if(log.isErrorEnabled()) { //Something is seriously wrong, correlator should not be null since latch is not locked!
+ log.error("correlator is null, event will be ignored (evt=" + evt + ")");
+ }
+ }
+ return null;
+ }
+
+
+
+ public Object down(Event evt) {
+ if(channel != null) {
+ return channel.downcall(evt);
+ }
+ else
+ if(this.log.isWarnEnabled()) {
+ this.log.warn("channel is null, discarding event " + evt);
+ }
+ return null;
+ }
+
+
+ /* ----------------------- End of Protocol Interface ------------------------ */
+
+ }
+
+
+ class TransportAdapter implements Transport {
+
+ public void send(Message msg) throws Exception {
+ if(channel != null) {
+ channel.send(msg);
+ }
+ else
+ if(adapter != null) {
+ try {
+ if(id != null) {
+ adapter.send(id, msg);
+ }
+ else {
+ adapter.send(msg);
+ }
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) {
+ log.error("exception=" + Util.print(ex));
+ }
+ }
+ }
+ else {
+ if(log.isErrorEnabled()) {
+ log.error("channel == null");
+ }
+ }
+ }
+
+ public Object receive(long timeout) throws Exception {
+ return null; // not supported and not needed
+ }
+ }
+
+
+ class PullPushHandler implements ExtendedMessageListener, MembershipListener {
+
+
+ /* ------------------------- MessageListener interface ---------------------- */
+ public void receive(Message msg) {
+ boolean consumed=false;
+ if(corr != null) {
+ consumed=corr.receiveMessage(msg);
+ }
+
+ if(!consumed) { // pass on to MessageListener
+ if(msg_listener != null) {
+ msg_listener.receive(msg);
+ }
+ }
+ }
+
+ public byte[] getState() {
+ return msg_listener != null ? msg_listener.getState() : null;
+ }
+
+ public byte[] getState(String state_id) {
+ if(msg_listener == null) return null;
+ if(msg_listener instanceof ExtendedMessageListener && state_id!=null) {
+ return ((ExtendedMessageListener)msg_listener).getState(state_id);
+ }
+ else {
+ return msg_listener.getState();
+ }
+ }
+
+ public void setState(byte[] state) {
+ if(msg_listener != null) {
+ msg_listener.setState(state);
+ }
+ }
+
+ public void setState(String state_id, byte[] state) {
+ if(msg_listener != null) {
+ if(msg_listener instanceof ExtendedMessageListener && state_id!=null) {
+ ((ExtendedMessageListener)msg_listener).setState(state_id, state);
+ }
+ else {
+ msg_listener.setState(state);
+ }
+ }
+ }
+
+ public void getState(OutputStream ostream) {
+ if (msg_listener instanceof ExtendedMessageListener) {
+ ((ExtendedMessageListener) msg_listener).getState(ostream);
+ }
+ }
+
+ public void getState(String state_id, OutputStream ostream) {
+ if (msg_listener instanceof ExtendedMessageListener && state_id!=null) {
+ ((ExtendedMessageListener) msg_listener).getState(state_id,ostream);
+ }
+
+ }
+
+ public void setState(InputStream istream) {
+ if (msg_listener instanceof ExtendedMessageListener) {
+ ((ExtendedMessageListener) msg_listener).setState(istream);
+ }
+ }
+
+ public void setState(String state_id, InputStream istream) {
+ if (msg_listener instanceof ExtendedMessageListener && state_id != null) {
+ ((ExtendedMessageListener) msg_listener).setState(state_id,istream);
+ }
+ }
+ /*
+ * --------------------- End of MessageListener interface
+ * -------------------
+ */
+
+
+ /* ------------------------ MembershipListener interface -------------------- */
+ public void viewAccepted(View v) {
+ if(corr != null) {
+ corr.receiveView(v);
+ }
+
+ Vector new_mbrs=v.getMembers();
+ setMembers(new_mbrs);
+ if(membership_listener != null) {
+ membership_listener.viewAccepted(v);
+ }
+ }
+
+ public void suspect(Address suspected_mbr) {
+ if(corr != null) {
+ corr.receiveSuspect(suspected_mbr);
+ }
+ if(membership_listener != null) {
+ membership_listener.suspect(suspected_mbr);
+ }
+ }
+
+ public void block() {
+ if(membership_listener != null) {
+ membership_listener.block();
+ }
+ }
+
+ /* --------------------- End of MembershipListener interface ---------------- */
+
+
+
+ // @todo: receive SET_LOCAL_ADDR event and call corr.setLocalAddress(addr)
+
+ }
+
+
+}
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/MessageListenerAdapter.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/MessageListenerAdapter.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/MessageListenerAdapter.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,170 @@
+package org.jgroups.blocks;
+
+import org.jgroups.Message;
+import org.jgroups.MessageListener;
+import org.jgroups.ExtendedMessageListener;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashSet;
+
+/**
+ * This class provides multiplexing possibilities for {@link MessageListener}
+ * instances. Usually, we have more than one instance willing to listen to
+ * incoming messages, but only one that can produce state for group.
+ * {@link PullPushAdapter} allows only one instance of {@link MessageListener}
+ * to be registered for message notification. With help of this class you
+ * can overcome this limitation.
+ *
+ * @author Roman Rokytskyy (rrokytskyy@acm.org)
+ */
+public class MessageListenerAdapter implements ExtendedMessageListener {
+
+ protected MessageListener stateListener;
+
+ protected final HashSet messageListeners = new HashSet();
+
+ // we need this cache, because every call to messageListeners.iterator()
+ // would generate few new objects, but iteration over the cache would not.
+ protected MessageListener[] messageListenersCache = new MessageListener[0];
+
+ /**
+ * Create default instance of this class. Newly created instance will have
+ * no message or state listeners. You have to use
+ * {@link #addMessageListener(MessageListener)} or
+ * {@link #removeMessageListener(MessageListener)} to add or remove message
+ * listeners, and {@link #setStateListener(MessageListener)} to set listener
+ * that will participate in state transfer.
+ */
+ public MessageListenerAdapter() {
+ this(null);
+ }
+
+ /**
+ * Create instance of this class. mainListener
is a main
+ * listener instance that received message notifications and can get and
+ * set group state.
+ *
+ * @param mainListener instance of {@link MessageListener} that will
+ * provide state messages.
+ */
+ public MessageListenerAdapter(MessageListener mainListener) {
+ if (mainListener != null) {
+ stateListener = mainListener;
+ addMessageListener(mainListener);
+ }
+ }
+
+ /**
+ * Get state from state listener if present.
+ *
+ * @return current state of the group state or null
if no state
+ * listeners were registered.
+ */
+ public byte[] getState() {
+ if (stateListener != null)
+ return stateListener.getState();
+ else
+ return null;
+ }
+
+
+ public byte[] getState(String state_id) {
+ if(stateListener == null)
+ return null;
+ if(stateListener instanceof ExtendedMessageListener) {
+ return ((ExtendedMessageListener)stateListener).getState(state_id);
+ }
+ else {
+ return stateListener.getState();
+ }
+ }
+
+ public void getState(OutputStream ostream) {
+ if (stateListener instanceof ExtendedMessageListener) {
+ ((ExtendedMessageListener) stateListener).getState(ostream);
+ }
+ }
+
+ public void getState(String state_id, OutputStream ostream) {
+ if (stateListener instanceof ExtendedMessageListener && state_id!=null) {
+ ((ExtendedMessageListener) stateListener).getState(state_id,ostream);
+ }
+ }
+
+ /**
+ * Receive message from group. This method will send this message to each
+ * message listener that was registered in this adapter.
+ *
+ * @param msg message to distribute within message listeners.
+ */
+ public void receive(Message msg) {
+ for (int i = 0; i < messageListenersCache.length; i++)
+ messageListenersCache[i].receive(msg);
+ }
+
+ /**
+ * Set state of ths group. This method will delegate call to state listener
+ * if it was previously registered.
+ */
+ public void setState(byte[] state) {
+ if (stateListener != null)
+ stateListener.setState(state);
+ }
+
+ public void setState(String state_id, byte[] state) {
+ if(stateListener != null) {
+ if(stateListener instanceof ExtendedMessageListener) {
+ ((ExtendedMessageListener)stateListener).setState(state_id, state);
+ }
+ else {
+ stateListener.setState(state);
+ }
+ }
+ }
+
+
+ public void setState(InputStream istream) {
+ if (stateListener instanceof ExtendedMessageListener) {
+ ((ExtendedMessageListener) stateListener).setState(istream);
+ }
+ }
+
+ public void setState(String state_id, InputStream istream) {
+ if (stateListener instanceof ExtendedMessageListener && state_id != null) {
+ ((ExtendedMessageListener) stateListener).setState(state_id,istream);
+ }
+ }
+
+ /**
+ * Add message listener to this adapter. This method registers
+ * listener
for message notification.
+ *
+ * Note, state notification will not be used.
+ */
+ public final synchronized void addMessageListener(MessageListener listener) {
+ if (messageListeners.add(listener))
+ messageListenersCache =
+ (MessageListener[])messageListeners.toArray(
+ new MessageListener[messageListeners.size()]);
+ }
+
+ /**
+ * Remove message listener from this adapter. This method deregisters
+ * listener
from message notification.
+ */
+ public synchronized void removeMessageListener(MessageListener listener) {
+ if (messageListeners.remove(listener))
+ messageListenersCache =
+ (MessageListener[])messageListeners.toArray(
+ new MessageListener[messageListeners.size()]);
+ }
+
+ /**
+ * Register listener
for state notification events. There can
+ * be only one state listener per adapter.
+ */
+ public void setStateListener(MessageListener listener) {
+ stateListener = listener;
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/MethodCall.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/MethodCall.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/MethodCall.java 17 Aug 2012 14:51:17 -0000 1.1
@@ -0,0 +1,527 @@
+package org.jgroups.blocks;
+
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.*;
+
+
+/**
+ * A method call is the JGroups representation of a remote method.
+ * It includes the name of the method (case sensitive) and a list of arguments.
+ * A method call is serializable and can be passed over the wire.
+ * @author Bela Ban
+ * @version $Revision: 1.1 $
+ */
+public class MethodCall implements Externalizable {
+
+ private static final long serialVersionUID=7873471327078957662L;
+
+ /** The name of the method, case sensitive. */
+ protected String method_name;
+
+ /** The ID of a method, maps to a java.lang.reflect.Method */
+ protected short method_id=-1;
+
+ /** The arguments of the method. */
+ protected Object[] args;
+
+ /** The class types, e.g., new Class[]{String.class, int.class}. */
+ protected Class[] types;
+
+ /** The signature, e.g., new String[]{String.class.getName(), int.class.getName()}. */
+ protected String[] signature;
+
+ /** The Method of the call. */
+ protected Method method;
+
+ /** To carry arbitrary data with a method call, data needs to be serializable if sent across the wire */
+ protected Map payload;
+
+ protected static final Log log=LogFactory.getLog(MethodCall.class);
+
+ /** Which mode to use. */
+ protected short mode=OLD;
+
+ /** Infer the method from the arguments. */
+ protected static final short OLD=1;
+
+ /** Explicitly ship the method, caller has to determine method himself. */
+ protected static final short METHOD=2;
+
+ /** Use class information. */
+ protected static final short TYPES=3;
+
+ /** Provide a signature, similar to JMX. */
+ protected static final short SIGNATURE=4;
+
+ /** Use an ID to map to a method */
+ protected static final short ID=5;
+
+
+ /**
+ * Creates an empty method call, this is always invalid, until
+ * setName()
has been called.
+ */
+ public MethodCall() {
+ }
+
+
+ public MethodCall(Method method) {
+ this(method, null);
+ }
+
+ public MethodCall(Method method, Object[] arguments) {
+ init(method);
+ if(arguments != null) args=arguments;
+ }
+
+ /**
+ *
+ * @param method_name
+ * @param args
+ * @deprecated Use one of the constructors that take class types as arguments
+ */
+ public MethodCall(String method_name, Object[] args) {
+ this.method_name=method_name;
+ this.mode=OLD;
+ this.args=args;
+ }
+
+ public MethodCall(short method_id, Object[] args) {
+ this.method_id=method_id;
+ this.mode=ID;
+ this.args=args;
+ }
+
+
+ public MethodCall(String method_name, Object[] args, Class[] types) {
+ this.method_name=method_name;
+ this.args=args;
+ this.types=types;
+ this.mode=TYPES;
+ }
+
+ public MethodCall(String method_name, Object[] args, String[] signature) {
+ this.method_name=method_name;
+ this.args=args;
+ this.signature=signature;
+ this.mode=SIGNATURE;
+ }
+
+ private void init(Method method) {
+ this.method=method;
+ this.mode=METHOD;
+ method_name=method.getName();
+ }
+
+
+ public int getMode() {
+ return mode;
+ }
+
+
+
+ /**
+ * returns the name of the method to be invoked using this method call object
+ * @return a case sensitive name, can be null for an invalid method call
+ */
+ public String getName() {
+ return method_name;
+ }
+
+ /**
+ * sets the name for this MethodCall and allowing you to reuse the same object for
+ * a different method invokation of a different method
+ * @param n - a case sensitive method name
+ */
+ public void setName(String n) {
+ method_name=n;
+ }
+
+ public short getId() {
+ return method_id;
+ }
+
+ public void setId(short method_id) {
+ this.method_id=method_id;
+ }
+
+ /**
+ * returns an ordered list of arguments used for the method invokation
+ * @return returns the list of ordered arguments
+ */
+ public Object[] getArgs() {
+ return args;
+ }
+
+ public void setArgs(Object[] args) {
+ if(args != null)
+ this.args=args;
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+
+
+ public void setMethod(Method m) {
+ init(m);
+ }
+
+
+ public synchronized Object put(Object key, Object value) {
+ if(payload == null)
+ payload=new HashMap();
+ return payload.put(key, value);
+ }
+
+ public synchronized Object get(Object key) {
+ return payload != null? payload.get(key) : null;
+ }
+
+
+ /**
+ *
+ * @param target_class
+ * @return
+ * @throws Exception
+ */
+ Method findMethod(Class target_class) throws Exception {
+ int len=args != null? args.length : 0;
+ Method m;
+
+ Method[] methods=getAllMethods(target_class);
+ for(int i=0; i < methods.length; i++) {
+ m=methods[i];
+ if(m.getName().equals(method_name)) {
+ if(m.getParameterTypes().length == len)
+ return m;
+ }
+ }
+
+ return null;
+ }
+
+
+ /**
+ * The method walks up the class hierarchy and returns all methods of this class
+ * and those inherited from superclasses and superinterfaces.
+ */
+ Method[] getAllMethods(Class target) {
+ Class superclass = target;
+ List methods = new ArrayList();
+ int size = 0;
+
+ while(superclass != null) {
+ try {
+ Method[] m = superclass.getDeclaredMethods();
+ methods.add(m);
+ size += m.length;
+ superclass = superclass.getSuperclass();
+ }
+ catch(SecurityException e) {
+ // if it runs in an applet context, it won't be able to retrieve
+ // methods from superclasses that belong to the java VM and it will
+ // raise a security exception, so we catch it here.
+ if(log.isWarnEnabled())
+ log.warn("unable to enumerate methods of superclass "+superclass+" of class "+target);
+ superclass=null;
+ }
+ }
+
+ Method[] result = new Method[size];
+ int index = 0;
+ for(Iterator i = methods.iterator(); i.hasNext();) {
+ Method[] m = (Method[])i.next();
+ System.arraycopy(m, 0, result, index, m.length);
+ index += m.length;
+ }
+ return result;
+ }
+
+ /**
+ * Returns the first method that matches the specified name and parameter types. The overriding
+ * methods have priority. The method is chosen from all the methods of the current class and all
+ * its superclasses and superinterfaces.
+ *
+ * @return the matching method or null if no mathching method has been found.
+ */
+ Method getMethod(Class target, String methodName, Class[] types) {
+
+ if (types == null) {
+ types = new Class[0];
+ }
+
+ Method[] methods = getAllMethods(target);
+ methods: for(int i = 0; i < methods.length; i++) {
+ Method m = methods[i];
+ if (!methodName.equals(m.getName())) {
+ continue;
+ }
+ Class[] parameters = m.getParameterTypes();
+ if (types.length != parameters.length) {
+ continue;
+ }
+ for(int j = 0; j < types.length; j++) {
+ if(!parameters[j].isAssignableFrom(types[j])) {
+ // if (!types[j].equals(parameters[j])) {
+ continue methods;
+ }
+ }
+ return m;
+ }
+ return null;
+ }
+
+
+ /**
+ * Invokes the method with the supplied arguments against the target object.
+ * If a method lookup is provided, it will be used. Otherwise, the default
+ * method lookup will be used.
+ * @param target - the object that you want to invoke the method on
+ * @return an object
+ */
+ public Object invoke(Object target) throws Throwable {
+ Class cl;
+ Method meth=null;
+ Object retval=null;
+
+
+ if(method_name == null || target == null) {
+ if(log.isErrorEnabled()) log.error("method name or target is null");
+ return null;
+ }
+ cl=target.getClass();
+ try {
+ switch(mode) {
+ case OLD:
+ meth=findMethod(cl);
+ break;
+ case METHOD:
+ if(this.method != null)
+ meth=this.method;
+ break;
+ case TYPES:
+ //meth=cl.getDeclaredMethod(method_name, types);
+ meth = getMethod(cl, method_name, types);
+ break;
+ case SIGNATURE:
+ Class[] mytypes=null;
+ if(signature != null)
+ mytypes=getTypesFromString(cl, signature);
+ //meth=cl.getDeclaredMethod(method_name, mytypes);
+ meth = getMethod(cl, method_name, mytypes);
+ break;
+ case ID:
+ break;
+ default:
+ if(log.isErrorEnabled()) log.error("mode " + mode + " is invalid");
+ break;
+ }
+
+ if(meth != null) {
+ retval=meth.invoke(target, args);
+ }
+ else {
+ throw new NoSuchMethodException(method_name);
+ }
+ return retval;
+ }
+ catch(InvocationTargetException inv_ex) {
+ throw inv_ex.getTargetException();
+ }
+ catch(NoSuchMethodException no) {
+ StringBuilder sb=new StringBuilder();
+ sb.append("found no method called ").append(method_name).append(" in class ");
+ sb.append(cl.getName()).append(" with (");
+ if(args != null) {
+ for(int i=0; i < args.length; i++) {
+ if(i > 0)
+ sb.append(", ");
+ sb.append((args[i] != null)? args[i].getClass().getName() : "null");
+ }
+ }
+ sb.append(") formal parameters");
+ log.error(sb.toString());
+ throw no;
+ }
+ catch(Throwable e) {
+ // e.printStackTrace(System.err);
+ if(log.isErrorEnabled()) log.error("exception in invoke()", e);
+ throw e;
+ }
+ }
+
+ public Object invoke(Object target, Object[] args) throws Throwable {
+ if(args != null)
+ this.args=args;
+ return invoke(target);
+ }
+
+
+ Class[] getTypesFromString(Class cl, String[] signature) throws Exception {
+ String name;
+ Class parameter;
+ Class[] mytypes=new Class[signature.length];
+
+ for(int i=0; i < signature.length; i++) {
+ name=signature[i];
+ if("long".equals(name))
+ parameter=long.class;
+ else if("int".equals(name))
+ parameter=int.class;
+ else if("short".equals(name))
+ parameter=short.class;
+ else if("char".equals(name))
+ parameter=char.class;
+ else if("byte".equals(name))
+ parameter=byte.class;
+ else if("float".equals(name))
+ parameter=float.class;
+ else if("double".equals(name))
+ parameter=double.class;
+ else if("boolean".equals(name))
+ parameter=boolean.class;
+ else
+ parameter=Class.forName(name, false, cl.getClassLoader());
+ mytypes[i]=parameter;
+ }
+ return mytypes;
+ }
+
+
+ public String toString() {
+ StringBuilder ret=new StringBuilder();
+ boolean first=true;
+ if(method_name != null)
+ ret.append(method_name);
+ else
+ ret.append(method_id);
+ ret.append('(');
+ if(args != null) {
+ for(int i=0; i < args.length; i++) {
+ if(first)
+ first=false;
+ else
+ ret.append(", ");
+ ret.append(args[i]);
+ }
+ }
+ ret.append(')');
+ return ret.toString();
+ }
+
+ public String toStringDetails() {
+ StringBuilder ret=new StringBuilder();
+ ret.append("MethodCall ");
+ if(method_name != null)
+ ret.append("name=").append(method_name);
+ else
+ ret.append("id=").append(method_id);
+ ret.append(", number of args=").append((args != null? args.length : 0)).append(')');
+ if(args != null) {
+ ret.append("\nArgs:");
+ for(int i=0; i < args.length; i++) {
+ ret.append("\n[").append(args[i]).append(" (").
+ append((args[i] != null? args[i].getClass().getName() : "null")).append(")]");
+ }
+ }
+ return ret.toString();
+ }
+
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ if(method_name != null) {
+ out.writeBoolean(true);
+ out.writeUTF(method_name);
+ }
+ else {
+ out.writeBoolean(false);
+ out.writeShort(method_id);
+ }
+ out.writeObject(args);
+ out.writeShort(mode);
+
+ switch(mode) {
+ case OLD:
+ break;
+ case METHOD:
+ out.writeObject(method.getParameterTypes());
+ out.writeObject(method.getDeclaringClass());
+ break;
+ case TYPES:
+ out.writeObject(types);
+ break;
+ case SIGNATURE:
+ out.writeObject(signature);
+ break;
+ case ID:
+ break;
+ default:
+ if(log.isErrorEnabled()) log.error("mode " + mode + " is invalid");
+ break;
+ }
+
+ if(payload != null) {
+ out.writeBoolean(true);
+ out.writeObject(payload);
+ }
+ else {
+ out.writeBoolean(false);
+ }
+ }
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ boolean name_available=in.readBoolean();
+ if(name_available)
+ method_name=in.readUTF();
+ else
+ method_id=in.readShort();
+ args=(Object[])in.readObject();
+ mode=in.readShort();
+
+ switch(mode) {
+ case OLD:
+ break;
+ case METHOD:
+ Class[] parametertypes=(Class[])in.readObject();
+ Class declaringclass=(Class)in.readObject();
+ try {
+ method=declaringclass.getDeclaredMethod(method_name, parametertypes);
+ }
+ catch(NoSuchMethodException e) {
+ throw new IOException(e.toString());
+ }
+ break;
+ case TYPES:
+ types=(Class[])in.readObject();
+ break;
+ case SIGNATURE:
+ signature=(String[])in.readObject();
+ break;
+ case ID:
+ break;
+ default:
+ if(log.isErrorEnabled()) log.error("mode " + mode + " is invalid");
+ break;
+ }
+
+ boolean payload_available=in.readBoolean();
+ if(payload_available) {
+ payload=(Map)in.readObject();
+ }
+ }
+
+
+}
+
+
+
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/MethodLookup.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/MethodLookup.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/MethodLookup.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,11 @@
+package org.jgroups.blocks;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author Bela Ban
+ * @version $Id: MethodLookup.java,v 1.1 2012/08/17 14:51:18 marcin Exp $
+ */
+public interface MethodLookup {
+ Method findMethod(short id);
+}
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/NBMessageForm_NIO.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/NBMessageForm_NIO.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/NBMessageForm_NIO.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,90 @@
+// $Id: NBMessageForm_NIO.java,v 1.1 2012/08/17 14:51:18 marcin Exp $
+
+package org.jgroups.blocks;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+
+/**
+ * NBMessageForm - Message form for non-blocking message reads.
+ * @author akbollu
+ * @author Bela Ban
+ */
+public class NBMessageForm_NIO
+{
+ ByteBuffer headerBuffer = null;
+ ByteBuffer dataBuffer = null;
+ static final int HEADER_SIZE = 4;
+ final boolean isComplete = false;
+ int messageSize = 0;
+ boolean w_in_p = false;
+ SocketChannel channel = null;
+
+
+
+ public NBMessageForm_NIO(int dataBuffSize, SocketChannel ch)
+ {
+ headerBuffer = ByteBuffer.allocate(HEADER_SIZE);
+ dataBuffer = ByteBuffer.allocate(dataBuffSize);
+ channel = ch;
+ }
+
+
+
+ public ByteBuffer readCompleteMsgBuffer() throws IOException
+ {
+
+ int rt;
+
+ try {
+ rt = channel.read(headerBuffer);
+ if ( (rt == 0) || (rt == -1) )
+ {
+ channel.close();
+ return null;
+ }
+ if (rt == HEADER_SIZE)
+ {
+ headerBuffer.flip();
+ messageSize = headerBuffer.getInt();
+ if(dataBuffer.capacity() < messageSize)
+ {
+ dataBuffer = ByteBuffer.allocate(messageSize);
+ }
+ }
+ else {
+ return null;
+ }
+ }
+ catch(IOException ex) {
+ channel.close();
+ throw ex;
+ }
+
+
+ //rt == 0 need not be checked twice in the same event
+ channel.read(dataBuffer);
+ if(isComplete())
+ {
+ dataBuffer.flip();
+ return dataBuffer;
+ }
+ return null;
+ }
+
+
+
+ public void reset()
+ {
+ dataBuffer.clear();
+ headerBuffer.clear();
+ messageSize = 0;
+ w_in_p = false;
+ }
+
+ private boolean isComplete()
+ {
+ return ( dataBuffer.position() == messageSize );
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/NotificationBus.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/NotificationBus.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/NotificationBus.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,449 @@
+// $Id: NotificationBus.java,v 1.1 2012/08/17 14:51:18 marcin Exp $
+
+package org.jgroups.blocks;
+
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jgroups.*;
+import org.jgroups.util.Promise;
+import org.jgroups.util.Util;
+
+import java.io.Serializable;
+import java.util.Vector;
+
+
+/**
+ * This class provides notification sending and handling capability.
+ * Producers can send notifications to all registered consumers.
+ * Provides hooks to implement shared group state, which allows an
+ * application programmer to maintain a local cache which is replicated
+ * by all instances. NotificationBus sits on
+ * top of a channel, however it creates its channel itself, so the
+ * application programmers do not have to provide their own channel.
+ *
+ * @author Bela Ban
+ */
+public class NotificationBus implements Receiver {
+ final Vector members=new Vector();
+ Channel channel=null;
+ Address local_addr=null;
+ Consumer consumer=null; // only a single consumer allowed
+ String bus_name="notification_bus";
+ final Promise get_cache_promise=new Promise();
+ final Object cache_mutex=new Object();
+
+ protected final Log log=LogFactory.getLog(getClass());
+
+
+ String props=null;
+
+
+ public interface Consumer {
+ void handleNotification(Serializable n);
+
+ /** Called on the coordinator to obtains its cache */
+ Serializable getCache();
+
+ void memberJoined(Address mbr);
+
+ void memberLeft(Address mbr);
+ }
+
+
+ public NotificationBus() throws Exception {
+ this((Channel)null, null);
+ }
+
+
+ public NotificationBus(String bus_name) throws Exception {
+ this(bus_name, null);
+ }
+
+
+ public NotificationBus(String bus_name, String properties) throws Exception {
+ if(bus_name != null) this.bus_name=bus_name;
+ if(properties != null) props=properties;
+ channel=new JChannel(props);
+ channel.setReceiver(this);
+ }
+
+ public NotificationBus(Channel channel, String bus_name) throws Exception {
+ if(bus_name != null) this.bus_name=bus_name;
+ this.channel=channel;
+ if(channel != null)
+ channel.setReceiver(this);
+ }
+
+
+ public void setConsumer(Consumer c) {
+ consumer=c;
+ }
+
+
+ public Address getLocalAddress() {
+ if(local_addr != null) return local_addr;
+ if(channel != null)
+ local_addr=channel.getLocalAddress();
+ return local_addr;
+ }
+
+
+ /**
+ * Returns a reference to the real membership: don't modify.
+ * If you need to modify, make a copy first !
+ * @return Vector of Address objects
+ */
+ public Vector getMembership() {
+ return members;
+ }
+
+
+ /**
+ * Answers the Channel.
+ * Used to operate on the underlying channel directly, e.g. perform operations that are not
+ * provided using only NotificationBus. Should be used sparingly.
+ * @return underlying Channel
+ */
+ public Channel getChannel() {
+ return channel;
+ }
+
+
+ public boolean isCoordinator() {
+ Object first_mbr=null;
+
+ synchronized(members) {
+ first_mbr=!members.isEmpty()? members.elementAt(0) : null;
+ if(first_mbr == null)
+ return true;
+ }
+ return getLocalAddress() != null && getLocalAddress().equals(first_mbr);
+ }
+
+
+ public void start() throws Exception {
+ channel.connect(bus_name);
+ }
+
+
+ public void stop() {
+ if(channel != null) {
+ channel.close(); // disconnects from channel and closes it
+ channel=null;
+ }
+ }
+
+
+ /** Pack the argument in a Info, serialize that one into the message buffer and send the message */
+ public void sendNotification(Serializable n) {
+ sendNotification(null, n);
+ }
+
+ /** Pack the argument in a Info, serialize that one into the message buffer and send the message */
+ public void sendNotification(Address dest, Serializable n) {
+ Message msg=null;
+ byte[] data=null;
+ Info info;
+
+ try {
+ if(n == null) return;
+ info=new Info(Info.NOTIFICATION, n);
+ data=Util.objectToByteBuffer(info);
+ msg=new Message(dest, null, data);
+ if(channel == null) {
+ if(log.isErrorEnabled()) log.error("channel is null. Won't send notification");
+ return;
+ }
+ channel.send(msg);
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) log.error("error sending notification", ex);
+ }
+ }
+
+
+ /**
+ Determines the coordinator and asks it for its cache. If there is no coordinator (because we are first member),
+ null will be returned. Used only internally by NotificationBus.
+ @param timeout Max number of msecs until the call returns
+ @param max_tries Max number of attempts to fetch the cache from the coordinator
+ */
+ public Serializable getCacheFromCoordinator(long timeout, int max_tries) {
+ return getCacheFromMember(null, timeout, max_tries);
+ }
+
+
+ /**
+ Determines the coordinator and asks it for its cache. If there is no coordinator (because we are first member),
+ null will be returned. Used only internally by NotificationBus.
+ @param mbr The address of the member from which to fetch the state. If null, the current coordinator
+ will be asked for the state
+ @param timeout Max number of msecs until the call returns - if timeout elapses
+ null will be returned
+ @param max_tries Max number of attempts to fetch the cache from the coordinator (will be set to 1 if < 1)
+ */
+ public Serializable getCacheFromMember(Address mbr, long timeout, int max_tries) {
+ Serializable cache=null;
+ int num_tries=0;
+ Info info;
+ Message msg;
+ Address dst=mbr; // member from which to fetch the cache
+
+ long start, stop; // +++ remove
+
+
+ if(max_tries < 1) max_tries=1;
+
+ get_cache_promise.reset();
+ while(num_tries <= max_tries) {
+ if(mbr == null) { // mbr == null means get cache from coordinator
+ dst=determineCoordinator();
+ if(dst == null || dst.equals(getLocalAddress())) { // we are the first member --> empty cache
+ if(log.isInfoEnabled()) log.info("[" + getLocalAddress() +
+ "] no coordinator found --> first member (cache is empty)");
+ return null;
+ }
+ }
+
+ // +++ remove
+ if(log.isInfoEnabled()) log.info("[" + getLocalAddress() + "] dst=" + dst +
+ ", timeout=" + timeout + ", max_tries=" + max_tries + ", num_tries=" + num_tries);
+
+ info=new Info(Info.GET_CACHE_REQ);
+ msg=new Message(dst, null, info);
+ try {
+ channel.send(msg);
+ }
+ catch(Exception e) {
+ log.error("failed sending message", e);
+ return null;
+ }
+
+ start=System.currentTimeMillis();
+ cache=get_cache_promise.getResult(timeout);
+ stop=System.currentTimeMillis();
+ if(cache != null) {
+ if(log.isInfoEnabled()) log.info("got cache from " +
+ dst + ": cache is valid (waited " + (stop - start) + " msecs on get_cache_promise)");
+ return cache;
+ }
+ else {
+ if(log.isErrorEnabled()) log.error("received null cache; retrying (waited " +
+ (stop - start) + " msecs on get_cache_promise)");
+ }
+
+ Util.sleep(500);
+ ++num_tries;
+ }
+ if(cache == null)
+ if(log.isErrorEnabled()) log.error("[" + getLocalAddress() +
+ "] cache is null (num_tries=" + num_tries + ')');
+ return cache;
+ }
+
+
+ /**
+ Don't multicast this to all members, just apply it to local consumers.
+ */
+ public void notifyConsumer(Serializable n) {
+ if(consumer != null && n != null)
+ consumer.handleNotification(n);
+ }
+
+
+ /* -------------------------------- Interface MessageListener -------------------------------- */
+ public void receive(Message msg) {
+ Info info=null;
+ Object obj;
+
+ if(msg == null || msg.getLength() == 0) return;
+ try {
+ obj=msg.getObject();
+ if(!(obj instanceof Info)) {
+ if(log.isErrorEnabled()) log.error("expected an instance of Info (received " +
+ obj.getClass().getName() + ')');
+ return;
+ }
+ info=(Info) obj;
+ switch(info.type) {
+ case Info.NOTIFICATION:
+ notifyConsumer(info.data);
+ break;
+
+ case Info.GET_CACHE_REQ:
+ handleCacheRequest(msg.getSrc());
+ break;
+
+ case Info.GET_CACHE_RSP:
+ // +++ remove
+ if(log.isDebugEnabled()) log.debug("[GET_CACHE_RSP] cache was received from " + msg.getSrc());
+ get_cache_promise.setResult(info.data);
+ break;
+
+ default:
+ if(log.isErrorEnabled()) log.error("type " + info.type + " unknown");
+ break;
+ }
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) log.error("exception=" + ex);
+ }
+ }
+
+ public byte[] getState() {
+ return null;
+ }
+
+ public void setState(byte[] state) {
+ }
+
+ /* ----------------------------- End of Interface MessageListener ---------------------------- */
+
+
+
+
+ /* ------------------------------- Interface MembershipListener ------------------------------ */
+
+ public synchronized void viewAccepted(View new_view) {
+ Vector joined_mbrs, left_mbrs, tmp;
+ Object tmp_mbr;
+
+ if(new_view == null) return;
+ tmp=new_view.getMembers();
+
+ synchronized(members) {
+ // get new members
+ joined_mbrs=new Vector();
+ for(int i=0; i < tmp.size(); i++) {
+ tmp_mbr=tmp.elementAt(i);
+ if(!members.contains(tmp_mbr))
+ joined_mbrs.addElement(tmp_mbr);
+ }
+
+ // get members that left
+ left_mbrs=new Vector();
+ for(int i=0; i < members.size(); i++) {
+ tmp_mbr=members.elementAt(i);
+ if(!tmp.contains(tmp_mbr))
+ left_mbrs.addElement(tmp_mbr);
+ }
+
+ // adjust our own membership
+ members.removeAllElements();
+ members.addAll(tmp);
+ }
+
+ if(consumer != null) {
+ if(!joined_mbrs.isEmpty())
+ for(int i=0; i < joined_mbrs.size(); i++)
+ consumer.memberJoined((Address) joined_mbrs.elementAt(i));
+ if(!left_mbrs.isEmpty())
+ for(int i=0; i < left_mbrs.size(); i++)
+ consumer.memberLeft((Address) left_mbrs.elementAt(i));
+ }
+ }
+
+
+ public void suspect(Address suspected_mbr) {
+ }
+
+ public void block() {
+ }
+
+
+ /* ----------------------------- End of Interface MembershipListener ------------------------- */
+
+
+
+
+
+
+
+ /* ------------------------------------- Private Methods ------------------------------------- */
+
+ Address determineCoordinator() {
+ Vector v=channel != null ? channel.getView().getMembers() : null;
+ return v != null ? (Address) v.elementAt(0) : null;
+ }
+
+
+ void handleCacheRequest(Address sender) throws ChannelException {
+ Serializable cache=null;
+ Message msg;
+ Info info;
+
+ if(sender == null) {
+ // +++ remove
+ //
+ if(log.isErrorEnabled()) log.error("sender is null");
+ return;
+ }
+
+ synchronized(cache_mutex) {
+ cache=getCache(); // get the cache from the consumer
+ info=new Info(Info.GET_CACHE_RSP, cache);
+ msg=new Message(sender, null, info);
+ if(log.isInfoEnabled()) log.info("[" + getLocalAddress() + "] returning cache to " + sender);
+ channel.send(msg);
+ }
+ }
+
+ public Serializable getCache() {
+ return consumer != null ? consumer.getCache() : null;
+ }
+
+
+
+ /* --------------------------------- End of Private Methods ---------------------------------- */
+
+
+
+
+
+ private static class Info implements Serializable {
+ public final static int NOTIFICATION=1;
+ public final static int GET_CACHE_REQ=2;
+ public final static int GET_CACHE_RSP=3;
+
+
+ int type=0;
+ Serializable data=null; // if type == NOTIFICATION data is notification, if type == GET_CACHE_RSP, data is cache
+ private static final long serialVersionUID = -7198723001828406107L;
+
+
+ public Info(int type) {
+ this.type=type;
+ }
+
+ public Info(int type, Serializable data) {
+ this.type=type;
+ this.data=data;
+ }
+
+
+ public String toString() {
+ StringBuilder sb=new StringBuilder();
+ sb.append("type= ");
+ if(type == NOTIFICATION)
+ sb.append("NOTIFICATION");
+ else if(type == GET_CACHE_REQ)
+ sb.append("GET_CACHE_REQ");
+ else if(type == GET_CACHE_RSP)
+ sb.append("GET_CACHE_RSP");
+ else
+ sb.append("");
+ if(data != null) {
+ if(type == NOTIFICATION)
+ sb.append(", notification=" + data);
+ else if(type == GET_CACHE_RSP) sb.append(", cache=" + data);
+ }
+ return sb.toString();
+ }
+ }
+
+
+}
+
+
+
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/PullPushAdapter.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/PullPushAdapter.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/PullPushAdapter.java 17 Aug 2012 14:51:19 -0000 1.1
@@ -0,0 +1,480 @@
+// $Id: PullPushAdapter.java,v 1.1 2012/08/17 14:51:19 marcin Exp $
+
+package org.jgroups.blocks;
+
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jgroups.*;
+import org.jgroups.util.Util;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+
+/**
+ * Allows a client of {@link org.jgroups.Channel} to be notified when messages have been received
+ * instead of having to actively poll the channel for new messages. Typically used in the
+ * client role (receive()). As this class does not implement interface
+ * {@link org.jgroups.Transport}, but uses it for receiving messages, an underlying object
+ * has to be used to send messages (e.g. the channel on which an object of this class relies).
+ * Multiple MembershipListeners can register with the PullPushAdapter; when a view is received, they
+ * will all be notified. There is one main message listener which sends and receives message. In addition,
+ * MessageListeners can register with a certain tag (identifier), and then send messages tagged with this
+ * identifier. When a message with such an identifier is received, the corresponding MessageListener will be
+ * looked up and the message dispatched to it. If no tag is found (default), the main MessageListener will
+ * receive the message.
+ * @author Bela Ban
+ * @version $Revision
+ * @deprecated Use {@link org.jgroups.Receiver} instead, this class will be removed in JGroups 3.0
+ */
+public class PullPushAdapter implements Runnable, ChannelListener {
+ protected Transport transport=null;
+ protected MessageListener listener=null; // main message receiver
+ protected final List membership_listeners=new ArrayList();
+ protected Thread receiver_thread=null;
+ protected final HashMap listeners=new HashMap(); // keys=identifier (Serializable), values=MessageListeners
+ protected final Log log=LogFactory.getLog(getClass());
+ static final String PULL_HEADER="PULL_HEADER";
+
+
+ public PullPushAdapter(Transport transport) {
+ this.transport=transport;
+ start();
+ }
+
+ public PullPushAdapter(Transport transport, MessageListener l) {
+ this.transport=transport;
+ setListener(l);
+ start();
+ }
+
+
+ public PullPushAdapter(Transport transport, MembershipListener ml) {
+ this.transport=transport;
+ addMembershipListener(ml);
+ start();
+ }
+
+
+ public PullPushAdapter(Transport transport, MessageListener l, MembershipListener ml) {
+ this.transport=transport;
+ setListener(l);
+ addMembershipListener(ml);
+ start();
+ }
+
+
+ public PullPushAdapter(Transport transport, MessageListener l, MembershipListener ml, boolean start) {
+ this.transport=transport;
+ setListener(l);
+ addMembershipListener(ml);
+ if(start)
+ start();
+ }
+
+
+
+ public Transport getTransport() {
+ return transport;
+ }
+
+
+ public final void start() {
+ if(receiver_thread == null || !receiver_thread.isAlive()) {
+ receiver_thread=new Thread(this, "PullPushAdapterThread");
+ receiver_thread.setDaemon(true);
+ receiver_thread.start();
+ }
+ if(transport instanceof JChannel)
+ ((JChannel)transport).addChannelListener(this);
+ }
+
+ public void stop() {
+ Thread tmp=null;
+ if(receiver_thread != null && receiver_thread.isAlive()) {
+ tmp=receiver_thread;
+ receiver_thread=null;
+ tmp.interrupt();
+ try {
+ tmp.join(1000);
+ }
+ catch(Exception ex) {
+ }
+ }
+ receiver_thread=null;
+ }
+
+ /**
+ * Sends a message to the group - listeners to this identifier will receive the messages.
+ * @param identifier the key that the proper listeners are listenting on
+ * @param msg the Message to be sent
+ * @see #registerListener
+ */
+ public void send(Serializable identifier, Message msg) throws Exception {
+ if(msg == null) {
+ if(log.isErrorEnabled()) log.error("msg is null");
+ return;
+ }
+ if(identifier == null)
+ transport.send(msg);
+ else {
+ msg.putHeader(PULL_HEADER, new PullHeader(identifier));
+ transport.send(msg);
+ }
+ }
+
+ /**
+ * Sends a message with no identifier; listener member will get this message on the other group members.
+ * @param msg the Message to be sent
+ * @throws Exception
+ */
+ public void send(Message msg) throws Exception {
+ send(null, msg);
+ }
+
+
+ public final void setListener(MessageListener l) {
+ listener=l;
+ }
+
+
+
+ /**
+ * Sets a listener to messages with a given identifier.
+ * Messages sent with this identifier in their headers will be routed to this listener.
+ * Note: there can be only one listener for one identifier;
+ * if you want to register a different listener to an already registered identifier, then unregister first.
+ * @param identifier - messages sent on the group with this object will be received by this listener
+ * @param l - the listener that will get the message
+ */
+ public void registerListener(Serializable identifier, MessageListener l) {
+ if(l == null || identifier == null) {
+ if(log.isErrorEnabled()) log.error("message listener or identifier is null");
+ return;
+ }
+ if(listeners.containsKey(identifier)) {
+ if(log.isErrorEnabled()) log.error("listener with identifier=" + identifier +
+ " already exists, choose a different identifier or unregister current listener");
+ // we do not want to overwrite the listener
+ return;
+ }
+ listeners.put(identifier, l);
+ }
+
+ /**
+ * Removes a message listener to a given identifier from the message listeners map.
+ * @param identifier - the key to whom we do not want to listen any more
+ */
+ public void unregisterListener(Serializable identifier) {
+ listeners.remove(identifier);
+ }
+
+
+ /** @deprecated Use {@link #addMembershipListener} */
+ public void setMembershipListener(MembershipListener ml) {
+ addMembershipListener(ml);
+ }
+
+ public final void addMembershipListener(MembershipListener l) {
+ if(l != null && !membership_listeners.contains(l))
+ membership_listeners.add(l);
+ }
+
+ public void removeMembershipListener(MembershipListener l) {
+ if(l != null && membership_listeners.contains(l))
+ membership_listeners.remove(l);
+ }
+
+
+ /**
+ * Reentrant run(): message reception is serialized, then the listener is notified of the
+ * message reception
+ */
+ public void run() {
+ Object obj;
+
+ while(receiver_thread != null && Thread.currentThread().equals(receiver_thread)) {
+ try {
+ obj=transport.receive(0);
+ if(obj == null)
+ continue;
+
+ if(obj instanceof Message) {
+ handleMessage((Message)obj);
+ }
+ else if(obj instanceof GetStateEvent) {
+ byte[] retval=null;
+ GetStateEvent evt=(GetStateEvent)obj;
+ String state_id=evt.getStateId();
+ if(listener != null) {
+ try {
+ if(listener instanceof ExtendedMessageListener && state_id!=null) {
+ retval=((ExtendedMessageListener)listener).getState(state_id);
+ }
+ else {
+ retval=listener.getState();
+ }
+ }
+ catch(Throwable t) {
+ log.error("getState() from application failed, will return empty state", t);
+ }
+ }
+ else {
+ log.warn("no listener registered, returning empty state");
+ }
+
+ if(transport instanceof Channel) {
+ ((Channel)transport).returnState(retval, state_id);
+ }
+ else {
+ if(log.isErrorEnabled())
+ log.error("underlying transport is not a Channel, but a " +
+ transport.getClass().getName() + ": cannot return state using returnState()");
+ }
+ }
+ else if(obj instanceof SetStateEvent) {
+ SetStateEvent evt=(SetStateEvent)obj;
+ String state_id=evt.getStateId();
+ if(listener != null) {
+ try {
+ if(listener instanceof ExtendedMessageListener && state_id!=null) {
+ ((ExtendedMessageListener)listener).setState(state_id, evt.getArg());
+ }
+ else {
+ listener.setState(evt.getArg());
+ }
+ }
+ catch(ClassCastException cast_ex) {
+ if(log.isErrorEnabled()) log.error("received SetStateEvent, but argument " +
+ ((SetStateEvent)obj).getArg() + " is not serializable ! Discarding message.");
+ }
+ }
+ }
+ else if(obj instanceof StreamingGetStateEvent) {
+ StreamingGetStateEvent evt=(StreamingGetStateEvent)obj;
+ if(listener instanceof ExtendedMessageListener)
+ {
+ if(evt.getStateId()==null)
+ {
+ ((ExtendedMessageListener)listener).getState(evt.getArg());
+ }
+ else
+ {
+ ((ExtendedMessageListener)listener).getState(evt.getStateId(),evt.getArg());
+ }
+ }
+ }
+ else if(obj instanceof StreamingSetStateEvent) {
+ StreamingSetStateEvent evt=(StreamingSetStateEvent)obj;
+ if(listener instanceof ExtendedMessageListener)
+ {
+ if(evt.getStateId()==null)
+ {
+ ((ExtendedMessageListener)listener).setState(evt.getArg());
+ }
+ else
+ {
+ ((ExtendedMessageListener)listener).setState(evt.getStateId(),evt.getArg());
+ }
+ }
+ }
+ else if(obj instanceof View) {
+ notifyViewChange((View)obj);
+ }
+ else if(obj instanceof SuspectEvent) {
+ notifySuspect((Address)((SuspectEvent)obj).getMember());
+ }
+ else if(obj instanceof BlockEvent) {
+ notifyBlock();
+ if(transport instanceof Channel) {
+ ((Channel)transport).blockOk();
+ }
+ }
+ else if(obj instanceof UnblockEvent) {
+ notifyUnblock();
+ }
+ }
+ catch(ChannelNotConnectedException conn) {
+ Address local_addr=((Channel)transport).getLocalAddress();
+ if(log.isTraceEnabled()) log.trace('[' + (local_addr == null ? "" : local_addr.toString()) +
+ "] channel not connected, exception is " + conn);
+ Util.sleep(1000);
+ receiver_thread=null;
+ break;
+ }
+ catch(ChannelClosedException closed_ex) {
+ Address local_addr=((Channel)transport).getLocalAddress();
+ if(log.isTraceEnabled()) log.trace('[' + (local_addr == null ? "" : local_addr.toString()) +
+ "] channel closed, exception is " + closed_ex);
+ // Util.sleep(1000);
+ receiver_thread=null;
+ break;
+ }
+ catch(Throwable e) {
+ }
+ }
+ }
+
+
+ /**
+ * Check whether the message has an identifier. If yes, lookup the MessageListener associated with the
+ * given identifier in the hashtable and dispatch to it. Otherwise just use the main (default) message
+ * listener
+ */
+ protected void handleMessage(Message msg) {
+ PullHeader hdr=(PullHeader)msg.getHeader(PULL_HEADER);
+ Serializable identifier;
+ MessageListener l;
+
+ if(hdr != null && (identifier=hdr.getIdentifier()) != null) {
+ l=(MessageListener)listeners.get(identifier);
+ if(l == null) {
+ if(log.isErrorEnabled()) log.error("received a messages tagged with identifier=" +
+ identifier + ", but there is no registration for that identifier. Will drop message");
+ }
+ else
+ l.receive(msg);
+ }
+ else {
+ if(listener != null)
+ listener.receive(msg);
+ }
+ }
+
+
+ protected void notifyViewChange(View v) {
+ MembershipListener l;
+
+ if(v == null) return;
+ for(Iterator it=membership_listeners.iterator(); it.hasNext();) {
+ l=(MembershipListener)it.next();
+ try {
+ l.viewAccepted(v);
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) log.error("exception notifying " + l + " of view(" + v + ")", ex);
+ }
+ }
+ }
+
+ protected void notifySuspect(Address suspected_mbr) {
+ MembershipListener l;
+
+ if(suspected_mbr == null) return;
+ for(Iterator it=membership_listeners.iterator(); it.hasNext();) {
+ l=(MembershipListener)it.next();
+ try {
+ l.suspect(suspected_mbr);
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) log.error("exception notifying " + l + " of suspect(" + suspected_mbr + ")", ex);
+ }
+ }
+ }
+
+ protected void notifyBlock() {
+ MembershipListener l;
+
+ for(Iterator it=membership_listeners.iterator(); it.hasNext();) {
+ l=(MembershipListener)it.next();
+ try {
+ l.block();
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) log.error("exception notifying " + l + " of block()", ex);
+ }
+ }
+ }
+
+ protected void notifyUnblock() {
+ MembershipListener l;
+
+ for(Iterator it=membership_listeners.iterator(); it.hasNext();) {
+ l=(MembershipListener)it.next();
+ if(l instanceof ExtendedMembershipListener){
+ try {
+ ((ExtendedMembershipListener)l).unblock();
+ }
+ catch(Throwable ex) {
+ if(log.isErrorEnabled()) log.error("exception notifying " + l + " of unblock()", ex);
+ }
+ }
+ }
+ }
+
+ public void channelConnected(Channel channel) {
+ if(log.isTraceEnabled())
+ log.trace("channel is connected");
+ }
+
+ public void channelDisconnected(Channel channel) {
+ if(log.isTraceEnabled())
+ log.trace("channel is disconnected");
+ }
+
+ public void channelClosed(Channel channel) {
+ }
+
+ public void channelShunned() {
+ if(log.isTraceEnabled())
+ log.trace("channel is shunned");
+ }
+
+ public void channelReconnected(Address addr) {
+ start();
+ }
+
+
+
+
+ public static final class PullHeader extends Header {
+ Serializable identifier=null;
+
+ public PullHeader() {
+ ; // used by externalization
+ }
+
+ public PullHeader(Serializable identifier) {
+ this.identifier=identifier;
+ }
+
+ public Serializable getIdentifier() {
+ return identifier;
+ }
+
+ public int size() {
+ if(identifier == null)
+ return 12;
+ else
+ return 64;
+ }
+
+
+ public String toString() {
+ return "PullHeader";
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject(identifier);
+ }
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ identifier=(Serializable)in.readObject();
+ }
+ }
+
+
+ /**
+ * @return Returns the listener.
+ */
+ public MessageListener getListener() {
+ return listener;
+ }
+}
Index: 3rdParty_sources/jgroups/org/jgroups/blocks/ReplicatedHashMap.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/jgroups/org/jgroups/blocks/ReplicatedHashMap.java,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/jgroups/org/jgroups/blocks/ReplicatedHashMap.java 17 Aug 2012 14:51:18 -0000 1.1
@@ -0,0 +1,1043 @@
+package org.jgroups.blocks;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jgroups.*;
+import org.jgroups.persistence.PersistenceFactory;
+import org.jgroups.persistence.PersistenceManager;
+import org.jgroups.util.Promise;
+import org.jgroups.util.Util;
+
+import java.io.*;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+
+/**
+ * Subclass of a {@link java.util.concurrent.ConcurrentHashMap} with replication of the contents across a cluster.
+ * Any change to the hashmap (clear(), put(), remove() etc) will transparently be
+ * propagated to all replicas in the group. All read-only methods will always access the local replica.
+ * Keys and values added to the hashmap must be serializable , the reason
+ * being that they will be sent across the network to all replicas of the group. Having said
+ * this, it is now for example possible to add RMI remote objects to the hashtable as they
+ * are derived from java.rmi.server.RemoteObject
which in turn is serializable.
+ * This allows to lookup shared distributed objects by their name and invoke methods on them,
+ * regardless of one's onw location. A ReplicatedHashMap
thus allows to
+ * implement a distributed naming service in just a couple of lines.
+ * An instance of this class will contact an existing member of the group to fetch its
+ * initial state.
+ * This class combines both {@link org.jgroups.blocks.ReplicatedHashtable} (asynchronous replication) and
+ * {@link org.jgroups.blocks.DistributedHashtable} (synchronous replication) into one class
+ * @author Bela Ban
+ * @version $Id: ReplicatedHashMap.java,v 1.1 2012/08/17 14:51:18 marcin Exp $
+ */
+public class ReplicatedHashMap extends ConcurrentHashMap implements ExtendedReceiver, ReplicatedMap {
+ private static final long serialVersionUID=-5317720987340048547L;
+
+
+ public interface Notification {
+ void entrySet(K key, V value);
+
+ void entryRemoved(K key);
+
+ void viewChange(View view, Vector new_mbrs, Vector old_mbrs);
+
+ void contentsSet(Map new_entries);
+
+ void contentsCleared();
+ }
+
+ private static final short PUT = 1;
+ private static final short PUT_IF_ABSENT = 2;
+ private static final short PUT_ALL = 3;
+ private static final short REMOVE = 4;
+ private static final short REMOVE_IF_EQUALS = 5;
+ private static final short REPLACE_IF_EXISTS = 6;
+ private static final short REPLACE_IF_EQUALS = 7;
+ private static final short CLEAR = 8;
+
+
+ protected static Map methods;
+
+ static {
+ try {
+ methods=new HashMap