mirror of https://github.com/postgres/postgres
parent
5bbad66e0e
commit
e2e84a1c5e
@ -1,4 +1,7 @@ |
||||
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 |
||||
- Finished the XML Export classes |
||||
- First of the test data suite now in CVS. |
||||
|
||||
|
||||
@ -0,0 +1,116 @@ |
||||
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. |
||||
|
||||
@ -0,0 +1,35 @@ |
||||
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. |
||||
|
||||
@ -0,0 +1,228 @@ |
||||
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); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,43 @@ |
||||
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; |
||||
} |
||||
@ -0,0 +1,31 @@ |
||||
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; |
||||
} |
||||
@ -0,0 +1,30 @@ |
||||
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(); |
||||
} |
||||
} |
||||
@ -0,0 +1,97 @@ |
||||
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); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,233 @@ |
||||
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); |
||||
} |
||||
} |
||||
@ -0,0 +1,233 @@ |
||||
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; |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,191 @@ |
||||
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
|
||||
|
||||
} |
||||
@ -0,0 +1,133 @@ |
||||
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; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,8 @@ |
||||
#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 |
||||
@ -0,0 +1,33 @@ |
||||
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); |
||||
|
||||
} |
||||
@ -0,0 +1,141 @@ |
||||
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); |
||||
} |
||||
} |
||||
@ -0,0 +1,170 @@ |
||||
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); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,150 @@ |
||||
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(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,42 @@ |
||||
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); |
||||
} |
||||
} |
||||
@ -0,0 +1,79 @@ |
||||
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.1 2001/03/05 09:15:36 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 = init(); |
||||
|
||||
// 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; |
||||
|
||||
} |
||||
@ -0,0 +1,141 @@ |
||||
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) |
||||
{ |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,47 @@ |
||||
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); |
||||
} |
||||
} |
||||
@ -0,0 +1,238 @@ |
||||
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 |
||||
*/ |
||||
} |
||||
@ -0,0 +1,125 @@ |
||||
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; |
||||
} |
||||
} |
||||
@ -0,0 +1,157 @@ |
||||
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' |
||||
}; |
||||
} |
||||
@ -0,0 +1,102 @@ |
||||
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; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,91 @@ |
||||
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); |
||||
} |
||||
} |
||||
@ -0,0 +1,176 @@ |
||||
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; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,53 @@ |
||||
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); |
||||
} |
||||
} |
||||
@ -0,0 +1,381 @@ |
||||
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); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue