Commit 20d31fd6 authored by Bruce Momjian's avatar Bruce Momjian

Completely remove /contrib/retep, with Peter's approval; now on Source

Forge.
parent 9c7cd8ba
Fri Mar 02 16:08:00 GMT 2001 peter@retep.org.uk
- Started importing in the rest of the retep tools.
Tue Jan 23 10:19:00 GMT 2001 peter@retep.org.uk
- Finished the XML Export classes
- First of the test data suite now in CVS.
Retep Tools Implementation
--------------------------
The tools are designed to be put into a single jar file, but each one is
executable either individually or part of one single application.
To run the big application, you can either:
java -jar retepTools.jar
or with the retepTools.jar in the classpath run:
java uk.org.retep.tools.Main
Windows users: For you you can also double click the retepTools.jar as windows
will automatically run javac for you.
To run the individual tools, you must have the .jar file in your classpath and
then run the relevant Main class.
Tool Type Class
------------------------------------------------------------------------------
pg_hba.conf Editor/repairer Editor uk.org.retep.util.hba.Main
Properties Editor Editor uk.org.retep.util.proped.Main
Layout of the classes
---------------------
Simply, tools that work on property files (Java properties, resource files,
configuration settings - pg_hba.conf for example) go under uk.org.retep.util in
their own package. Other utility classes (like PropertyIO) go in to the
uk.org.retep.util.misc package except for certain ones where they are related.
ie: TableModels. In swing you have JTable which uses a TableModel to display
(and possibly update) some data. These go under uk.org.retep.util.models where
you will find PropertiesTableModel for example. This one allows a Properties
object to be displayed & updated.
Come core classes like Logger, ExceptionDialog etc go into the main
uk.org.retep.util package.
Directory/Package Contents
------------------------------------------------------------------------------
uk.org.retep Home of the tools.properties file
uk.org.retep.tools The main all-in-one application
uk.org.retep.dtu The Data Transform Unit
uk.org.retep.util Core utility classes
uk.org.retep.util.hba pg_hba.conf editor/repairer
uk.org.retep.util.misc Misc utility classes
uk.org.retep.util.models Swing table models
uk.org.retep.util.proped Property Editor
uk.org.retep.util.xml.core Basic XML Factory
uk.org.retep.util.xml.jdbc JDBC/XML interface
uk.org.retep.util.xml.parser Simple SAX parser
Structure of a tool
-------------------
Each tool has at least 2 base classes, and an entry in the tools.properties
file. For this example, I'll show you the Properties Editor:
Base package uk.org.retep.util.proped
Main tool class uk.org.retep.util.proped.PropertyEditor
Standalone class uk.org.retep.util.proped.Main
The main tool class is the entry point used by the main application. Because
they are used in a GUI, this class must extend javax.swing.JComponent and
implement the uk.org.retep.tools.Tool interface. (NB: You will find I always
use JPanel, but JComponent is used here so that any swing class can be used
you are not limited to JPanel.)
The standalone class is a basic static class that implements the main method.
It should extend the uk.org.retep.misc.StandaloneApp class and be written along
the lines of the following example:
import uk.org.retep.util.StandaloneApp;
import javax.swing.JComponent;
public class Main extends StandaloneApp
{
public Main(String[] args)
throws Exception
{
super(args);
}
public JComponent init()
throws Exception
{
// Your initialisation here. In this case the PropertyEditor
PropertyEditor panel = new PropertyEditor();
// do stuff here, ie load a file if supplied
// return the tool
return panel;
}
public static void main(String[] args)
throws Exception
{
Main main = new Main(args);
main.pack();
main.setVisible(true);
}
}
you will find a template in the uk.org.retep.util.Main class. Simply copy this
classes source, as it gives you the basic stub. Just add your own implementation
if init() like the one above. Look at the full Main class for the
PropertiesEditor to see how to get at the command line args.
By convention, the standalone class is named Main.
#-------------------------------------------------------------------------
#
# Makefile for contributed retep tools
#
# Copyright (c) 2001, PostgreSQL Global Development Group
#
# $Header: /cvsroot/pgsql/contrib/retep/Attic/Makefile,v 1.1 2001/07/06 23:07:20 petere Exp $
#
#-------------------------------------------------------------------------
subdir = contrib/retep
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
all:
$(ANT) -buildfile $(srcdir)/build.xml all
install: installdirs
$(ANT) -buildfile $(srcdir)/build.xml install \
-Dinstall.directory=$(javadir)
installdirs:
$(mkinstalldirs) $(javadir)
uninstall:
$(ANT) -buildfile $(srcdir)/build.xml uninstall \
-Dinstall.directory=$(javadir)
clean distclean maintainer-clean:
$(ANT) -buildfile $(srcdir)/build.xml clean
Before you ask what retepTools are, they are my personal suite of utilities.
About 90% of them are JDBC related (either they use JDBC, or I use them in
developing the JDBC driver).
Now, because of various reasons I won't go into now, in January 2001 I decided
to release the entire lot to the public. I could have used something like
SourceForge, but as they are mainly JDBC related I thought here is the best
place.
Now all (bar retepPDF, see end-note) will over the next few months be going
into the /contrib/retep directory. They range from simple XML Inport/Export
classes to entire sub-systems that can be plugged into applications.
All this lot were never released, so I'm placing them under PostgreSQL's
licence.
Please refer to Implementation for details of what package does what.
It all requires Java2SE (JDK1.2) as a minimum. I do have some plans for some
EJB tools later, so those will need Java2EE, but not yet ;-)
Peter Mount
peter@retep.org.uk
March 2 2001
retepPDF: This is not included for two reasons:
1: It's big and not really related in any way to PostgreSQL
2: More importantly, I (may be foolishly) released it some 3 years ago under
the LGPL. As a few people have added to it, it's not really possible to
change the licence, and I don't want to polute PostgreSQL's source tree ;-)
retepGraph: This was an old graphics library. It's been obsolete for 3 years
now, so it's not going in.
<?xml version="1.0"?>
<!--
build file to build the donated retep tools packages
$Header: /cvsroot/pgsql/contrib/retep/Attic/build.xml,v 1.8 2001/07/06 23:07:20 petere Exp $
-->
<!DOCTYPE project [
<!ENTITY jarname "retepTools.jar">
]>
<project name="retep" default="all" basedir=".">
<!-- set global properties for this build -->
<property name="srcdir" value="." />
<property name="builddir" value="build" />
<property name="package" value="uk/org/retep" />
<property name="jardir" value="jars" />
<!-- Some checks used to build dependent on the environment -->
<target name="checks">
<available property="jdk1.2+" classname="java.lang.ThreadLocal" />
<available property="jdk1.3+" classname="java.lang.StrictMath" />
<available property="jdk1.2e+" classname="javax.sql.DataSource" />
<available property="xml" classname="org.xml.sax.Parser" />
</target>
<target name="warning" depends="checks" unless="jdk1.2+">
<echo>
*** WARNING: Contributed retep tools need jdk1.2 or later.
*** Compilation NOT done
</echo>
</target>
<!-- default target -->
<target name="all">
<antcall target="jar" />
</target>
<!-- Builds the various jar files -->
<target name="jar" depends="compile">
<jar jarfile="${jardir}/&jarname;" whenempty="fail">
<fileset dir="${builddir}">
<include name="**/*.class" />
</fileset>
<fileset dir="${srcdir}">
<include name="**/*.properties" />
</fileset>
</jar>
</target>
<!-- Builds the XML Tools -->
<target name="compile" depends="checks,prepare,warning" if="jdk1.2+">
<javac srcdir="${srcdir}" destdir="${builddir}">
<include name="${package}/**" />
<exclude name="${package}/**" unless="jdk1.2+" />
</javac>
</target>
<!-- Prepares the build by creating a directory to place the class files -->
<target name="prepare">
<mkdir dir="${builddir}" />
<mkdir dir="${jardir}" />
</target>
<target name="install" depends="all" if="install.directory">
<copy todir="${install.directory}" overwrite="true" filtering="off">
<fileset dir="${jardir}">
<include name="&jarname;" />
</fileset>
</copy>
</target>
<target name="uninstall" if="install.directory">
<delete>
<fileset dir="${install.directory}">
<include name="&jarname;" />
</fileset>
</delete>
</target>
<!-- This target removes any class files from the build directory -->
<target name="clean">
<delete quiet="true" dir="${builddir}" />
<delete quiet="true" dir="${jardir}" />
</target>
</project>
<!ELEMENT album (track*)+>
<!ATTLIST album
title CDATA #IMPLIED
aid CDATA #IMPLIED
>
<!ELEMENT catalogue (group)>
<!ELEMENT group (album*)>
<!ATTLIST group
name CDATA #IMPLIED
>
<!ELEMENT track (#PCDATA)>
<!ATTLIST track
tid CDATA #IMPLIED
id CDATA #IMPLIED
>
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0" encoding="UTF-8"?>
<!--JBuilder XML Project-->
<project>
<property category="idl" name="ProcessIDL" value="false" />
<property category="runtime.0" name="RunnableType" value="com.borland.jbuilder.runtime.ApplicationRunner" />
<property category="runtime.0" name="application.class" value="uk.org.retep.util.hba.Main" />
<property category="runtime.0" name="application.parameters" value="-d2 pg_hba.conf" />
<property category="runtime.0" name="appserver.ejbJarsSaved" value="1" />
<property category="runtime.0" name="appserver.parameters" value="-jts -jns -jss -jdb" />
<property category="runtime.0" name="appserver.servername" value="ejbcontainer" />
<property category="runtime.0" name="appserver.vmparameters" value="" />
<property category="runtime.0" name="jsprunner.docbase" value="." />
<property category="runtime.0" name="jsprunner.jspfile" value="E%|/docs/java/xml/example6" />
<property category="sys" name="AuthorLabel" value="@author" />
<property category="sys" name="BackupPath" value="bak" />
<property category="sys" name="BeansInstantiate" value="false" />
<property category="sys" name="BraceStyle" value="1" />
<property category="sys" name="CheckStable" value="1" />
<property category="sys" name="Company" value="" />
<property category="sys" name="CompanyLabel" value="Company:" />
<property category="sys" name="Copyright" value="Copyright (c) 2001" />
<property category="sys" name="CopyrightLabel" value="Copyright:" />
<property category="sys" name="DefaultPackage" value="uk.org.retep.util.misc" />
<property category="sys" name="Description" value="" />
<property category="sys" name="DescriptionLabel" value="Description:" />
<property category="sys" name="DocPath" value="doc" />
<property category="sys" name="EventMatch" value="false" />
<property category="sys" name="EventStyle" value="1" />
<property category="sys" name="ExcludeClassEnabled" value="0" />
<property category="sys" name="InstanceVisibility" value="0" />
<property category="sys" name="JDK" value="java 1.3.0-C" />
<property category="sys" name="LastTag" value="0" />
<property category="sys" name="Libraries" value="JAXP;Oracle JDBC;JDK1.3 JRE" />
<property category="sys" name="MakeStable" value="0" />
<property category="sys" name="OutPath" value="build" />
<property category="sys" name="SourcePath" value="." />
<property category="sys" name="Title" value="" />
<property category="sys" name="TitleLabel" value="Title:" />
<property category="sys" name="Version" value="1.0" />
<property category="sys" name="VersionLabel" value="@version" />
<property category="sys" name="WorkingDirectory" value="." />
<node type="Package" name="uk.org.retep.dtu" />
<node type="Package" name="uk.org.retep.tools" />
<node type="Package" name="uk.org.retep.util" />
<node type="Package" name="uk.org.retep.xml.core" />
<node type="Package" name="uk.org.retep.xml.jdbc" />
<node type="Package" name="uk.org.retep.xml.parser" />
<file path="build.xml" />
<file path="CHANGELOG" />
<file path="Implementation" />
<file path="uk/org/retep/util/models/PropertiesTableModel.java" />
<file path="README" />
</project>
package uk.org.retep.dtu;
import uk.org.retep.xml.core.XMLFactory;
import uk.org.retep.xml.core.XMLFactoryException;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
public class DCollection implements Collection
{
protected int num,max,inc;
protected DElement elements[];
public DCollection()
{
this(10);
}
public DCollection(int aIncrement)
{
num=0;
max=0;
inc=aIncrement;
elements=null;
}
protected void resize()
{
if(num>=max) {
max+=inc;
DElement n[] = new DElement[max];
if(elements!=null) {
System.arraycopy(elements,0,n,0,elements.length);
}
elements=n;
}
}
public int size()
{
return num;
}
public boolean isEmpty()
{
return (num==0);
}
/**
* Checks the list using it's XML id.
*/
public synchronized boolean contains(Object parm1)
{
if(parm1 instanceof DElement) {
DElement e = (DElement) parm1;
int ei = e.getID();
// out of range?
if(ei<0 || ei>=num)
return false;
return elements[ei].equals(e);
}
return false;
}
public Iterator iterator()
{
return new iterator(this);
}
/**
* Inner class to implement an Iterator
*/
protected class iterator implements Iterator
{
protected DCollection c;
protected int i;
public iterator(DCollection aCollection)
{
c=aCollection;
i=0;
}
public boolean hasNext()
{
return i<c.size();
}
public Object next() {
return c.getElement(i++);
}
public void remove() {
}
}
public synchronized Object[] toArray()
{
Object o[] = new Object[num];
System.arraycopy(elements,0,o,0,num);
return o;
}
public Object[] toArray(Object[] parm1)
{
/**@todo: Implement this java.util.Collection method*/
throw new java.lang.UnsupportedOperationException("Method toArray() not yet implemented.");
}
/**
* Adds a node to the Collection, and sets it's ID to its position in the Collection
*/
public synchronized boolean add(Object parm1)
{
if(parm1 instanceof DElement) {
DElement e = (DElement) parm1;
// Do nothing if it's already in a Collection
if(e.getID()>-1) {
return false;
}
// Add to the Collection
resize();
e.setID(num);
elements[num++] = e;
return true;
}
return false;
}
public synchronized boolean remove(Object parm1)
{
if(parm1 instanceof DElement) {
DElement e = (DElement) parm1;
int ei = e.getID();
if(ei<0 || ei>=num)
return false;
// Mark the node as parentless
e.setID(-1);
// Now remove from the array by moving latter nodes, fixing their ids
// in the process
for(int j=ei,k=ei+1;k<num;j++,k++) {
elements[j]=elements[k];
elements[j].setID(j);
}
num--;
return true;
}
return false;
}
public boolean containsAll(Collection parm1)
{
/**@todo: Implement this java.util.Collection method*/
throw new java.lang.UnsupportedOperationException("Method containsAll() not yet implemented.");
}
public boolean addAll(Collection parm1)
{
/**@todo: Implement this java.util.Collection method*/
throw new java.lang.UnsupportedOperationException("Method addAll() not yet implemented.");
}
public boolean removeAll(Collection parm1)
{
/**@todo: Implement this java.util.Collection method*/
throw new java.lang.UnsupportedOperationException("Method removeAll() not yet implemented.");
}
public boolean retainAll(Collection parm1)
{
/**@todo: Implement this java.util.Collection method*/
throw new java.lang.UnsupportedOperationException("Method retainAll() not yet implemented.");
}
public synchronized void clear()
{
// Mark each node as parentless
for(int i=0;i<num;i++) {
elements[i].setID(-1);
}
// dispose the array
num=0;
max=0;
elements=null;
}
/**
* Returns the element with supplied id.
* @return element or null
*/
public synchronized DElement getElement(int id)
{
if(id<0 || id>=num)
return null;
return elements[id];
}
/**
* Repairs the collection, ensuring all id's are correct
*/
public synchronized void repair()
{
for(int i=0;i<num;i++) {
elements[i].setID(i);
}
}
public synchronized void saveXML(XMLFactory aFactory)
throws IOException, XMLFactoryException
{
for(int i=0;i<num;i++) {
elements[i].saveXML(aFactory);
}
}
}
\ No newline at end of file
package uk.org.retep.dtu;
public class DConstants
{
/**
* A global version number
*/
public static final String XML_VERSION_ID = "V7.1-2001-02-26";
/**
* XML Tag names
*/
public static final String XML_DISPLAYNAME= "DISPLAYNAME";
public static final String XML_FROM = "FROM";
public static final String XML_ID = "ID";
public static final String XML_MODULE = "MODULE";
public static final String XML_NODE = "NODE";
public static final String XML_TO = "TO";
public static final String XML_TRANSFORM = "TRANSFORM";
public static final String XML_TYPE = "TYPE";
public static final String XML_VERSION = "VERSION";
public static final String XML_X = "X";
public static final String XML_Y = "Y";
public static final int NOP = 0; // No operation or always run transform
public static final int SUCCESS = 1; // Run transform only if DNode.OK
public static final int ERROR = 2; // Run transform only if DNode.ERROR
/**
* Node types 20-39 reserved for Transformation types
*/
public static final int TRANSFORMBASE = 20;
/**
* Node types 20-99 reserved for Internal Node implementations
*/
public static final int INTERNALBASE = 50;
/**
* Node types 100+ are for user extensions
*/
public static final int USERBASE = 100;
}
\ No newline at end of file
package uk.org.retep.dtu;
import uk.org.retep.xml.core.XMLFactory;
import uk.org.retep.xml.core.XMLFactoryException;
import java.io.IOException;
public interface DElement
{
/**
* Fetch the unique ID of this Element
*/
public int getID();
/**
* Sets the unique id - normally set by DCollection
*/
public void setID(int id);
/**
* @return the type of the Element
*/
public int getType();
/**
* Set's the element type
*/
public void setType(int aType);
public void saveXML(XMLFactory aFactory) throws IOException, XMLFactoryException;
}
\ No newline at end of file
package uk.org.retep.dtu;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
public class DEnvironment
{
protected HashMap dsrc;
public DEnvironment()
{
dsrc=new HashMap();
}
public void addDataSource(String aKey,Object aObject)
{
dsrc.put(aKey,aObject);
}
public Object getDataSource(String aKey)
{
return dsrc.get(aKey);
}
public Iterator getDataSources()
{
return dsrc.values().iterator();
}
}
\ No newline at end of file
package uk.org.retep.dtu;
import uk.org.retep.xml.core.XMLFactory;
import uk.org.retep.xml.core.XMLFactoryException;
import uk.org.retep.xml.parser.TagListener;
import uk.org.retep.util.Logger;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
/**
* DModule represents a programatic module of steps used within the DTU
*/
public class DModule implements Serializable
{
// The nodes and transitions between them
protected DCollection nodes;
protected String displayName;
public static final String DEFAULT_DISPLAYNAME = "unnamed module";
public DModule()
{
nodes=new DCollection();
displayName=DEFAULT_DISPLAYNAME;
Logger.log(Logger.DEBUG,"new DModule",this);
}
// Expensive!
public DNode getNode(int id)
{
return (DNode) nodes.getElement(id);
}
public DNode addNode(DNode aNode)
{
Logger.log(Logger.DEBUG,"DModule.addNode",aNode);
nodes.add(aNode);
return aNode;
}
public void removeNode(DNode aNode)
{
Logger.log(Logger.DEBUG,"DModule.removeNode",aNode);
nodes.remove(aNode);
}
public void clear()
{
Logger.log(Logger.DEBUG,"DModule.clear",this);
nodes.clear();
}
public void setDisplayName(String aName)
{
Logger.log(Logger.DEBUG,"DModule.setDisplayName",aName);
displayName = aName;
}
public String getDisplayName()
{
return displayName;
}
public Iterator iterator()
{
return nodes.iterator();
}
/**
* Writes an XML representation of this module to an XMLFactory. The caller
* must close the factory after use!
*/
public synchronized void saveXML(XMLFactory aFactory)
throws IOException, XMLFactoryException
{
Logger.log(Logger.DEBUG,"DModule.saveXML start",this);
Iterator it;
aFactory.startTag(DConstants.XML_MODULE);
aFactory.addAttribute(DConstants.XML_DISPLAYNAME,displayName);
aFactory.addAttribute(DConstants.XML_VERSION,DConstants.XML_VERSION_ID);
// The nodes
nodes.saveXML(aFactory);
// The transforms
//trans.saveXML(aFactory);
aFactory.endTag(); // MODULE
Logger.log(Logger.DEBUG,"DModule.saveXML end",this);
}
}
\ No newline at end of file
package uk.org.retep.dtu;
import uk.org.retep.xml.core.XMLFactory;
import uk.org.retep.xml.core.XMLFactoryException;
import uk.org.retep.xml.parser.TagHandler;
import uk.org.retep.xml.parser.TagListener;
import uk.org.retep.util.Logger;
import java.io.CharArrayWriter;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
import org.xml.sax.InputSource;
import org.xml.sax.Parser;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
public class DModuleXML implements TagListener
{
protected TagHandler handler;
protected DModule module = null;
protected DNode node = null;
protected DTransform trans = null;
protected ArrayList txmap;
public DModuleXML()
{
handler = new TagHandler();
handler.addTagListener(this);
txmap = new ArrayList();
Logger.log(Logger.DEBUG,"DModuleXML initialised");
}
public TagHandler getTagHandler()
{
return handler;
}
/**
* Used to optimise the switch handling in tagStart.
*
* The values of each T_* constant must match the corresponding element no
* in the tags static array.
*/
private static final int T_DEFAULT=-1;
private static final int T_MODULE =0;
private static final int T_NODE =1;
private static final int T_TRANS =2;
private static final String tags[] = {
DConstants.XML_MODULE,
DConstants.XML_NODE,
DConstants.XML_TRANSFORM
};
/**
* This is called when a tag has just been started.
* <p><b>NB:</b> args is volatile, so if you use it beyond the lifetime of
* this call, then you must make a copy of the HashMap (and not use simply
* store this HashMap).
* @param level The number of tags above this
* @param tag The tag name
* @param args A HashMap of any arguments
*/
public void tagStart(int level,String tag,HashMap args)
{
Logger.log(Logger.DEBUG,"DModuleXML.tagStart",tag);
// Prefetch some common attributes
String sType = (String) args.get(DConstants.XML_TYPE);
String sX = (String) args.get(DConstants.XML_X);
String sY = (String) args.get(DConstants.XML_Y);
int type=-1,x=-1,y=-1;
if(sType!=null) {
type = Integer.parseInt(sType);
}
if(sX!=null) {
y = Integer.parseInt(sX);
}
if(sY!=null) {
x = Integer.parseInt(sY);
}
// Match the tag against the tags array (used for switch() )
int tagID=T_DEFAULT;
for(int i=0;i<tags.length;i++) {
if(tag.equals(tags[i])) {
tagID=i;
}
}
switch(tagID)
{
// The main module tag
case T_MODULE:
module = new DModule();
String sDisplayName = (String) args.get(DConstants.XML_DISPLAYNAME);
if(sDisplayName!=null) {
module.setDisplayName(sDisplayName);
}
break;
// Basic nodes
case T_NODE:
node = new DNode();
node.setType(type);
module.addNode(node);
break;
// Basic transforms
case T_TRANS:
trans = new DTransform();
trans.setType(type);
// When finished we fix the transforms
int to = Integer.parseInt((String) args.get(DConstants.XML_TO));
txmap.add(new tx(node,trans,to));
break;
default:
// ignore unknown tags for now
break;
}
}
protected class tx
{
public DNode node;
public DTransform transform;
public int toID;
public tx(DNode aNode,DTransform aTransform,int aID)
{
node=aNode;
transform=aTransform;
toID=aID;
}
}
/**
* This method is called by ContHandler to process a tag once it has been
* fully processed.
* <p><b>NB:</b> content is volatile, so you must copy its contents if you use
* it beyond the lifetime of this call.
* @param content CharArrayWriter containing the content of the tag.
*/
public void tagContent(CharArrayWriter content)
{
// Ignore
}
public void fixTransforms()
{
DNode to;
Iterator it = txmap.iterator();
while(it.hasNext()) {
tx x = (tx) it.next();
//Logger.log(Logger.DEBUG,"Fixing transform "+x.toID,x.transform,Integer.toString(x.node.getID()),Integer.toString(module.getNode(x.toID).getID()));
to = module.getNode(x.toID);
x.transform.setFrom(x.node);
x.transform.setTo(to);
//to.setFrom(x.transform);
}
}
/**
* Parse an InputSource and return the contained module.
* @return DModule loaded, null if the xml file does not contain a module.
*/
public DModule parse(InputSource is)
throws IOException,SAXException
{
getTagHandler().parse(is);
fixTransforms();
return module;
}
/**
* Parse an uri and return the contained module.
* @return DModule loaded, null if the xml file does not contain a module.
*/
public DModule parse(String uri)
throws IOException,SAXException
{
getTagHandler().parse(uri);
fixTransforms();
return module;
}
/**
* Debug test - read xml from one file and save to another.
*/
public static void main(String args[]) throws Exception
{
if(args.length!=2) {
System.err.println("Syntax: java DModuleXML in-file out-file");
System.exit(1);
}
Logger.setLevel(Logger.DEBUG);
Logger.log(Logger.INFO,"DModuleXML Read test1.xml");
DModuleXML dm = new DModuleXML();
DModule module = dm.parse(new InputSource(new FileInputStream(args[0])));
Logger.log(Logger.INFO,"Parse complete");
Logger.log(Logger.INFO,"DModuleXML Write XML");
FileWriter fw = new FileWriter(args[1]);
module.saveXML(new XMLFactory(fw));
fw.close();
Logger.log(Logger.INFO,"Write complete");
DProcessor.run(module);
}
}
\ No newline at end of file
package uk.org.retep.dtu;
import uk.org.retep.util.Logger;
import uk.org.retep.xml.core.XMLFactory;
import uk.org.retep.xml.core.XMLFactoryException;
import java.io.IOException;
import java.io.Serializable;
import java.util.Iterator;
/**
* This is the base class for all nodes.
*/
public class DNode implements DElement, Serializable
{
// The id of this node
protected int id;
// The type of this node
protected int type;
protected int x,y;
public static final int OK = 0; // Node last ran fine
public static final int ERROR = 1; // Node failed on last run
/**
* This type of node does nothing
*/
public static int NOP = 0; // No action
public DNode()
{
this(NOP);
}
public DNode(int aType)
{
id=-1;
type=aType;
// Init the transform linkage
mf=mt=5;
nf=nt=0;
fn = new DTransform[mf];
tn = new DTransform[mt];
Logger.log(Logger.DEBUG,"new DNode");
}
public int getID()
{
return id;
}
public void setID(int aID)
{
id=aID;
Logger.log(Logger.DEBUG,"DNode.setID",aID);
}
public int getType()
{
return type;
}
public void setType(int aType)
{
type=aType;
Logger.log(Logger.DEBUG,"DNode.setType",aType);
}
/**
*/
public void saveXML(XMLFactory aFactory)
throws IOException, XMLFactoryException
{
Logger.log(Logger.DEBUG,"DNode.saveXML start",this);
Iterator it;
aFactory.startTag(DConstants.XML_NODE);
aFactory.addAttribute(DConstants.XML_ID,new Integer(getID()));
aFactory.addAttribute(DConstants.XML_TYPE,new Integer(getType()));
// used for display only
aFactory.addAttribute(DConstants.XML_X,new Integer(getX()));
aFactory.addAttribute(DConstants.XML_Y,new Integer(getY()));
// Save the transforms here (only the from list required)
for(int i=0;i<nf;i++) {
fn[i].saveXML(aFactory);
}
aFactory.endTag(); // NODE
Logger.log(Logger.DEBUG,"DNode.saveXML finish",this);
}
public void setPosition(int aX,int aY)
{
x=aX;
y=aY;
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
public void setX(int aX)
{
x=aX;
}
public void setY(int aY)
{
y=aY;
}
/**
* This must be overidden to do something
* @return Return status
*/
public int run(DEnvironment env)
{
return OK;
}
/**
* Node Transforms...
*/
protected int nf,mf,nt,mt;
protected DTransform fn[],tn[];
/**
* Executes the transform
*/
public DTransform getTransform(int aID)
{
return tn[aID];
}
/**
* @return number of transforms
*/
public int getFromTransforms()
{
return nf;
}
/**
* @return number of transforms
*/
public int getToTransforms()
{
return nt;
}
/**
* Adds a transform to this node (called by DTransform)
*/
protected synchronized void setFrom(DTransform aTransform)
{
for(int i=0;i<nf;i++) {
if(fn[i].equals(aTransform)) {
return;
}
}
if(nf>=mf) {
mf+=5;
DTransform nn[] = new DTransform[mf];
System.arraycopy(fn,0,nn,0,nf);
fn=nn;
}
fn[nf++]=aTransform;
}
/**
* Adds a transform to this node (called by DTransform)
*/
protected synchronized void setTo(DTransform aTransform)
{
for(int i=0;i<nt;i++) {
if(tn[i].equals(aTransform)) {
return;
}
}
if(nt>=mt) {
mt+=5;
DTransform nn[] = new DTransform[mt];
System.arraycopy(tn,0,nn,0,nt);
tn=nn;
}
tn[nt++]=aTransform;
}
/**
* Removes a transform (called by DTransform)
*/
protected synchronized void removeFrom(DTransform aTransform)
{
for(int i=0;i<nf;i++) {
if(tn[i].equals(aTransform)) {
for(int j=i+1;j<nf;j++,i++) {
fn[i]=fn[j];
}
nf--;
return;
}
}
}
/**
* Removes a transform (called by DTransform)
*/
protected synchronized void removeTo(DTransform aTransform)
{
for(int i=0;i<nt;i++) {
if(tn[i].equals(aTransform)) {
for(int j=i+1;j<nt;j++,i++) {
tn[i]=tn[j];
}
nt--;
return;
}
}
}
}
package uk.org.retep.dtu;
import uk.org.retep.util.Logger;
import java.util.Iterator;
/**
* This class processes a Module. It's implemented as a Thread and there can
* be many threads running on a single module
*/
public class DProcessor
{
/**
* This starts a module
*/
public static DProcessor run(DModule aModule) {
// 3600000 is 1 hour in milliseconds
return run(aModule,3600000);
}
/**
* This starts a module
*/
public static DProcessor run(DModule aModule,long timeout) {
return new DProcessor(aModule,timeout);
}
protected DProcessor(DModule aModule,long timeout) {
ThreadGroup group = new ThreadGroup(aModule.getDisplayName()+" DProcessor");
// Setup the environment
DEnvironment env = new DEnvironment();
// loop for any nodes without a transform pointing _to_ it.
Iterator it = aModule.iterator();
while(it.hasNext()) {
DNode node = (DNode) it.next();
// Only start if we have no predecessor
if(node.getFromTransforms()==0) {
proc proc = new proc(group,aModule,node,env);
proc.start();
}
}
// Now wait until all the threads have finished
boolean running=true;
try {
int cnt=1; // must loop at least once!
while(cnt>0) {
int numThreads = group.activeCount();
Thread threads[] = new Thread[numThreads];
cnt = group.enumerate(threads,false);
//Logger.log(Logger.DEBUG,"Waiting on threads",cnt);
while(cnt>0) {
//Logger.log(Logger.DEBUG,"Waiting on thread",cnt);
threads[--cnt].join(timeout);
}
Logger.log(Logger.DEBUG,"All threads appear to have died, retesting");
}
} catch(InterruptedException ie) {
Logger.log(Logger.ERROR,"DProcessor, exception caught while waiting for threads to die",ie);
}
// finally close any open datasources
Logger.log(Logger.DEBUG,"DProcessor cleanup");
Logger.log(Logger.DEBUG,"DProcessor finished");
}
class proc implements Runnable
{
protected DModule module; // The module being run
protected DNode pc; // current Program Counter
protected DEnvironment env; // Shared environment
// Used when launching new threads only
protected DTransform trans; // If not null, a transform to run first
protected int status;
protected Thread thread;
/**
* Start processing from DNode aNode. This is called by DProcessor at
* initialisation only.
*/
protected proc(ThreadGroup aGroup,DModule aModule,DNode aNode,DEnvironment aEnv)
{
// aGroup will be null when forking...
if(aGroup==null) {
thread = new Thread(this);
} else {
thread = new Thread(aGroup,this);
}
module = aModule;
pc = aNode;
env = aEnv;
}
/**
* Start processing the DTransform aTransform from aNode (does not execute
* the node). This is called by this inner class itself when forking new
* threads.
*/
protected proc(DModule aModule,DNode aNode,DEnvironment aEnv,DTransform aTransform,int aStatus)
{
this(null,aModule,aNode,aEnv);
trans = aTransform;
status = aStatus;
}
/**
* Start this thread
*/
public void start()
{
thread.start();
}
public void run()
{
// Handle an initial transform first. It's used when a new Thread was created.
if(trans!=null) {
transform(trans,false,status);
trans=null;
}
while(pc!=null) {
//Logger.log(Logger.DEBUG,"running node ",pc.getID());
// Process the node
int status = pc.run(env);
//Logger.log(Logger.DEBUG," status ",status);
// Now the transforms. This thread continues with the first one that runs,
// but any others that will also run will do so in their own thread.
// If no transform runs (or there are none), then the thread will die.
int numTrans = pc.getToTransforms();
boolean fork=false;
for(int i=0;i<numTrans;i++) {
fork = transform(pc.getTransform(i),fork,status);
//Logger.log(Logger.DEBUG,"fork",fork?"true":"false");
}
//Logger.log(Logger.DEBUG,"fork",fork?"true":"false");
if(!fork) {
// No transforms ran, so we quit this thread
pc=null;
}
// This lets the other threads a chance to run
Thread.yield();
}
}
/**
* This executes a transform
* @param aTransform DTransform to execute
* @param fork true then a new process is triggered
* @param status The return status of the previous node
* @return true if the transform ran or a fork occured.
*/
public boolean transform(DTransform aTransform,boolean fork,int status)
{
// Check to see if the transform will run (based on the calling nodes return
// status
if(!aTransform.willRun(status,env)) {
return false;
}
if(fork) {
// Create the new processor but this time we want a transform to run
proc proc = new proc(module,pc,env,aTransform,status);
return true;
}
if(aTransform.run(env)) {
pc=aTransform.getTo();
return true;
}
return false;
}
} // class proc
}
\ No newline at end of file
package uk.org.retep.dtu;
import uk.org.retep.xml.core.XMLFactory;
import uk.org.retep.xml.core.XMLFactoryException;
import java.io.IOException;
/**
* This manages the links between two nodes.
*/
public class DTransform
{
protected DNode from,to;
protected int type;
public DTransform()
{
this(null,null);
}
public DTransform(DNode aFrom,DNode aTo)
{
from=aFrom;
to=aTo;
}
public int getType()
{
return type;
}
public void setType(int aType)
{
type=aType;
}
public void setFrom(DNode aNode)
{
if(from!=null) {
from.removeTo(this);
}
from=aNode;
from.setTo(this);
}
public DNode getFrom()
{
return from;
}
public void setTo(DNode aNode)
{
if(to!=null) {
to.removeFrom(this);
}
to=aNode;
aNode.setFrom(this);
}
public DNode getTo()
{
return to;
}
/**
* This ensures the minimum tag/attributes are generated.
* To extend, extend saveCustomXML() which is called by this method
* appropriately.
*/
public final void saveXML(XMLFactory aFactory)
throws IOException, XMLFactoryException
{
// Bare minimum is the tag type, and the destination node's id
aFactory.startTag(DConstants.XML_TRANSFORM);
aFactory.addAttribute(DConstants.XML_TYPE,Integer.toString(getType()));
aFactory.addAttribute(DConstants.XML_TO,Integer.toString(to.getID()));
saveCustomXML(aFactory);
aFactory.endTag();
}
/**
* Custom transformations must overide this method and write direct to the
* supplied XMLFactory. A tag is currently open when the method is called, but
* is closed immediately this method exits.
*/
public void saveCustomXML(XMLFactory aFactory)
throws IOException, XMLFactoryException
{
// Default method does nothing...
}
/**
* Checks to see if we should run based on the calling nodes status. Overide
* this to add this sort of checking.
*
* @param status The return status of the calling node
* @param env DEnvironment we are using
* @return true if we will run.
*/
public boolean willRun(int status,DEnvironment env)
{
switch(getType())
{
// NOP is the generic link - always run
case DConstants.NOP:
return true;
// SUCCESS only runs if the previous node was OK
case DConstants.SUCCESS:
return status==DNode.OK;
case DConstants.ERROR:
return status==DNode.ERROR;
// Default - always run. Overide the method if you need to change this
default:
return true;
}
}
/**
* Overide this for a transform to do something.
* @param env DEnvironment we are using
* @return true if we actually ran. DProcessor will jump to the getTo() node if so.
*/
public boolean run(DEnvironment env)
{
return true;
}
}
\ No newline at end of file
#Written by Retep PropertyEditor
#Sat Mar 03 16:29:44 GMT+00:00 2001
tool.hba=pg_hba.conf editor
tool.hba.class=uk.org.retep.util.hba.Editor
tool.proped.class=uk.org.retep.util.proped.PropertyEditor
tool.hba.type=Misc
tool.proped.type=Misc
tool.proped=Properties Editor
package uk.org.retep.tools;
import javax.swing.JMenuBar;
/**
* Tools can implement this interface to provide the parent manager (the big
* application or the StandaloneApp class) enough details to display them.
*
* If a tool does not implement this class, it gets basic treatment.
*
* @author
* @version 1.0
*/
public interface Tool
{
/**
* @return the JMenuBar for this tool, null if none.
*/
public JMenuBar getMenuBar();
/**
* @return the title string to go into the JFrame/JInternalFrame's title bar.
*/
public String getTitle();
/**
* Called by StandaloneApp to indicate this is within a StandaloneApp.
* You should assume you are not in standalone mode until this is called.
*/
public void setStandaloneMode(boolean aMode);
}
\ No newline at end of file
package uk.org.retep.util;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/**
* Display an Exception to the user
* @author
* @version 1.0
*/
public class ExceptionDialog extends JDialog
{
// This is used to store the parent frame.
// Classes like StandaloneApp set's this so that the
// displayException() method can work without knowing/finding out
// the parent Frame/JFrame.
private static Frame globalFrame;
private static ExceptionDialog globalDialog;
JPanel panel1 = new JPanel();
BorderLayout borderLayout1 = new BorderLayout();
JTextArea message = new JTextArea();
JPanel jPanel1 = new JPanel();
JButton jButton1 = new JButton();
GridLayout gridLayout1 = new GridLayout();
JButton jButton2 = new JButton();
JLabel jLabel1 = new JLabel();
public ExceptionDialog(Frame frame, String title, boolean modal)
{
super(frame, title, modal);
try
{
jbInit();
pack();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
public ExceptionDialog()
{
this(null, "", false);
}
void jbInit() throws Exception
{
panel1.setLayout(borderLayout1);
message.setBorder(BorderFactory.createLoweredBevelBorder());
message.setText("jTextArea1");
message.setBackground(Color.lightGray);
message.setEditable(false);
jButton1.setText("Close");
jButton1.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
jButton1_actionPerformed(e);
}
});
jPanel1.setLayout(gridLayout1);
jButton2.setEnabled(false);
jButton2.setText("Stack Trace");
jLabel1.setEnabled(false);
getContentPane().add(panel1);
panel1.add(message, BorderLayout.CENTER);
this.getContentPane().add(jPanel1, BorderLayout.SOUTH);
jPanel1.add(jButton2, null);
jPanel1.add(jLabel1, null);
jPanel1.add(jButton1, null);
}
/**
* Sets the Frame used to display all dialog boxes.
*/
public static void setFrame(Frame aFrame)
{
globalFrame = aFrame;
}
/**
* Displays a dialog based on the exception
* @param ex Exception that was thrown
*/
public static void displayException(Exception ex)
{
displayException(ex,null);
}
/**
* Displays a dialog based on the exception
* @param ex Exception that was thrown
*/
public static void displayException(Exception ex,String msg)
{
String cname = ex.getClass().getName();
int i=cname.lastIndexOf(".");
displayException(cname.substring(i+1),ex,msg);
}
public static void displayException(String title,Exception ex)
{
displayException(title,ex,null);
}
public static void displayException(String title,Exception ex,String msg)
{
Logger.log(Logger.ERROR,title,ex.getMessage());
// Default to a stack trace if no frame set
if(globalFrame==null) {
ex.printStackTrace();
return;
}
if(globalDialog==null) {
globalDialog=new ExceptionDialog(globalFrame,title,true);
globalDialog.pack();
}
globalDialog.setTitle(title);
if(msg!=null) {
globalDialog.message.setText(msg);
globalDialog.message.append(":\n");
}
globalDialog.message.append(ex.getMessage());
globalDialog.pack();
globalDialog.setVisible(true);
}
void jButton1_actionPerformed(ActionEvent e)
{
setVisible(false);
}
}
\ No newline at end of file
package uk.org.retep.util;
import uk.org.retep.util.Logger;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Properties;
/**
* This is a Singleton that stores global properties, command line arguments
* etc.
*
* All tools are guranteed that this will exist.
*
* @author
* @version 1.0
*/
public class Globals
{
private static final Globals SINGLETON = new Globals();
private Hashtable global= new Hashtable();
private Properties props = new Properties();
private ArrayList args = new ArrayList();
private Globals()
{
}
public static Globals getInstance()
{
return SINGLETON;
}
/**
* Retrieves an object from the global pool
* @param aKey key of the object
* @return The object, null if not found
*/
public Object get(Object aKey)
{
return global.get(aKey);
}
/**
* Stores an object into the global pool
* @param aKey key of the object
* @param aObj the object to store
* @return aObj
*/
public Object put(Object aKey,Object aObj)
{
return global.put(aKey,aObj);
}
/**
* Returns a Properties object of all properties
*/
/*
public Properties getProperties()
{
return props;
}
*/
/**
* @param aProp a property supplied to the command line
* @return property or NULL if not present
*/
public String getProperty(String aProp)
{
return props.getProperty(aProp);
}
/**
* @param aProp a property supplied to the command line
* @param aDefault default to return if property was not supplied
* @return property value
*/
public String getProperty(String aProp,String aDefault)
{
return props.getProperty(aProp,aDefault);
}
/**
* @param aID ID of the argument, 0 ... getArgumentCount()-1
* @return argument
*/
public String getArgument(int aID)
{
return (String) args.get(aID);
}
/**
* Returns an array of String objects representing the arguments
*/
public String[] getArguments()
{
return (String[]) args.toArray();
}
/**
* Returns an Iterator of the arguments
*/
public Iterator getArgumentIterator()
{
return args.iterator();
}
/**
* @return number of arguments
*/
public int getArgumentCount()
{
return args.size();
}
/**
* Parses the command line arguments
*/
public void parseArguments(String[] aArgs)
throws Exception
{
for(int i=0;i<aArgs.length;i++) {
String arg = aArgs[i];
if(arg.startsWith("--") || arg.startsWith("-")) {
if(arg.length()>1) {
// Split the option at the first '=' char if any
int s = arg.startsWith("--") ? 2 : 1 ; // -- or -
int e = arg.indexOf("=");
String key,val;
if(e>s) {
// Format: -key=value
key=arg.substring(s,e-1);
val=arg.substring(e+1);
} else if(e>-1 && e<=s) {
// Can't have a property without a key!
throw new Exception("Invalid option -=");
} else {
key=arg.substring(s);
val=""; // can't be null
}
if(key.equals("d")) {
// -d | --d is reserved to set the Logger level
int level=0;
if(!val.equals("")) {
level=Integer.parseInt(val);
}
Logger.setLevel(level);
} else {
// Add all other properties into the Properties object
props.put(key,val);
Logger.log(Logger.INFO,"Argument",key,val);
}
} else {
// Just a - on its own?
System.out.println("Unknown option: -");
}
} else {
// Add the argument to the array
args.add(arg);
}
}
}
}
\ No newline at end of file
package uk.org.retep.util;
import java.io.CharArrayWriter;
import java.io.PrintWriter;
public class Logger
{
protected static int level;
protected static PrintWriter logger;
public static final int NONE = -1;
public static final int INFO = 0;
public static final int ERROR = 1;
public static final int DEBUG = 2;
public static final int ALL = 3;
static {
level = NONE;
logger = null;
};
private static final String levels[] = {
"INFO :",
"ERROR:",
"DEBUG:",
"ALL :"
};
public static void setLevel(int aLevel)
{
// Incase we have not yet set a logger
if(logger==null) {
logger = new PrintWriter(System.out);
}
if(aLevel<NONE) {
aLevel=NONE;
} else if(aLevel>ALL) {
aLevel=ALL;
}
level=aLevel;
if(level>NONE) {
log(INFO,"Log level changed to",level,levels[level]);
}
}
public static void setLogger(PrintWriter pw)
{
if(logger!=null) {
try {
logger.flush();
logger.close();
} catch(Exception ex) {
logger=pw;
log(ERROR,"Exception while closing logger",ex);
}
}
logger=pw;
}
public static void log(String msg)
{
log(INFO,msg);
}
public static void log(int aLevel,String msg)
{
write(aLevel,msg,null);
}
public static void log(int aLevel,String msg,int arg1)
{
Object o[] = {new Integer(arg1)};
write(aLevel,msg,o);
}
public static void log(int aLevel,String msg,int arg1,Object arg2)
{
Object o[] = {new Integer(arg1),arg2};
write(aLevel,msg,o);
}
public static void log(int aLevel,String msg,double arg1)
{
Object o[] = {new Double(arg1)};
write(aLevel,msg,o);
}
public static void log(int aLevel,String msg,double arg1,Object arg2)
{
Object o[] = {new Double(arg1),arg2};
write(aLevel,msg,o);
}
public static void log(int aLevel,String msg,Object arg1)
{
Object o[] = {arg1};
write(aLevel,msg,o);
}
public static void log(int aLevel,String msg,Object arg1,Object arg2)
{
Object o[] = {arg1,arg2};
write(aLevel,msg,o);
}
public static void log(int aLevel,String msg,Object arg1,Object arg2,Object arg3)
{
Object o[] = {arg1,arg2,arg3};
write(aLevel,msg,o);
}
public static void log(int aLevel,String msg,Throwable t)
{
CharArrayWriter buffer = new CharArrayWriter();
PrintWriter printWriter = new PrintWriter(buffer);
t.printStackTrace(printWriter);
Object o[] = {buffer.toString()};
buffer.close();
write(aLevel,msg,o);
}
private static void write(int aLevel,String aMsg,Object args[])
{
// Can't be above ALL
if(aLevel>ALL) {
aLevel=ALL;
}
// Ignore if below or equal to NONE
if(aLevel<INFO || aLevel>level) {
return;
}
logger.print("Logger:");
logger.print(levels[aLevel]);
logger.print(aMsg);
if(args!=null) {
for(int a=0;a<args.length;a++) {
logger.print(":");
logger.print(args[a]);
}
}
logger.println();
logger.flush();
}
}
package uk.org.retep.util;
import uk.org.retep.util.StandaloneApp;
import javax.swing.JComponent;
import javax.swing.JLabel;
/**
* This is a template for your own Tools. Copy not extend this class. Please
* refer to Implementation for details.
*
* All you need to to is implement the init() method.
*
* $Id: Main.java,v 1.1 2001/03/05 09:15:36 peter Exp $
*/
public class Main extends StandaloneApp
{
public Main(String[] args)
throws Exception
{
super(args);
}
public JComponent init()
throws Exception
{
// Create your tool here, then do things like load files based on the
// command line arguments. Then return that tool.
// NB: This just allows us to compile. You're implementation must return
// the Tool itself.
return new JLabel("Replace with your own tool!");
}
public static void main(String[] args)
throws Exception
{
Main main = new Main(args);
main.pack();
main.setVisible(true);
}
}
package uk.org.retep.util;
import uk.org.retep.tools.Tool;
import uk.org.retep.util.Globals;
import uk.org.retep.util.ExceptionDialog;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/**
* This provides the basic services needed for enabling some of the tools to
* run in a Stand-alone fassion.
*
* Note: Because it's designed for standalone use, if this window is closed,
* the JVM is terminated. Do not use for normal application use.
*
* $Id: StandaloneApp.java,v 1.2 2001/03/05 10:18:48 peter Exp $
*
* @author
* @version 1.0
*/
public abstract class StandaloneApp extends JFrame
{
public StandaloneApp(String[] aArgs)
throws Exception
{
super(); // Initialise JFrame
// Allow dialogs to work with us
ExceptionDialog.setFrame(this);
// Add a window listener
this.addWindowListener(new java.awt.event.WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
// Parse the command line arguments
Globals.getInstance().parseArguments(aArgs);
// Now initialise this tool (init is overidden)
JComponent tool = null;
try {
tool = init();
} catch(Exception ex) {
ex.printStackTrace();
System.exit(1);
}
// Now add to this frame
this.getContentPane().add(tool, BorderLayout.CENTER);
// Finally call the Tool interface
if(tool instanceof Tool) {
Tool t = (Tool) tool;
// Notify the tool we are a standalone
t.setStandaloneMode(true);
// Fetch the title
setTitle(t.getTitle());
// and a MenuBar (if needed)
JMenuBar mb = t.getMenuBar();
if(mb!=null) {
setJMenuBar(t.getMenuBar());
}
} else {
// Ok, set a default title string
setTitle("RetepTools Standalone");
}
}
/**
* You must overide this method with your initialiser.
*/
public abstract JComponent init() throws Exception;
}
\ No newline at end of file
package uk.org.retep.util.hba;
import uk.org.retep.tools.Tool;
import uk.org.retep.util.models.HBATableModel;
import java.awt.*;
import java.io.*;
import java.util.*;
import javax.swing.table.*;
import javax.swing.*;
/**
* pg_hba.conf editor (& repairer)
*
* @author
* @version 1.0
*/
public class Editor extends JPanel implements Tool
{
BorderLayout borderLayout1 = new BorderLayout();
HBATableModel model = new HBATableModel();
JPanel jPanel1 = new JPanel();
GridBagLayout gridBagLayout1 = new GridBagLayout();
JLabel jLabel1 = new JLabel();
JComboBox typeEntry = new JComboBox();
JLabel jLabel2 = new JLabel();
JLabel jLabel3 = new JLabel();
JLabel jLabel4 = new JLabel();
JTextField ipEntry = new JTextField();
JTextField maskEntry = new JTextField();
JComboBox authEntry = new JComboBox();
JTextField argEntry = new JTextField();
JLabel jLabel5 = new JLabel();
JPanel jPanel2 = new JPanel();
FlowLayout flowLayout1 = new FlowLayout();
JButton jButton1 = new JButton();
JButton jButton2 = new JButton();
JScrollPane jScrollPane1 = new JScrollPane();
JButton jButton3 = new JButton();
JTable jTable1 = new JTable();
public Editor()
{
try
{
jbInit();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
void jbInit() throws Exception
{
this.setLayout(borderLayout1);
jTable1.setPreferredSize(new Dimension(600, 300));
jTable1.setModel(model);
this.setPreferredSize(new Dimension(600, 300));
this.add(jScrollPane1, BorderLayout.CENTER);
jScrollPane1.getViewport().add(jTable1, null);
jPanel1.setLayout(gridBagLayout1);
jLabel1.setText("Type");
jLabel2.setText("IP Address");
jLabel3.setText("Mask");
jLabel4.setText("Authentication");
ipEntry.setText("jTextField1");
maskEntry.setText("jTextField2");
argEntry.setText("jTextField3");
jLabel5.setText("Argument");
jPanel2.setLayout(flowLayout1);
jButton1.setText("New entry");
jButton2.setText("Validate");
jButton3.setText("Devele");
this.add(jPanel1, BorderLayout.SOUTH);
jPanel1.add(jLabel1, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0
,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
jPanel1.add(typeEntry, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0
,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
jPanel1.add(jLabel2, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0
,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
jPanel1.add(jLabel3, new GridBagConstraints(3, 1, 1, 1, 0.0, 0.0
,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
jPanel1.add(jLabel4, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0
,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
jPanel1.add(ipEntry, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0
,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
jPanel1.add(maskEntry, new GridBagConstraints(4, 1, 1, 1, 0.0, 0.0
,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
jPanel1.add(authEntry, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0
,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
jPanel1.add(argEntry, new GridBagConstraints(4, 2, 1, 1, 0.0, 0.0
,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
jPanel1.add(jLabel5, new GridBagConstraints(3, 2, 1, 1, 0.0, 0.0
,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
jPanel1.add(jPanel2, new GridBagConstraints(0, 3, 5, 1, 0.0, 0.0
,GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
jPanel2.add(jButton3, null);
jPanel2.add(jButton1, null);
jPanel2.add(jButton2, null);
}
public void openFile(String aFilename)
throws IOException
{
FileInputStream fis = new FileInputStream(aFilename);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
ArrayList list = model.getArray();
String s = br.readLine();
while(s!=null) {
if(s.startsWith("#")) {
// ignore comments
} else {
Record rec = Record.parseLine(s);
if(rec!=null) {
rec.validate();
list.add(rec);
}
}
s=br.readLine();
}
model.fireTableDataChanged();
}
public JMenuBar getMenuBar()
{
return null;
}
public String getTitle()
{
return "pg_hba.conf Editor/Repair tool";
}
public void setStandaloneMode(boolean aMode)
{
}
}
\ No newline at end of file
package uk.org.retep.util.hba;
import uk.org.retep.util.ExceptionDialog;
import uk.org.retep.util.Globals;
import uk.org.retep.util.Logger;
import uk.org.retep.util.StandaloneApp;
import java.io.IOException;
import javax.swing.JComponent;
import javax.swing.JPanel;
/**
* Standalone entry point for the Properties editor
*
* $Id: Main.java,v 1.1 2001/03/05 09:15:37 peter Exp $
*/
public class Main extends StandaloneApp
{
public Main(String[] args)
throws Exception
{
super(args);
}
public JComponent init()
throws Exception
{
Globals globals = Globals.getInstance();
Editor editor = new Editor();
if(globals.getArgumentCount()>0) {
editor.openFile(globals.getArgument(0));
}
return editor;
}
public static void main(String[] args)
throws Exception
{
Main main = new Main(args);
main.pack();
main.setVisible(true);
}
}
package uk.org.retep.util.hba;
import uk.org.retep.util.Logger;
import uk.org.retep.util.misc.IPAddress;
import uk.org.retep.util.misc.WStringTokenizer;
/**
* Used to store the entries of a pg_hba.conf file
* @author
* @version 1.0
*/
public class Record
{
int type;
String dbname;
IPAddress ip;
IPAddress mask;
int authType;
String authArg;
public static final int TYPE_LOCAL = 0;
public static final int TYPE_HOST = 1;
public static final int TYPE_HOSTSSL = 2;
public static final String types[] = {
"local","host","hostssl"
};
public static final int AUTH_TRUST = 0;
public static final int AUTH_PASSWORD = 1;
public static final int AUTH_CRYPT = 2;
public static final int AUTH_IDENT = 3;
public static final int AUTH_KRB4 = 4;
public static final int AUTH_KRB5 = 5;
public static final int AUTH_REJECT = 6;
public static final String auths[] = {
"trust","password","crypt",
"ident",
"krb4","krb5",
"reject"
};
private static final String spc = " ";
public Record()
{
}
public int getType()
{
return type;
}
public void setType(int aType)
{
type=aType;
}
public String getDatabase()
{
return dbname;
}
public void setDatabase(String aDB)
{
dbname=aDB;
}
public int getAuthType()
{
return authType;
}
public void setAuthType(int aType)
{
authType=aType;
}
public String getAuthArgs()
{
return authArg;
}
public void setAuthArgs(String aArg)
{
authArg=aArg;
}
public IPAddress getIP()
{
return ip;
}
public void setIP(String aArg)
{
setIP(new IPAddress(aArg));
}
public void setIP(IPAddress aArg)
{
ip=aArg;
}
public IPAddress getMask()
{
return mask;
}
public void setMask(String aArg)
{
setMask(new IPAddress(aArg));
}
public void setMask(IPAddress aArg)
{
mask=aArg;
}
public String toString()
{
StringBuffer buf = new StringBuffer();
write(buf);
return buf.toString();
}
public void write(StringBuffer buf)
{
buf.append(types[type]).append(spc);
if(type==TYPE_HOST || type==TYPE_HOSTSSL) {
buf.append(getIP()).append(spc);
buf.append(getMask()).append(spc);
}
buf.append(auths[authType]);
// Now the authArg
switch(type)
{
// These have no authArgs
case AUTH_TRUST:
case AUTH_REJECT:
case AUTH_KRB4:
case AUTH_KRB5:
break;
// These must have an arg
case AUTH_IDENT:
buf.append(spc).append(getAuthArgs());
break;
// These may have an optional arg
case AUTH_PASSWORD:
case AUTH_CRYPT:
if(!(authArg==null || authArg.equals("")))
buf.append(spc).append(getAuthArgs());
break;
}
}
private static WStringTokenizer tok;
public static Record parseLine(String s)
{
Record res = new Record();
int type;
if(s==null || s.equals("") || s.startsWith("#"))
return null;
if(tok==null)
tok=new WStringTokenizer();
tok.setString(s);
type=WStringTokenizer.matchToken(types,tok.nextToken());
res.setType(type);
res.setDatabase(tok.nextToken());
if(type==TYPE_HOST || type==TYPE_HOSTSSL) {
res.setIP(new IPAddress(tok.nextToken()));
res.setMask(new IPAddress(tok.nextToken()));
}
res.setAuthType(WStringTokenizer.matchToken(auths,tok.nextToken()));
res.setAuthArgs(tok.nextToken());
return res;
}
public static final int VALID = 0;
public static final int INVALID_TYPE = 1;
public static final int INVALID_IPREQUIRED = 2;
/**
* Validates the record
*/
public int validate()
{
switch(type)
{
case TYPE_HOST:
case TYPE_HOSTSSL:
if(ip==null || ip.isInvalid()) {
Logger.log(Logger.INFO,"pg_hba.conf: IP missing or invalid - repairing");
setMask("127.0.0.1");
}
if(mask==null || mask.isInvalid() || !ip.validateMask(mask)) {
Logger.log(Logger.INFO,"pg_hba.conf: IP address without mask - repairing");
setMask(ip.getMask());
}
break;
case TYPE_LOCAL:
break;
default:
return INVALID_TYPE;
}
return VALID;
}
/*
# host all 192.168.54.1 255.255.255.255 reject
# host all 0.0.0.0 0.0.0.0 krb5
# host all 192.168.0.0 255.255.0.0 ident omicron
#
local all trust
host all 127.0.0.1 255.255.255.255 trust
*/
}
\ No newline at end of file
package uk.org.retep.util.misc;
import java.util.StringTokenizer;
/**
* Represent an IP address
* @author
* @version 1.0
*/
public class IPAddress
{
protected long address;
protected long b[] = new long[4];
protected boolean invalid=true;
public IPAddress()
{
}
public IPAddress(String s)
{
setAddress(s);
}
public synchronized void setAddress(String s)
{
if(s==null || s.equals("")) {
invalid=true;
return;
}
address=0;
StringTokenizer tok = new StringTokenizer(s,".");
int i=0;
while(i<4 && tok.hasMoreElements()) {
b[i++] = Long.parseLong(tok.nextToken());
}
while(i<4) {
b[i++]=0;
}
invalid=false;
refresh();
}
public void refresh()
{
if(invalid)
return;
address = (b[0]<<24) | (b[1]<<16) | (b[2]<<8) | (b[3]);
}
public boolean isInvalid()
{
refresh();
return invalid;
}
public String toString()
{
refresh();
if(invalid)
return "*INVALID*";
return Long.toString(b[0])+"."+Long.toString(b[1])+"."+Long.toString(b[2])+"."+Long.toString(b[3]);
}
public boolean equals(Object o)
{
if(o instanceof IPAddress) {
IPAddress ip = (IPAddress) o;
refresh();
ip.refresh();
if(ip.invalid == invalid)
return false;
return address==ip.address;
}
return false;
}
private static int gethoststart(long b)
{
if((b & 0x80)==0x00) return 1; // class A
if((b & 0xc0)==0x80) return 2; // class B
if((b & 0xe0)==0xc0) return 3; // class C
return 4; // class D
}
public boolean validateMask(IPAddress mask)
{
// If were a network check the host mask
int i=gethoststart(b[0]);
System.out.println("Host start "+i);
while(i<4 && b[i]==0) {
if(mask.b[i++]>0)
return false;
}
for(i=0;i<4;i++) {
if((b[i]&mask.b[i])!=b[i])
return false;
}
return true;
}
public IPAddress getMask()
{
IPAddress mask = new IPAddress();
int i=3;
while(i>-1 && b[i]==0) {
mask.b[i--]=0;
}
while(i>-1) {
mask.b[i--]=255;
}
mask.invalid=false;
mask.refresh();
return mask;
}
}
\ No newline at end of file
package uk.org.retep.util.misc;
import java.io.*;
import java.util.Date;
import java.util.Iterator;
import java.util.Properties;
import java.util.TreeMap;
/**
* Misc Properties utilities..
* @author
* @version 1.0
*/
public class PropertiesIO
{
public PropertiesIO()
{
}
/**
* Builds a TreeMap based on the given Properties object. This is useful
* because the keys will be in sorted order.
*/
public static TreeMap getTreeMap(Properties p)
{
TreeMap map = new TreeMap();
Iterator e = p.keySet().iterator();
while(e.hasNext()) {
Object k = e.next();
map.put(k,p.get(k));
}
return map;
}
/**
* Writes a Properties file to the writer. This is similar to Properties.save
* except you can pick the key/value separator
*/
public static synchronized void save(Properties p,OutputStream out,char sep,String header)
throws IOException
{
save(p,p.keySet().iterator(),out,sep,header);
}
/**
* Writes a Properties file to the writer. This is similar to Properties.save
* except you can pick the key/value separator and the keys are written
* in a sorted manner
*/
public static synchronized void saveSorted(Properties p,OutputStream out,char sep,String header)
throws IOException
{
save(p,getTreeMap(p).keySet().iterator(),out,sep,header);
}
/**
* This is the same as save, only the keys in the enumeration are written.
*/
public static synchronized void save(Properties p,Iterator e, OutputStream out,char sep,String header)
throws IOException
{
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(out, "8859_1"));
if (header != null) {
w.write('#');
w.write(header);
w.newLine();
}
w.write('#');
w.write(new Date().toString());
w.newLine();
while(e.hasNext()) {
String key = (String)e.next();
w.write(encode(key,true));
w.write(sep);
w.write(encode((String)p.get(key),false));
w.newLine();
}
w.flush();
}
private static final String specialSaveChars = "=: \t\r\n\f#!";
/**
* Encodes a string in a way similar to the JDK's Properties method
*/
public static String encode(String s, boolean escapeSpace)
{
int l=s.length();
StringBuffer buf = new StringBuffer(l<<1);
for(int i=0;i<l;i++) {
char c = s.charAt(i);
switch(c)
{
case ' ':
if(i==0 || escapeSpace) {
buf.append('\\');
}
buf.append(' ');
break;
case '\\':
buf.append('\\').append('\\');
break;
case '\t':
buf.append('\\').append('t');
break;
case '\n':
buf.append('\\').append('n');
break;
case '\r':
buf.append('\\').append('r');
break;
case '\f':
buf.append('\\').append('f');
break;
default:
if((c<0x20)||(c>0x7e)) {
buf.append('\\').append('u');
buf.append(toHex((c >> 12) & 0xF));
buf.append(toHex((c >> 8) & 0xF));
buf.append(toHex((c >> 4) & 0xF));
buf.append(toHex( c & 0xF));
} else {
if (specialSaveChars.indexOf(c) != -1)
buf.append('\\');
buf.append(c);
}
}
}
return buf.toString();
}
/**
* Convert a nibble to a hex character
* @param nibble the nibble to convert.
*/
public static char toHex(int n) {
return hd[(n & 0xF)];
}
/** A table of hex digits */
private static final char[] hd = {
'0','1','2','3','4','5','6','7',
'8','9','A','B','C','D','E','F'
};
}
\ No newline at end of file
package uk.org.retep.util.misc;
/**
* Similar to StringTokenizer but handles white spaces and multiple delimiters
* between tokens. It also handles quotes
*
* @author
* @version 1.0
*/
public class WStringTokenizer
{
String string;
int pos,len;
/**
* Constructor
*/
public WStringTokenizer()
{
}
/**
* Constructor: set the initial string
* @param aString String to tokenise
*/
public WStringTokenizer(String aString)
{
setString(aString);
}
/**
* @param aString String to tokenise
*/
public void setString(String aString)
{
string=aString;
pos=0;
len=string.length();
}
/**
* @return true if more tokens may be possible
*/
public boolean hasMoreTokens()
{
return !(string==null || pos==len);
}
/**
* @return next token, null if complete.
*/
public String nextToken()
{
char c;
boolean q=false;
if(!hasMoreTokens())
return null;
// find start of token
while(pos<len) {
c = string.charAt(pos);
if(c=='\'' || c=='\"')
q=!q;
if(q || c==' '||c=='\t')
pos++;
else
break;
}
// find last char of token
int p=pos;
while(pos<len) {
c = string.charAt(pos);
if(c=='\'' || c=='\"')
q=!q;
if(!q && (c==' '||c=='\t') )
break;
else
pos++;
}
return string.substring(p,pos);
}
/**
* Compare a string against an array of strings and return the index
* @param t array to compare against (all lowercase)
* @param s string to test
* @return index in t of s, -1 if not present
*/
public static int matchToken(String[] t,String s)
{
s=s.toLowerCase();
for(int i=0;i<t.length;i++)
if(t[i].equals(s))
return i;
return -1;
}
}
\ No newline at end of file
package uk.org.retep.util.models;
import uk.org.retep.util.hba.Record;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.table.*;
/**
* A TableModel to display the contents of a pg_hba.conf file
* @author
* @version 1.0
*/
public class HBATableModel extends AbstractTableModel
{
ArrayList list = new ArrayList();
private static final String cols[] = {
"Type","Database","IP Address","IP Mask","Authentication","Arguments"
};
public HBATableModel()
{
}
public ArrayList getArray()
{
return list;
}
public int getColumnCount()
{
return cols.length;
}
public Object getValueAt(int aRow, int aCol)
{
Record rec = (Record) list.get(aRow);
int t;
switch(aCol)
{
case 0:
t = rec.getType();
return t<0 ? "ERR" : Record.types[t] ;
case 1:
return rec.getDatabase();
case 2:
return rec.getIP();
case 3:
return rec.getMask();
case 4:
t=rec.getAuthType();
return t<0 ? "ERR" : Record.auths[t] ;
case 5:
return rec.getAuthArgs();
default:
return "";
}
}
public int getRowCount()
{
return list.size();
}
public boolean isCellEditable(int rowIndex, int columnIndex)
{
/**@todo: Override this javax.swing.table.AbstractTableModel method*/
return super.isCellEditable( rowIndex, columnIndex);
}
public String getColumnName(int aColumn)
{
return cols[aColumn];
}
public void setValueAt(Object aValue, int rowIndex, int columnIndex)
{
/**@todo: Override this javax.swing.table.AbstractTableModel method*/
super.setValueAt( aValue, rowIndex, columnIndex);
}
}
\ No newline at end of file
package uk.org.retep.util.models;
import uk.org.retep.util.Logger;
import uk.org.retep.util.misc.PropertiesIO;
import java.io.*;
import java.util.*;
import javax.swing.table.*;
import java.text.*;
/**
* A TableModel that shows a view of a PropertyFile object
*
* $Id: PropertiesTableModel.java,v 1.1 2001/03/05 09:15:37 peter Exp $
*
* @author
* @version 1.0
*/
public class PropertiesTableModel extends AbstractTableModel
{
// The properties
protected TreeMap properties;
protected Properties origProperties;
protected Object keys[];
public PropertiesTableModel()
{
this(new Properties());
}
public PropertiesTableModel(Properties aProperties)
{
setProperties(aProperties);
}
public synchronized int getKeyRow(Object k)
{
for(int i=0;i<keys.length;i++) {
if(keys[i].equals(k)) {
return i;
}
}
return -1;
}
/**
* Best not use this one to update, use the put method in this class!
*/
public Properties getProperties()
{
return origProperties;
}
public synchronized void put(Object k,Object v)
{
properties.put(k,v);
origProperties.put(k,v);
refresh();
}
public Object get(Object k)
{
return origProperties.get(k);
}
public synchronized void remove(Object k)
{
properties.remove(k);
origProperties.remove(k);
refresh();
}
public boolean contains(Object o)
{
return origProperties.contains(o);
}
public boolean containsKey(Object o)
{
return origProperties.containsKey(o);
}
public boolean containsValue(Object o)
{
return origProperties.containsValue(o);
}
public void setProperties(Properties aProperties)
{
origProperties=aProperties;
properties = PropertiesIO.getTreeMap(aProperties);
refresh();
}
public void refresh()
{
keys = properties.keySet().toArray();
fireTableDataChanged();
}
private static final String cols[] = {
"Property","Value"
};
public int getColumnCount()
{
return cols.length;
}
public Object getValueAt(int aRow, int aColumn)
{
if(aRow<0 || aRow>=keys.length || aColumn<0 || aColumn>=cols.length)
return null;
Object key = keys[aRow];
switch(aColumn)
{
case 0:
return key;
case 1:
return properties.get(key);
default:
return null;
}
}
public int getRowCount()
{
return keys.length;
}
public String getColumnName(int aColumn)
{
return cols[aColumn];
}
public void setValueAt(Object aValue, int aRow, int aColumn)
{
if(aRow<0 || aRow>=keys.length || aColumn<0 || aColumn>=cols.length)
return;
switch(aColumn)
{
// Rename the key (only if not already present). If already present
// the refresh() will replace with the old one anyhow...
case 0:
if(!properties.containsKey(aValue)) {
Object oldValue = get(keys[aRow]);
remove(keys[aRow]);
put(aValue,oldValue);
}
refresh();
break;
// Update the value...
case 1:
put(keys[aRow],aValue);
//refresh();
break;
default:
// Should never be called
Logger.log(Logger.ERROR,"PropertiesTableModel: Column range",aColumn);
}
}
public boolean isCellEditable(int aRow, int aColumn)
{
return true;
}
}
package uk.org.retep.util.proped;
import uk.org.retep.util.ExceptionDialog;
import uk.org.retep.util.Globals;
import uk.org.retep.util.Logger;
import uk.org.retep.util.StandaloneApp;
import java.io.IOException;
import java.util.Iterator;
import javax.swing.JComponent;
/**
* Standalone entry point for the Properties editor
*
* $Id: Main.java,v 1.1 2001/03/05 09:15:38 peter Exp $
*/
public class Main extends StandaloneApp
{
public Main(String[] args)
throws Exception
{
super(args);
}
public JComponent init()
throws Exception
{
Globals globals = Globals.getInstance();
PropertyEditor panel = new PropertyEditor();
// Only handle 1 open at a time in standalone mode
if(globals.getArgumentCount()>0) {
try {
panel.openFile(globals.getArgument(0));
} catch(IOException ioe) {
ExceptionDialog.displayException(ioe,"while loading "+globals.getArgument(0));
throw (Exception) ioe.fillInStackTrace();
}
}
return panel;
}
public static void main(String[] args)
throws Exception
{
Main main = new Main(args);
main.pack();
main.setVisible(true);
}
}
\ No newline at end of file
package uk.org.retep.util.proped;
import uk.org.retep.util.ExceptionDialog;
import uk.org.retep.util.misc.PropertiesIO;
import uk.org.retep.util.models.PropertiesTableModel;
import java.awt.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import java.awt.event.*;
/**
* A property file editor
*
* $Id: PropertyEditor.java,v 1.1 2001/03/05 09:15:38 peter Exp $
*
* @author
* @version 1.0
*/
public class PropertyEditor
extends JPanel
implements uk.org.retep.tools.Tool
{
BorderLayout borderLayout1 = new BorderLayout();
// The filename, null if not set
String filename;
File file;
JScrollPane jScrollPane1 = new JScrollPane();
JTable contentTable = new JTable();
PropertiesTableModel model = new PropertiesTableModel();
boolean standaloneMode;
private static final String TITLE_PREFIX = "Retep PropertyEditor";
JPopupMenu popupMenu = new JPopupMenu();
JMenuItem newPopupItem = new JMenuItem();
JMenuItem dupPopupItem = new JMenuItem();
JMenuItem delPopupItem = new JMenuItem();
JMenuBar menuBar = new JMenuBar();
JMenu jMenu1 = new JMenu();
JMenuItem jMenuItem4 = new JMenuItem();
JMenuItem jMenuItem5 = new JMenuItem();
JMenuItem jMenuItem6 = new JMenuItem();
JMenuItem jMenuItem7 = new JMenuItem();
JMenuItem jMenuItem8 = new JMenuItem();
JMenuItem closeMenuItem = new JMenuItem();
public PropertyEditor()
{
try
{
jbInit();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
/**
* @return the default menubar
*/
public JMenuBar getMenuBar()
{
return menuBar;
}
/**
* @return the File menu
*/
public JMenu getMenu()
{
return jMenu1;
}
/**
* @return the recomended title string for the parent JFrame/JInternalFrame
*/
public String getTitle()
{
if(filename==null) {
return TITLE_PREFIX;
}
return TITLE_PREFIX+": "+filename;
}
/**
* Sets menus up to Standalone mode
*/
public void setStandaloneMode(boolean aMode)
{
standaloneMode=aMode;
if(aMode) {
closeMenuItem.setText("Exit");
} else {
closeMenuItem.setText("Close");
}
}
public boolean isStandalone()
{
return standaloneMode;
}
public void openFile(String aFile)
throws IOException
{
openFile(new File(aFile));
}
public void openFile(File aFile)
throws IOException
{
FileInputStream fis = new FileInputStream(aFile);
Properties p = new Properties();
p.load(fis);
fis.close();
model.setProperties(p);
file=aFile;
filename = aFile.getAbsolutePath();
}
public void saveFile(File aFile)
throws IOException
{
FileOutputStream fis = new FileOutputStream(aFile);
PropertiesIO.save(model.getProperties(),fis,'=',"Written by "+TITLE_PREFIX);
fis.close();
filename = aFile.getAbsolutePath();
file = aFile;
}
void jbInit() throws Exception
{
this.setLayout(borderLayout1);
contentTable.setToolTipText("");
contentTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
contentTable.setModel(model);
contentTable.addMouseListener(new java.awt.event.MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
contentTable_mouseClicked(e);
}
public void mouseReleased(MouseEvent e)
{
contentTable_mouseReleased(e);
}
});
newPopupItem.setText("New");
newPopupItem.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
newPopupItem_actionPerformed(e);
}
});
dupPopupItem.setText("Duplicate");
dupPopupItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(67, java.awt.event.KeyEvent.CTRL_MASK, false));
dupPopupItem.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
dupPopupItem_actionPerformed(e);
}
});
delPopupItem.setText("Delete");
delPopupItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(68, java.awt.event.KeyEvent.CTRL_MASK, false));
delPopupItem.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
delPopupItem_actionPerformed(e);
}
});
jMenu1.setText("File");
jMenuItem4.setText("Open");
jMenuItem4.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
jMenuItem4_actionPerformed(e);
}
});
jMenuItem5.setText("Save");
jMenuItem5.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
jMenuItem5_actionPerformed(e);
}
});
jMenuItem6.setText("Save As");
jMenuItem6.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
jMenuItem6_actionPerformed(e);
}
});
jMenuItem7.setText("Revert");
jMenuItem7.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
jMenuItem7_actionPerformed(e);
}
});
jMenuItem8.setText("Print");
closeMenuItem.setText("Close");
closeMenuItem.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
closeMenuItem_actionPerformed(e);
}
});
jMenu2.setText("Edit");
jMenuItem1.setText("New");
jMenuItem1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(78, java.awt.event.KeyEvent.CTRL_MASK, false));
jMenuItem1.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
newPopupItem_actionPerformed(e);
}
});
jMenuItem2.setText("Duplicate");
jMenuItem3.setText("Delete");
this.add(jScrollPane1, BorderLayout.CENTER);
jScrollPane1.getViewport().add(contentTable, null);
popupMenu.add(newPopupItem);
popupMenu.add(dupPopupItem);
popupMenu.add(delPopupItem);
menuBar.add(jMenu1);
menuBar.add(jMenu2);
jMenu1.add(jMenuItem4);
jMenu1.add(jMenuItem5);
jMenu1.add(jMenuItem6);
jMenu1.add(jMenuItem7);
jMenu1.addSeparator();
jMenu1.add(jMenuItem8);
jMenu1.addSeparator();
jMenu1.add(closeMenuItem);
jMenu2.add(jMenuItem1);
jMenu2.add(jMenuItem2);
jMenu2.add(jMenuItem3);
}
Point popupPoint = new Point();
JMenu jMenu2 = new JMenu();
JMenuItem jMenuItem1 = new JMenuItem();
JMenuItem jMenuItem2 = new JMenuItem();
JMenuItem jMenuItem3 = new JMenuItem();
void contentTable_mouseClicked(MouseEvent e)
{
if(e.isPopupTrigger()) {
popupPoint.setLocation(e.getX(),e.getY());
popupMenu.show(contentTable,e.getX(),e.getY());
}
}
void contentTable_mouseReleased(MouseEvent e)
{
contentTable_mouseClicked(e);
}
void jMenuItem4_actionPerformed(ActionEvent e)
{
JFileChooser fc = new JFileChooser();
if(fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
try {
openFile(fc.getSelectedFile());
} catch(IOException ioe) {
ExceptionDialog.displayException(ioe);
}
}
}
void closeMenuItem_actionPerformed(ActionEvent e)
{
if(standaloneMode) {
System.exit(0);
} else {
filename="";
file=null;
model.setProperties(new Properties());
}
}
void newPopupItem_actionPerformed(ActionEvent e)
{
int y = contentTable.rowAtPoint(popupPoint);
// create a new unique key based on the current one
String key=(String) model.getValueAt(y,0);
if(key==null) {
key="new-key";
}
int uid=1;
while(model.containsKey(key+uid)) {
uid++;
}
key=key+uid;
model.put(key,"");
contentTable.clearSelection();
}
void dupPopupItem_actionPerformed(ActionEvent e)
{
int y = contentTable.rowAtPoint(popupPoint);
// create a new unique key based on the current one
String key=(String) model.getValueAt(y,0);
Object val=model.get(key);
int uid=1;
while(model.containsKey(key+uid)) {
uid++;
}
key=key+uid;
model.put(key,val);
contentTable.clearSelection();
}
void delPopupItem_actionPerformed(ActionEvent e)
{
int y = contentTable.rowAtPoint(popupPoint);
model.remove(model.getValueAt(y,0));
}
void jMenuItem6_actionPerformed(ActionEvent e)
{
JFileChooser fc = new JFileChooser();
if(fc.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
try {
saveFile(fc.getSelectedFile());
} catch(IOException ioe) {
ExceptionDialog.displayException(ioe);
}
}
}
void jMenuItem5_actionPerformed(ActionEvent e)
{
if(filename==null) {
jMenuItem6_actionPerformed(e);
} else {
try {
saveFile(file);
} catch(IOException ioe) {
ExceptionDialog.displayException(ioe);
}
}
}
void jMenuItem7_actionPerformed(ActionEvent e)
{
// add check here
if(file!=null) {
try {
openFile(file);
} catch(IOException ioe) {
ExceptionDialog.displayException(ioe);
}
} else {
jMenuItem4_actionPerformed(e);
}
}
}
\ No newline at end of file
package uk.org.retep.xml.core;
import java.io.IOException;
import java.io.Writer;
/**
* An XMLFactory is used to render XML Tags, accounting for nesting etc
*/
public class XMLFactory
{
/**
* The lest level (ie, how many tags down the tree we are)
*/
protected int level;
/**
* The size of our tag name cache
*/
protected int maxlevel;
/**
* Our tag name cache
*/
protected String[] names;
/**
* Used to keep track of how formatting is done
*/
protected boolean hascontent;
protected boolean[] contbuf;
/**
* Scratch used by nest()
*/
private char[] nestbuf;
/**
* The destination Writer
*/
protected Writer out;
/**
* True if we are still within a tag
*/
protected boolean inTag;
/**
* True if we have just created a tag so parameters are valid
*/
protected boolean inArg;
/**
* Constructs an XMLFactory with no output Writer
*/
public XMLFactory()
{
this(10);
}
/**
* Constructs an XMLFactory with no output Writer
* @param m Expected number of leaves in the XML Tree
*/
public XMLFactory(int m)
{
// Initialise the names cache
level=0;
maxlevel=m;
names=new String[maxlevel];
contbuf=new boolean[maxlevel];
// This is used by nest()
nestbuf=new char[maxlevel];
for(int i=0;i<maxlevel;i++)
nestbuf[i]=' ';
}
/**
* Constructs an XMLFactory
* @param out Writer to send the output to
*/
public XMLFactory(Writer out)
throws IOException
{
this();
setWriter(out);
}
/**
* Constructs an XMLFactory
* @param out Writer to send the output to
* @param encoding The XML encoding
*/
public XMLFactory(Writer out,String encoding)
throws IOException
{
this();
setWriter(out,encoding);
}
/**
* Constructs an XMLFactory
* @param out Writer to send the output to
* @param m Expected number of leaves in the XML Tree
*/
public XMLFactory(int m,Writer out)
throws IOException
{
this(m);
setWriter(out);
}
/**
* Constructs an XMLFactory
* @param out Writer to send the output to
* @param encoding The XML encoding
* @param m Expected number of leaves in the XML Tree
*/
public XMLFactory(int m,Writer out,String encoding)
throws IOException
{
this(m);
setWriter(out,encoding);
}
/**
* Sets the Writer to send the output to. This call will also send the
* XML header.
*
* @param out Writer to send output to
*/
public void setWriter(Writer out)
throws IOException
{
setWriter(out,"ISO-8859-1");
}
/**
* Sets the Writer to send the output to. This call will also send the
* XML header using the supplied encoding. It is up to the user code to
* implement this encoding.
*
* @param out Writer to send output to
* @param encoding Encoding of the XML Output
*/
public void setWriter(Writer out,String encoding)
throws IOException
{
this.out=out;
out.write("<?xml version=\"1.0\" encoding=\"");
out.write(encoding);
out.write("\" ?>\n");
}
/**
* @return Writer the XML is being sent out on.
*/
public Writer getWriter() {
return out;
}
/**
* This starts a tag
* @param name The tag name
*/
public void startTag(String name)
throws IOException
{
if(inTag && inArg) {
// Handles two startTag() calls in succession.
out.write(">");
}
nest(level);
out.write('<');
out.write(name);
inTag=true;
inArg=true;
// cache the current tag name
names[level]=name;
// cache the current hascontent value & reset
contbuf[level]=hascontent;
hascontent=false;
// increase the level and the cache's as necessary
level++;
if(level>maxlevel) {
maxlevel=maxlevel+10;
String n[]=new String[maxlevel];
System.arraycopy(names,0,n,0,level);
names=n;
boolean b[] = new boolean[maxlevel];
System.arraycopy(contbuf,0,b,0,level);
contbuf=b;
}
}
/**
* This ends a tag
*/
public void endTag()
throws IOException, XMLFactoryException
{
if(level<1)
throw new XMLFactoryException("endTag called above root node");
level--;
if(inArg) {
// We are still within the opening tag
out.write(" />");
} else {
// We must have written some content or child tags
// hascontent is true if addContent() was called. If it was never called
// to get here some child tags must have been written, so we call nest()
// so that the close tag is on it's own line, and everything looks neat
// and tidy.
if(!hascontent)
nest(level);
out.write("</");
out.write(names[level]);
out.write('>');
}
inArg=false; // The parent tag must be told it now has content
inTag= level>0; // Are we still in a tag?
hascontent=contbuf[level]; // retrieve this level's hascontent value
}
/**
* This completes the document releasing any open resources.
*/
public void close()
throws IOException, XMLFactoryException
{
while(level>0)
endTag();
out.write('\n');
out.flush();
}
/**
* This writes an attribute to the current tag. If the value is null, then no action is taken.
* @param name Name of the parameter
* @param value Value of the parameter
* @throw XMLFactoryException if out of context
*/
public void addAttribute(String name,Object value)
throws IOException, XMLFactoryException
{
if(value==null)
return;
if(inArg) {
out.write(' ');
out.write(name);
out.write("=\"");
out.write(encode(value.toString()));
out.write("\"");
} else
throw new XMLFactoryException("Cannot add attribute outside of a tag");
}
/**
* This writes some content to the current tag. Once this has been called,
* you cannot add any more attributes to the current tag. Note, if c is null,
* no action is taken.
* @param c content to add.
*/
public void addContent(Object c)
throws IOException, XMLFactoryException
{
if(c==null)
return;
if(inTag) {
if(inArg) {
// close the open tag
out.write('>');
inArg=false;
}
out.write(c.toString());
// This is used by endTag()
hascontent=true;
} else
throw new XMLFactoryException("Cannot add content outside of a tag");
}
/**
* This adds a comment to the XML file. This is normally used at the start of
* any XML output.
* @parm c Comment to include
*/
public void addComment(Object c)
throws IOException, XMLFactoryException
{
if(inTag)
throw new XMLFactoryException("Cannot add comments within a tag");
out.write("\n<!-- ");
out.write(c.toString());
out.write(" -->");
}
/**
* Indents the output according to the level
* @param level The indent level to generate
*/
protected void nest(int level)
throws IOException
{
out.write('\n');
while(level>nestbuf.length) {
out.write(nestbuf,0,nestbuf.length);
level-=nestbuf.length;
}
out.write(nestbuf,0,level);
}
/**
* Encodes the string so that any XML tag chars are translated
*/
protected String encode(String s) {
return s;
}
}
\ No newline at end of file
package uk.org.retep.xml.core;
/**
* Title:
* Description:
* Copyright: Copyright (c) 2001
* Company:
* @author
* @version 1.0
*/
public class XMLFactoryException extends Exception
{
public XMLFactoryException(String s)
{
super(s);
}
}
\ No newline at end of file
package uk.org.retep.xml.jdbc;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import uk.org.retep.xml.core.XMLFactory;
import uk.org.retep.xml.core.XMLFactoryException;
public class XMLDatabase
{
/**
* The XMLFactory being used by this instance
*/
protected XMLFactory factory;
/**
* Constructor. setXMLFactory() must be called if this method is used.
*/
public XMLDatabase()
{
}
/**
* Constructor
* @param fac XMLFactory to use
*/
public XMLDatabase(XMLFactory fac)
{
this();
setXMLFactory(fac);
}
/**
* Sets the factory to use.
* @param factory XMLFactory to use
*/
public void setXMLFactory(XMLFactory factory)
{
this.factory=factory;
}
/**
* @return the XMLFactory being used.
*/
public XMLFactory getXMLFactory()
{
return factory;
}
/**
* Flushes all output to the Writer.
* @throw IOException from Writer
* @throw XMLFactoryException from XMLFactory
*/
public void close()
throws IOException, XMLFactoryException
{
factory.close();
}
/**
* writes the schema of a table.
* @param con Connection to database
* @param table Table name
* @throw IOException from Writer
* @throw SQLException from JDBC
* @throw XMLFactoryException from XMLFactory
*/
public void writeTable(Connection con,String table)
throws IOException,SQLException,XMLFactoryException
{
writeTable(con.getMetaData(),table);
}
/**
* writes the schema of a table.
* @param db DatabaseMetaData for the database
* @param table Table name
* @throw IOException from Writer
* @throw SQLException from JDBC
* @throw XMLFactoryException from XMLFactory
*/
public void writeTable(DatabaseMetaData db,String table)
throws IOException,SQLException,XMLFactoryException
{
writeTable(db,null,null,table);
}
/**
* writes the schema of a table.
* @param db DatabaseMetaData for the database
* @param table Table name
* @throw IOException from Writer
* @throw SQLException from JDBC
* @throw XMLFactoryException from XMLFactory
*/
public void writeTable(DatabaseMetaData db,String cat,String schem,String table)
throws IOException,SQLException,XMLFactoryException
{
ResultSet trs;
factory.startTag("TABLE");
factory.addAttribute("NAME",table);
// fetch the remarks for this table (if any)
trs = db.getTables(null,null,table,null);
if(trs!=null) {
if(trs.next()) {
String rem = trs.getString(5);
if(rem!=null)
factory.addContent(rem);
}
trs.close();
}
trs = db.getColumns(null,null,table,"%");
if(trs!=null) {
while(trs.next()) {
factory.startTag("COLUMN");
factory.addAttribute("NAME",trs.getString(4));
factory.addAttribute("TYPE",trs.getString(6));
factory.addAttribute("COLUMN_SIZE",trs.getString(7));
factory.addAttribute("DECIMAL_DIGITS",trs.getString(9));
factory.addAttribute("NUM_PREC_RADIX",trs.getString(10));
factory.addAttribute("NULLABLE",trs.getString(11));
factory.addAttribute("COLUMN_DEF",trs.getString(13));
factory.addAttribute("CHAR_OCTET_LENGTH",trs.getString(16));
factory.addAttribute("ORDINAL_POSITION",trs.getString(17));
factory.addAttribute("IS_NULLABLE",trs.getString(18));
factory.addAttribute("TABLE_CAT",trs.getString(1));
factory.addAttribute("TABLE_SCHEM",trs.getString(2));
String rem = trs.getString(12);
if(rem!=null)
factory.addContent(rem);
factory.endTag();
}
trs.close();
}
factory.endTag();
}
/**
* This generates the schema of an entire database.
* @param db Connection to database
* @param table Table pattern
* @throw IOException from Writer
* @throw SQLException from JDBC
* @throw XMLFactoryException from XMLFactory
* @see java.sql.DatabaseMetaData.getTables()
*/
public void writeDatabase(Connection db,String table)
throws IOException, SQLException, XMLFactoryException
{
writeDatabase(db.getMetaData(),null,null,table);
}
/**
* This generates the schema of an entire database.
* @param db DatabaseMetaData of database
* @param table Table pattern
* @throw IOException from Writer
* @throw SQLException from JDBC
* @throw XMLFactoryException from XMLFactory
* @see java.sql.DatabaseMetaData.getTables()
*/
public void writeDatabase(DatabaseMetaData db,String table)
throws IOException, SQLException, XMLFactoryException
{
writeDatabase(db,null,null,table);
}
/**
* This generates the schema of an entire database.
* @param db DatabaseMetaData of database
* @param cat Catalog (may be null)
* @param schem Schema (may be null)
* @param table Table pattern
* @throw IOException from Writer
* @throw SQLException from JDBC
* @throw XMLFactoryException from XMLFactory
* @see java.sql.DatabaseMetaData.getTables()
*/
public void writeDatabase(Connection db)
throws IOException, SQLException, XMLFactoryException
{
writeDatabase(db.getMetaData(),null,null,"%");
}
/**
* This generates the schema of an entire database.
* @param db DatabaseMetaData of database
* @param cat Catalog (may be null)
* @param schem Schema (may be null)
* @param table Table pattern
* @throw IOException from Writer
* @throw SQLException from JDBC
* @throw XMLFactoryException from XMLFactory
* @see java.sql.DatabaseMetaData.getTables()
*/
public void writeDatabase(DatabaseMetaData db)
throws IOException, SQLException, XMLFactoryException
{
writeDatabase(db,null,null,"%");
}
/**
* This generates the schema of an entire database.
* @param db DatabaseMetaData of database
* @param cat Catalog (may be null)
* @param schem Schema (may be null)
* @param table Table pattern
* @throw IOException from Writer
* @throw SQLException from JDBC
* @throw XMLFactoryException from XMLFactory
* @see java.sql.DatabaseMetaData.getTables()
*/
public void writeDatabase(DatabaseMetaData db,String cat,String schem,String table)
throws IOException, SQLException, XMLFactoryException
{
ResultSet rs = db.getTables(cat,schem,table,null);
if(rs!=null) {
factory.startTag("DATABASE");
factory.addAttribute("PRODUCT",db.getDatabaseProductName());
factory.addAttribute("VERSION",db.getDatabaseProductVersion());
while(rs.next()) {
writeTable(db,rs.getString(1),rs.getString(2),rs.getString(3));
}
factory.endTag();
rs.close();
}
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
package uk.org.retep.xml.parser;
import java.util.HashMap;
import java.io.CharArrayWriter;
/**
* This interface defines the methods a class needs to implement if it wants the
* xml parser to notify it of any xml tags.
*/
public interface TagListener {
/**
* This is called when a tag has just been started.
* <p><b>NB:</b> args is volatile, so if you use it beyond the lifetime of
* this call, then you must make a copy of the HashMap (and not use simply
* store this HashMap).
* @param level The number of tags above this
* @param tag The tag name
* @param args A HashMap of any arguments
*/
public void tagStart(int level,String tag,HashMap args);
/**
* This method is called by ContHandler to process a tag once it has been
* fully processed.
* <p><b>NB:</b> content is volatile, so you must copy its contents if you use
* it beyond the lifetime of this call.
* @param content CharArrayWriter containing the content of the tag.
*/
public void tagContent(CharArrayWriter content);
}
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment