diff options
Diffstat (limited to 'shared')
| -rw-r--r-- | shared/CalendarCategory.java | 223 | ||||
| -rw-r--r-- | shared/CalendarEvent.java | 339 | ||||
| -rw-r--r-- | shared/Config.java | 236 | ||||
| -rw-r--r-- | shared/DoCallback.java | 10 | ||||
| -rw-r--r-- | shared/Main.java | 125 | ||||
| -rw-r--r-- | shared/MyDate.java | 54 | ||||
| -rw-r--r-- | shared/MyVector.java | 23 | ||||
| -rw-r--r-- | shared/remotecall/ClientRequest.java | 369 | ||||
| -rw-r--r-- | shared/remotecall/RemoteCall.java | 29 | ||||
| -rw-r--r-- | shared/remotecall/ServerResponse.java | 53 |
10 files changed, 1461 insertions, 0 deletions
diff --git a/shared/CalendarCategory.java b/shared/CalendarCategory.java new file mode 100644 index 0000000..7f4f346 --- /dev/null +++ b/shared/CalendarCategory.java @@ -0,0 +1,223 @@ +/** + * + */ +package shared; + +import java.util.Enumeration; +import java.util.Vector; +import java.util.regex.*; +import java.io.*; + +import shared.remotecall.*; + + +/** + * This class specifies a category of the calendar events. Its wrapping a vector of references + * of all events of this category. + * @author buetow + * + */ +public class CalendarCategory { + private Vector vecEvents; + private String sCategoryName; + private boolean bHasChanged = false; + private File categoryFile; + + /** + * Creates a new calendar category object and sets the categorie's name to the filename of the category. + * @param categoryFile The file object which contains the unparsed events for this specific category. It will be unset after parsing. + */ + public CalendarCategory(File categoryFile) { + this.categoryFile = categoryFile; + this.sCategoryName = categoryFile.getName(); + + // sCategoryName is now "calendar.Name", remove now the leading 'calendar.' + sCategoryName = sCategoryName.substring(sCategoryName.indexOf('.') + 1); + } + + /** + * Creates a new calendar category object and sets the categorie's File to the name of the category. + * @param sCategoryName Specifies the categorie's name. + */ + public CalendarCategory(String sCategoryName) { + this.sCategoryName = sCategoryName; + } + + /** + * This method sets the categorie's initial events. + * @param vecEvents Specifies the categorie's events. + */ + public void setEvents(Vector vecEvents) { + this.vecEvents = vecEvents; + } + + /** + * This method adds an event to the category. + * @param event Specifies the calendar event to add to this category. + */ + public void addEvent(CalendarEvent event) { + if (vecEvents == null) + vecEvents = new Vector(); + + vecEvents.add(event); + } + + /** + * This method returns the calendar events file object. + * @return Returns the categorie's file object. + */ + public File getFile() { + return categoryFile; + } + + /** + * This method Sets the categories file handle to null. This is done if all the data has been read from + * the file database. + */ + public void unsetFile() { + categoryFile = null; + } + + /** + * This method returns the categorie's name. + * @return Returns the categorie's name. + */ + public String getName() { + return sCategoryName; + } + + /** + * This method sets the categorie's name. + */ + public void setName(String sCategoryName) { + if (this.sCategoryName.equals(sCategoryName)) + return; + + deleteDatabaseFile(); + this.sCategoryName = sCategoryName; + categoryFile = new File(Config.getStringValue("server_database_dir")+"/calendar."+sCategoryName); + setHasChanged(true); + } + + /** + * This method deletes the database file of this event. + */ + public void deleteDatabaseFile() { + if (categoryFile == null) + categoryFile = new File(Config.getStringValue("server_database_dir")+"/calendar."+getName()); + + Main.infoMessage("Removing " + categoryFile.getPath()); + categoryFile.delete(); + } + + /** + * This method returns the categorie's events. + * @return Returns a Vector of all CalendarEvent objects. + */ + public Vector getEvents() { + return vecEvents; + } + + /** + * This method looks for all calendar events of this category which matches a given client's request. + * @param clientRequest Specifies the client request sent by the calendar client. + * @return Returns a Vector of all matching CalendarEvent objects. + */ + public Vector getMatchingEvents(ClientRequest clientRequest) { + Vector vecMatching = new Vector(); + int iNumEventsToRequest = clientRequest.getNumEventsToRequest(); + + Enumeration enumEvents = vecEvents.elements(); + while (enumEvents.hasMoreElements()) { + CalendarEvent event = (CalendarEvent) enumEvents.nextElement(); + if (clientRequest.match(event)) + vecMatching.add(event); + + if (iNumEventsToRequest > -1 && iNumEventsToRequest == vecMatching.size()) + break; + } + + return vecMatching; + } + + /** + * This method checks the current category's name against a regular expression pattern. + * @param pattern Specifies the pattern to be used. + * @return Returns true if the event matches, else false will be returned. + */ + public boolean matchesName(Pattern pattern) { + if (pattern == null) + return false; + + return pattern.matcher(getName()).find(); + } + + /** + * This method removes a given event from its event vector. + * @param event Specifies the calendar event object to be removed from this category + */ + public void removeEvent(CalendarEvent event) { + getEvents().removeElement(event); + } + + /** + * This method lets you check if the calendar category has been modified/changed by a + * calendar client request. This is needed by the CalendarDatabase.flush method, to write all + * the changes back to the database files. + * @return Returns true if the category has changed, else it will return false. + */ + public boolean hasChanged() { + return bHasChanged; + } + + /** + * This method merges two categories. + * @param calendarCategory Specifies the category to merge with. + */ + public void merge(CalendarCategory calendarCategory) { + Enumeration enumEvents = calendarCategory.getEvents().elements(); + while (enumEvents.hasMoreElements()) + vecEvents.add(enumEvents.nextElement()); + + System.out.println(vecEvents); + } + + /** + * This method specifies if the calendar category has been modified/changed or not. + * @param bHasChanged Specifies if the category has been modified/changed or not. + */ + public void setHasChanged(boolean bHasChanged) { + this.bHasChanged = bHasChanged; + } + + /** + * This method flushes the calendar category to the database at the filesystem. + */ + public void flush() { + Main.infoMessage("Flushing category " + getName() + " to database!"); + + if (vecEvents.size() == 0) { + deleteDatabaseFile(); + return; + } + + try { + FileWriter fileWriter = new FileWriter( + Config.getStringValue("server_database_dir") + "/calendar." + getName()); + BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); + + Enumeration enumEvent = vecEvents.elements(); + while (enumEvent.hasMoreElements()) { + CalendarEvent event = (CalendarEvent) enumEvent.nextElement(); + event.flush(bufferedWriter); + } + + bufferedWriter.close(); + + } catch (IOException e) { + Main.infoMessage("Error: Database flush error: " + e.getMessage()); + } + + setHasChanged(false); + } +} diff --git a/shared/CalendarEvent.java b/shared/CalendarEvent.java new file mode 100644 index 0000000..176c42c --- /dev/null +++ b/shared/CalendarEvent.java @@ -0,0 +1,339 @@ +/** + * + */ +package shared; + +import java.util.*; +import java.util.regex.*; +import java.io.*; + +/** + * This class specifies calendar events. Calendar event objects are the most used objects of the + * whole netcalendar suite. + * @author buetow + * + */ +public class CalendarEvent implements Serializable { + private static final long serialVersionUID = 1L; + private MyDate date; + private CalendarCategory category; + private String sCategoryName; + private String sDescription; + private String sPlace; + private boolean bYearly; + private int iEventID; + + static private int iEventIDCount = 0; + + /** + * Simple constructor, creates an event object and increments iEventIDCount by one. + * @param category Specifies the event's category. + */ + public CalendarEvent(CalendarCategory category) { + setCategory(category); + setEventID(iEventIDCount++); + setYearly(false); + } + + /** + * Simple constructor, creates an event object and increments iEventIDCount by one. + * @param sCategoryName Specifies the event's category name. + */ + public CalendarEvent(String sCategoryName) { + setCategoryName(sCategoryName.trim()); + setEventID(iEventIDCount++); + setYearly(false); + } + + /** + * This method sets the event's date. + * @param date Specifies the event's date. + */ + public void setDate(Date date) { + if (date instanceof MyDate) + this.date = (MyDate) date; + else + this.date = new MyDate(date); + } + + /** + * This method sets the event's category. + * @param category Specifies the event's category. + */ + public void setCategory(CalendarCategory category) { + this.category = category; + setCategoryName(category.getName()); + } + + /** + * This event returns the event's calendar category. + * @return Returns the event's calenda category. + */ + public CalendarCategory getCategory() { + return category; + } + + /** + * This methos sets thhe event's category name. + * @param sCategoryName Specifies the event's category name. + */ + public void setCategoryName(String sCategoryName) { + this.sCategoryName = sCategoryName.trim(); + } + + /** + * This method sets the event's descriptions tring. + * @param sDescription Specifies the event's description string. + */ + public void setDescription(String sDescription) { + this.sDescription = sDescription.trim(); + } + + /** + * This method sets the event's place string. + * @param sPlace Specifies the event's place string. + */ + public void setPlace(String sPlace) { + this.sPlace = sPlace.trim(); + } + + /** + * This method sets the event's ID number. + * @param iEventID specifies the event's ID number. + */ + public void setEventID(int iEventID) { + this.iEventID = iEventID; + } + + /** + * This method specifies if this event occurs yearly or not. + * @param bYearly Specifies if this event occury yearly or not. + */ + public void setYearly(boolean bYearly) { + this.bYearly = bYearly; + } + + /** + * This method returns the event's category name. + * @return Returns the event's category name. + */ + public String getCategoryName() { + return sCategoryName; + } + + /** + * This method returns the event's description string. + * @return Returns the event's description string. + */ + public String getDescription() { + return sDescription; + } + + /** + * This method returns the event's place string. + * @return Returns the event's place string. + */ + public String getPlace() { + return sPlace; + } + + /** + * This method returns the event's ID. + * @return Returns the event's ID. + */ + public int getID() { + return iEventID; + } + + /** + * This method returns the event's date object. + * @return Returns the event's date object. + */ + public MyDate getDate() { + return date; + } + + /** + * This method returns the event's ID number. + * @return Returns the event's ID number. + */ + public int getEventID() { + return iEventID; + } + + /** + * This method checks if this event occurs yearly or not. + * @return Returns true if the event occurs yearly, else it returns false. + */ + public boolean isYearly() { + return bYearly; + } + + /** + * Checks if the current event matches all available data of the event agains + * a given regular expression pattern. + * @param pattern Specifies the pattern to match against. + * @return Returns true if one element of the event matches. + */ + public boolean matches(Pattern pattern) { + if (pattern == null) + return false; + + else if (matchesDescription(pattern)) + return true; + + else if (matchesPlace(pattern)) + return true; + + else if (matchesCategoryName(pattern)) + return true; + + return matchesDateString(pattern); + } + + /** + * Checks if the current event's name matches agains a regular expression pattern. + * @param pattern Specifies the pattern to be matched against. + * @return Returns true if the event matches, else false will be returned. If the pattern is null, true will be returned. + */ + public boolean matchesCategoryName(Pattern pattern) { + if (pattern == null) + return true; + + return pattern.matcher(getCategoryName()).find(); + } + + /** + * Checks if the current event's description string matches agains a regular expression pattern. + * @param pattern Specifies the pattern to match against. + * @return Returns true if the event matches, else false will be returned. If the pattern is null, true will be returned. + */ + public boolean matchesDescription(Pattern pattern) { + if (pattern == null) + return true; + + return pattern.matcher(getDescription()).find(); + } + + /** + * Checks if the current event's place string matches agains a regular expression pattern. + * @param pattern Specifies the pattern to match against. + * @return Returns true if the event matches, else false will be returned. If the pattern is null, true will be returned. + */ + public boolean matchesPlace(Pattern pattern) { + if (pattern == null) + return true; + + return pattern.matcher(getPlace()).find(); + } + + /** + * Checks if the current event's category name matches agains a regular expression pattern + * @param pattern Specifies the pattern to match against. + * @return Returns true if the event matches, else false will be returned. If the pattern is null, true will be returned. + */ + public boolean matchesCategory(Pattern pattern) { + if (pattern == null) + return true; + + return pattern.matcher(getCategoryName()).find(); + } + + /** + * Checks if the current event's date string matches agains a regular expression pattern + * @param pattern Specifies the pattern to match against. + * @return Returns true if the event matches, else false will be returned. If the pattern is null, true will be returned. + */ + public boolean matchesDateString(Pattern pattern) { + if (pattern == null) + return true; + + return pattern.matcher(getDate().toString()).find(); + } + + /** + * Needed for ojbect serialization (sending part)- + * @param objectOutputStream Specifies the output stream to use. + * @throws IOException + */ + private void writeObject(ObjectOutputStream objectOutputStream) + throws IOException { + objectOutputStream.writeInt(iEventID); + objectOutputStream.writeBoolean(isYearly()); + objectOutputStream.writeObject(getDate()); + objectOutputStream.writeObject(getCategoryName()); + objectOutputStream.writeObject(getDescription()); + objectOutputStream.writeObject(getPlace()); + } + + /** + * Needed for object serialization (receiving part). + * @param objectInputStream Specifies the input stream to use. + * @throws IOException + * @throws ClassNotFoundException + */ + private void readObject(ObjectInputStream objectInputStream) + throws IOException, ClassNotFoundException { + setEventID(objectInputStream.readInt()); + setYearly(objectInputStream.readBoolean()); + setDate((Date) objectInputStream.readObject()); + setCategoryName((String) objectInputStream.readObject()); + setDescription((String) objectInputStream.readObject()); + setPlace((String) objectInputStream.readObject()); + + if (getEventID() < 0 ) + setEventID(iEventIDCount++); + } + + /** + * Removes the calendar event from its current category and sets the + * category reference to null. + */ + public void removeFromCurrentCategory() { + CalendarCategory category = getCategory(); + category.removeEvent(this); + } + + /** + * This method flushes the calendar event to the database at the filesystem. + * @param bufferedWriter Specifies the buffered writer to write to. + */ + protected void flush(BufferedWriter bufferedWriter) throws IOException { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(getDate()); + int iYear = calendar.get(Calendar.YEAR); + // if (iYear < 11) iYear += 2000; + int iMonth = calendar.get(Calendar.MONTH) + 1; + int iDays = calendar.get(Calendar.DAY_OF_MONTH); + int iHours= calendar.get(Calendar.HOUR); + int iMinutes = calendar.get(Calendar.MINUTE); + + String sPlace = getPlace(); + if (!sPlace.equals("")) + sPlace = ";;" + sPlace; + + String sYearly = isYearly() ? "yearly" : MyDate.addZerosToFront(iYear, 4); + String sEventLine = + MyDate.addZerosToFront(iMonth, 2) + "/" + + MyDate.addZerosToFront(iDays, 2) + "\t" + + sYearly + "-" + + MyDate.addZerosToFront(iHours, 2) + ":" + + MyDate.addZerosToFront(iMinutes, 2) + " " + + getDescription() + + sPlace + "\n"; + + bufferedWriter.write(sEventLine); + } + + /** + * This method is needed for a text representation of the object. + * @return Returns object represented as a String. + */ + public String toString() { + return "#" + getEventID() + " " + getDate() + "\n" + + "Yearly : " + isYearly() + "\n" + + "Category : " + getCategoryName() + "\n" + + "Description: " + getDescription() + "\n" + + "Place : " + getPlace() + "\n"; + } +} diff --git a/shared/Config.java b/shared/Config.java new file mode 100644 index 0000000..5d79c6f --- /dev/null +++ b/shared/Config.java @@ -0,0 +1,236 @@ +package shared; + +import java.util.*; +import java.net.*; +import java.io.*; + +/** + * This class makes all the configuration options available to all the other classes and objects + * of this program. Its reading and writing back the values from and to the config.txt file. + * @author buetow + * + */ +public final class Config { + public static final String VERSION = "NetCalendar 1.0"; + private static final String CONFIG_FILE = "config.txt"; + private static HashMap mapConfigVals; + + /** + * Initializes all the config values. + * @param args The start parameters. + */ + public static void initialize(String[] args) { + if (args.length > 0) { + if (args[0].equals("--help")) { + System.out.println(Config.VERSION + " help"); + System.out.println("(c) 2006, 2009 by Dipl.-Inform. (FH) Paul C. Buetow [netcalendar@dev.buetow.org]"); + System.out.println("This is free software, see the LICENSE.txt for copying conditions. There is NO"); + System.out.println("warranty; not even for MERCHANTABILITY of FITNESS FOR A PARTICULAR PURPOSE."); + System.out.println(); + System.out.println("Possible start parameters are:"); + System.out.println("\t--help Shows this help and exists"); + System.out.println("\t--client-only Runs the NetCalendar client only"); + System.out.println("\t--server-address=host Specifies the server host to connect to"); + System.out.println("\t--server-only Runs the NetCalendar server only"); + System.out.println("\t--client-and-server Runs the NetCalendar server and client"); + System.out.println("\t within the same process!"); + System.out.println(); + System.exit(0); + } + } + + mapConfigVals = new HashMap(); + readConfig(CONFIG_FILE); + + for (int i = 0; i < args.length; ++i) { + if (args[i].equals("--server-only")) { + mapConfigVals.put("server_run", "true"); + mapConfigVals.put("client_run", "false"); + + } else if(args[i].equals("--client-only")) { + mapConfigVals.put("server_run", "false"); + mapConfigVals.put("client_run", "true"); + + } else if(args[i].equals("--client-and-server")) { + mapConfigVals.put("server_run", "true"); + mapConfigVals.put("client_run", "true"); + mapConfigVals.put("server_address", "localhost"); + + } else if(args[i].startsWith("--server-address=")) { + mapConfigVals.put("server_address", args[i].substring(17)); + } + } + + if (args.length > 0) + writeConfigToFile(); + } + + /** + * This methods reads the options from the calendar config file 'config.txt'. + * @param sConfigFile Specifies the relative or absolute path to the config file. + */ + public static void readConfig(String sConfigFile) { + Main.infoMessage("Config: Using config file " + sConfigFile); + File file = new File(sConfigFile); + + if (!file.isFile()) { + Main.infoMessage("Config: " + sConfigFile + " is not a file!"); + System.exit(1); + } + + try { + BufferedReader in = new BufferedReader(new FileReader(file)); + String sLine; + + while ((sLine = in.readLine()) != null) { + int iSeperator = sLine.indexOf('='); + + if (iSeperator > -1) { + int iEnd = sLine.indexOf(';'); + + if (iEnd > -1) { + String sKey = sLine.substring(0, iSeperator).trim(); + String sVal = sLine.substring(iSeperator+1, iEnd).trim(); + mapConfigVals.put(sKey, sVal); + } + } + } + + } catch (Exception e) { + Main.infoMessage("Config: " + e.getMessage()); + System.exit(1); + } + } + + /** + * This method returns the inet address of the calendar server. + * @return Returns the calendar server's address . + */ + public static InetAddress getServerAddress() { + InetAddress serverAddress = null; + + try { + serverAddress = InetAddress.getByName(Config.getStringValue("server_address")); + } catch(Exception e) { + Main.infoMessage("Server address error: " + e.getMessage()); + } + + return serverAddress; + } + + /** + * This method returns a specific string config value. + * @param sKey Specifies the key of the config value to return. + * @return Returns the requested config value. + */ + public static String getStringValue(String sKey) { + return getStringValue(sKey, true); + } + + /** + * This method returns a specific string config value. + * @param sKey Specifies the key of the config value to return. + * @param bLogMessages Specifies if this action should be logged or not. + * @return Returns the requested config value. + */ + public static String getStringValue(String sKey, boolean bLogMessage) { + String sRet = (String) mapConfigVals.get(sKey); + + if (sRet != null) + sRet = sRet.trim(); + + return sRet; + } + + /** + * This method returns a specific integer config value. + * @param sKey Specifies the key of the config value to return. + * @return Returns the requested config value. + */ + public static int getIntValue(String sKey) { + String sVal = (String) mapConfigVals.get(sKey); + + if (sVal != null) + sVal = sVal.trim(); + + return Integer.parseInt(sVal); + } + + /** + * This method returns a specific boolean config value. + * @param sKey Specifies the key of the config value to return. + * @return Returns the requested config value. + */ + public static boolean getBooleanValue(String sKey) { + String sVal = (String) mapConfigVals.get(sKey); + + if (sVal != null) + sVal = sVal.trim(); + + boolean bRet = false; + + if (sVal != null) + bRet = sVal.equals("true"); + + return bRet; + } + + /** + * This method returns a set of keys of the config hash map. + * @return Returns a Set object containing all keys of the Config's hash map. + */ + public static Set getKeySet() { + return mapConfigVals.keySet(); + } + + /** + * This method changes or adds a specific config value. + * @param sKey Specifies the config key to set or update. + * @param sVal Specifies the value of the key to set or update. + */ + public static void setValue(String sKey, String sVal) { + mapConfigVals.put(sKey, sVal); + } + + /** + * This method returns a sorted String array of all available config keys. + * @return Returns a sorted String array of all available config keys. + */ + public static String [] getSortedKeyArray() { + Set keySet = getKeySet(); + Object [] keys = keySet.toArray(); + int iNumPairs = keys.length; + String [] sKeys = new String[iNumPairs]; + + for (int i = 0; i < iNumPairs; ++i) + sKeys[i] = (String) keys[i]; + + Arrays.sort(sKeys); + + return sKeys; + } + + /** + * This method writes the current configuration to the config file "config.txt". + */ + public static void writeConfigToFile() { + String [] sKeys = getSortedKeyArray(); + int iNumKeys = sKeys.length; + + try { + FileWriter fileWriter = new FileWriter(CONFIG_FILE); + BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); + + for (int i = 0; i < iNumKeys; ++i) { + String sKey = sKeys[i]; + String sVal = getStringValue(sKey); + bufferedWriter.write(sKey + "=" + sVal + ";\n"); + } + + bufferedWriter.close(); + + } catch(IOException e) { + Main.infoMessage("Error: " + e.toString()); + } + } +} diff --git a/shared/DoCallback.java b/shared/DoCallback.java new file mode 100644 index 0000000..fd35642 --- /dev/null +++ b/shared/DoCallback.java @@ -0,0 +1,10 @@ +package shared; + +/** + * This interface specifies a callback routine. + * @author buetow + * + */ +public interface DoCallback { + public void callback(Object o); +} diff --git a/shared/Main.java b/shared/Main.java new file mode 100644 index 0000000..24edc0d --- /dev/null +++ b/shared/Main.java @@ -0,0 +1,125 @@ +package shared; + +import java.io.*; + +import javax.swing.JFrame; + +import server.*; + +import client.*; + +/** + * This class contains the static main method to start the program from. + * This class is also responsible for handling info ans status messages and + * the logging option of those messages. + * @author buetow + * + */ +public final class Main { + private static NetCalendarClient netCalendarClient = null; + private static BufferedWriter bufferedLogfileWriter = null; + + /** + * This method is the start point of the whole program. Its initializing the static Config object + * and starts a calendar server and/or a calendar client thread depending on the "server_run" and + * "client_run" configuration options. + * @param args Specifies the program arguments (not used yet by the program) + */ + public static void main(String[] args) { + Config.initialize(args); + + try { + FileWriter fileWriter = new FileWriter(Config.getStringValue("logfile")); + bufferedLogfileWriter = new BufferedWriter(fileWriter); + + } catch (IOException e) { + infoMessage("Error: Could not open logfile: " + e.getMessage()); + } + + + if (Config.getBooleanValue("server_run")) { + new NetCalendarServer( + Config.getIntValue("server_port"), + Config.getStringValue("server_database_dir")); + } + + if (Config.getBooleanValue("client_run")) { + new Thread(new SplashScreen()).start(); + //Make sure we have nice window decorations. + JFrame.setDefaultLookAndFeelDecorated(true); + netCalendarClient = new NetCalendarClient(); + } + } + + /** + * All info messages of the calendar client and the calendar server go through this method. + * They are not using System.out.* directly. + * @param sMessage Specifies the program info message. + */ + public static void infoMessage(String sMessage) { + // Later: Add logging to a logfile! + System.out.println(sMessage); + logMessage(sMessage); + } + + /** + * This method is for various messages. All messages will show up in the status bar of the client's main window. + * If there is no main window, the infoMessage method will be used instead. + * @param sMessage Specifies the message to be displayed in the status bar. + */ + public static void statusMessage(String sMessage) { + if (netCalendarClient != null) + netCalendarClient.statusMessage(sMessage); + else + infoMessage(sMessage); + } + + /** + * This method writes a specific message string into a logfile which is specified in the config.txt. + * @param sMessage Specified the message string to write into the logfile. + */ + private static void logMessage(String sMessage) { + if (bufferedLogfileWriter != null) { + try { + bufferedLogfileWriter.write(sMessage + "\n"); + // bufferedLogfileWriter.flush(); + + } catch(IOException e) { + Main.infoMessage("Error: Could not write to logfile: " + e.toString()); + } + } + } + + /** + * This method is called thenever the server or the client process wants to exit. + * @param iCode Specifies the exit code to use for the System.exit call. + */ + public static void exit(int iCode) { + infoMessage("Shutting down the current process"); + + try { + bufferedLogfileWriter.close(); + } catch(IOException e) { + System.err.println("Error: Could not close logfile: " + e.toString()); + } + + System.exit(iCode); + } + + + /** + * This method executes an external program. + * @param sCommand Specifies the command string to execute. + */ + public static void execExternalCommand(String sCommand) { + if (sCommand.equals("none") || sCommand.equals("")) + return; + + try { + Runtime.getRuntime().exec(sCommand); + + } catch (IOException e) { + Main.infoMessage("Error while executing external command: " + e.getMessage()); + } + } +} diff --git a/shared/MyDate.java b/shared/MyDate.java new file mode 100644 index 0000000..664ce91 --- /dev/null +++ b/shared/MyDate.java @@ -0,0 +1,54 @@ +package shared; + +import java.util.*; + +/** + * This class extends the standard Date class and customizes the toString method. + * This class also contains some helper methods to make the life easier. + * @author buetow + * + */ +public class MyDate extends Date { + private final static long serialVersionUID = 1L; + private final static String [] DAYS = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + + /** + * Copy constructor. + * @param data Specifies the date objekt to copy the time from. + */ + public MyDate(Date date) { + super(date.getTime()); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(this); + + String sYear = addZerosToFront(calendar.get(Calendar.YEAR), 4); + String sMonth = addZerosToFront(calendar.get(Calendar.MONTH) + 1, 2); + String sDays = addZerosToFront(calendar.get(Calendar.DAY_OF_MONTH), 2); + String sHours= addZerosToFront(calendar.get(Calendar.HOUR), 2); + String sMinutes = addZerosToFront(calendar.get(Calendar.MINUTE), 2); + String sDay = DAYS[calendar.get(Calendar.DAY_OF_WEEK)-1]; + + return sDays + "." + sMonth + "." + sYear + " " + sHours + ":" + sMinutes + " " + sDay; + } + + /** + * This method adds zeros in front of a number and returns it as a string. + * @param iValue Specifies the number to add zeros to. + * @param iWantedLength Specifies the wanted max length of the string. + * @return Returns the number represented as a string with additional zeros on front. + */ + public static String addZerosToFront(int iValue, int iWantedLength) { + String sValue = iValue + ""; + + while (sValue.length() < iWantedLength) + sValue = "0" + sValue; + + return sValue; + } +} diff --git a/shared/MyVector.java b/shared/MyVector.java new file mode 100644 index 0000000..9d9d596 --- /dev/null +++ b/shared/MyVector.java @@ -0,0 +1,23 @@ +package shared; + +import java.util.Enumeration; +import java.util.Vector; + +/** + * This class extends the standard Vector class and defined additional help methods. + * @author buetow + * + */ +public class MyVector extends Vector { + private static final long serialVersionUID = 1L; + + /** + * This method appends a vector at the end. + * @param vecAppend Specifies the vector to be appended. + */ + public void appendVector(Vector vecAppend) { + Enumeration enumAppend = vecAppend.elements(); + while (enumAppend.hasMoreElements()) + this.add(enumAppend.nextElement()); + } +} diff --git a/shared/remotecall/ClientRequest.java b/shared/remotecall/ClientRequest.java new file mode 100644 index 0000000..ed31ed3 --- /dev/null +++ b/shared/remotecall/ClientRequest.java @@ -0,0 +1,369 @@ +package shared.remotecall; + +import java.util.*; +import java.io.*; +import java.util.regex.*; + +import shared.*; + +/** + * An object of this class is sent from the calendar client to the calendar server each time + * a request is made. This class encapsulates all the needed information so that the server can + * response with a serialized server response object. + * @author buetow + * + */ +public final class ClientRequest extends RemoteCall implements Serializable { + private static final long serialVersionUID = 6L; + private static final Pattern emptyPattern = Pattern.compile("[^\\s]"); + + public static final int REQUEST_EVENTS = 0; + public static final int REQUEST_ALL_EVENTS = 1; + public static final int MODIFY_EVENT = 2; + public static final int DELETE_EVENT = 3; + public static final int ADD_EVENT = 4; + public static final int RELOAD_DATABASE = 5; + public static final int FLUSH_DATABASE = 6; + public static final int SHUTDOWN_SERVER = 7; + public static final int RENAME_CATEGORY = 8; + public static final int DELETE_CATEGORY = 9; + + private int iAction = 0; + private int iNumEventsToRequest; + + private boolean bMainRegexp; + private boolean bCaseInsensitive; + + private Pattern patAll = null; + private Pattern patCategory = null; + private Pattern patDescription = null; + private Pattern patPlace = null; + private Pattern patDate = null; + private Date dateRangeFrom = null; + private Date dateRangeTo = null; + private CalendarEvent event = null; + private String sPassphrase; + private String sString = null; + + /** + * Simple constructor, creates a client request object requesting events up + * from the current date. + */ + public ClientRequest() { + dateRangeFrom = new Date(); + initialize(REQUEST_EVENTS); + } + + /** + * Simple constructor, creates a client request object requesting events up + * from the current date. + * @param iAction Specifies the request type of this request. + */ + public ClientRequest(int iAction) { + dateRangeFrom = new Date(); + initialize(iAction); + } + + /** + * This method initializes some common stuff. Called by each constructor. + * @param iAction Specifies the request type of this request. + */ + private void initialize(int iAction) { + this.iAction = iAction; + this.sPassphrase = Config.getStringValue("passphrase", false); + this.bCaseInsensitive = Config.getBooleanValue("regexp_case_insensitive"); + this.iNumEventsToRequest = Config.getIntValue("client_max_events"); + } + + /** + * This method is needed by the clanedar server to get the type of action requested. + * @param iAction Specifies the action to test against. + * @return Returns true if the specified action ID matches with the action ID of this request object. + */ + public boolean actionIs(int iAction) { + return this.iAction == iAction; + } + + /** + * This method is needed by the calendar server to get the type of action requested. + * @return Returns true if this object requests new events from the server. + */ + public boolean requestsNewEvents() { + return this.iAction < ClientRequest.MODIFY_EVENT; + } + + /** + * This method sets the date range to request. + * @param dateRangeFrom Specifies the beginning date. + * @param dateRangeTo Specifies the ending date. + */ + public void setDateRange(Date dateRangeFrom, Date dateRangeTo) { + this.dateRangeFrom = dateRangeFrom; + this.dateRangeTo = dateRangeTo; + } + + /** + * This method sets a calendar event object to be transfered to the calendar server because the event has been modified. + * @param event Specifies an event to be transfered to the calendar server. + */ + public void setEvent(CalendarEvent event) { + this.event = event; + if (actionIs(ADD_EVENT)) + event.setEventID(-1); + } + + /** + * This method returns the event object. + * @return Returns the calendar event which is stored inside this client request. + */ + public CalendarEvent getEvent() { + return event; + } + + /** + * With this method the client can define the maximum number of events to request. + * @param iNumEvents Specifies the maximum number of events to request. + */ + public void setNumEventsToRequest(int iNumEvents) { + this.iNumEventsToRequest = iNumEvents; + } + + /** + * This method returns the maximum number of events the client wants to request. + * @return Returns the maximum number of events the client wants to request. + */ + public int getNumEventsToRequest() { + return iNumEventsToRequest; + } + + /** + * This method sets if the client contains a regexp from the main session window. + * @param bMainRegexp Set to true if the user used the main regexp field of the main GUI window. + */ + public void setMainRegexp(boolean bMainRegexp) { + this.bMainRegexp = bMainRegexp; + } + + /** + * This method compiles a specific pattern object to match with on the server part after serialization. + * @param sRegexp Compiles a Pattern object with sRegexp as the regular expression. + */ + public void setRegexpAll(String sRegexp) { + if (isEmptyPattern(sRegexp)) + return; + + if (bCaseInsensitive) + patAll = Pattern.compile(sRegexp, Pattern.CASE_INSENSITIVE); + else + patAll = Pattern.compile(sRegexp); + } + + /** + * This method compiles a specific pattern object to match with on the server part after serialization. + * @param sRegexp Compiles a Pattern object with sRegexp as the regular expression. + */ + public void setRegexpCategory(String sRegexp) { + if (isEmptyPattern(sRegexp)) + return; + + if (bCaseInsensitive) + patCategory = Pattern.compile(sRegexp, Pattern.CASE_INSENSITIVE); + else + patCategory = Pattern.compile(sRegexp); + } + + /** + * This method compiles a specific pattern object to match with on the server part after serialization. + * @param sRegexp Compiles a Pattern object with sRegexp as the regular expression. + */ + public void setRegexpDescription(String sRegexp) { + if (isEmptyPattern(sRegexp)) + return; + + if (bCaseInsensitive) + patDescription = Pattern.compile(sRegexp, Pattern.CASE_INSENSITIVE); + else + patDescription = Pattern.compile(sRegexp); + } + + /** + * This method sets a string to be transfered to the netcalendar server. + * @param sString specifies the string to be transfered. + */ + public void setString(String sString) { + this.sString = sString; + } + + /** + * This method returns a string transfered by the netcalendar client. If no string has been transfered, + * null will be returned. + * @return Returns a string transfered by the netcalendar client. + */ + public String getString() { + return sString; + } + + /** + * This method compiles a specific pattern object to match with on the server part after serialization. + * @param sRegexp Compiles a Pattern object with sRegexp as the regular expression. + */ + public void setRegexpPlace(String sRegexp) { + if (isEmptyPattern(sRegexp)) + return; + + if (bCaseInsensitive) + patPlace = Pattern.compile(sRegexp, Pattern.CASE_INSENSITIVE); + else + patPlace = Pattern.compile(sRegexp); + } + + /** + * This method compiles a specific pattern object to match with on the server part after serialization. + * @param sRegexp Compiles a Pattern object with sRegexp as the regular expression. + */ + public void setRegexpDate(String sRegexp) { + if (isEmptyPattern(sRegexp)) + return; + + if (bCaseInsensitive) + patDate = Pattern.compile(sRegexp, Pattern.CASE_INSENSITIVE); + else + patDate = Pattern.compile(sRegexp); + } + + /** + * Checks if a specific calendar event matches this client request. + * @param calendarEvent Specifies the event to match against. + * @return Returns true if the given event matched. Else, false will be returned. + */ + public boolean match(CalendarEvent calendarEvent) { + // If we want to get all events! + if (actionIs(REQUEST_ALL_EVENTS)) + return true; + + // If we use the regex field of the main GUI + if (bMainRegexp) + return calendarEvent.matches(patAll); + + // If we use advanced searching: + if (dateRangeFrom != null) + if (dateRangeFrom.getTime() > calendarEvent.getDate().getTime()) + return false; + + if (dateRangeTo != null) + if (dateRangeTo.getTime() < calendarEvent.getDate().getTime()) + return false; + + if (calendarEvent.matches(patAll) || + (calendarEvent.matchesDescription(patDescription) + && calendarEvent.matchesCategory(patCategory) + && calendarEvent.matchesPlace(patPlace) + && calendarEvent.matchesDateString(patDate))) + return true; + + return false; + } + + /** + * Needed for ojbect serialization (sending part). + * @param objectOutputStream Specifies the output stream to use. + * @throws IOException + */ + private void writeObject(ObjectOutputStream objectOutputStream) + throws IOException { + objectOutputStream.writeInt(iAction); + objectOutputStream.writeInt(iNumEventsToRequest); + objectOutputStream.writeObject(sPassphrase); + objectOutputStream.writeBoolean(bMainRegexp); + objectOutputStream.writeBoolean(bCaseInsensitive); + + super.writeObjectIfDefined(objectOutputStream, sString); + super.writeObjectIfDefined(objectOutputStream, patAll); + super.writeObjectIfDefined(objectOutputStream, patCategory); + super.writeObjectIfDefined(objectOutputStream, patDescription); + super.writeObjectIfDefined(objectOutputStream, patPlace); + super.writeObjectIfDefined(objectOutputStream, patDate); + super.writeObjectIfDefined(objectOutputStream, dateRangeFrom); + super.writeObjectIfDefined(objectOutputStream, dateRangeTo); + super.writeObjectIfDefined(objectOutputStream, event); + } + + /** + * Needed for object serialization (recieving part). + * @param objectInputStream Specifies the input stream to use. + * @throws IOException + * @throws ClassNotFoundException + */ + private void readObject(ObjectInputStream objectInputStream) + throws IOException, ClassNotFoundException { + + iAction = objectInputStream.readInt(); + iNumEventsToRequest = objectInputStream.readInt(); + sPassphrase = (String) objectInputStream.readObject(); + setMainRegexp(objectInputStream.readBoolean()); + bCaseInsensitive = objectInputStream.readBoolean(); + + if (objectInputStream.readBoolean()) + sString = (String) objectInputStream.readObject(); + + if (objectInputStream.readBoolean()) + patAll = (Pattern) objectInputStream.readObject(); + + if (objectInputStream.readBoolean()) + patCategory = (Pattern) objectInputStream.readObject(); + + if (objectInputStream.readBoolean()) + patDescription = (Pattern) objectInputStream.readObject(); + + if (objectInputStream.readBoolean()) + patPlace = (Pattern) objectInputStream.readObject(); + + if (objectInputStream.readBoolean()) + patDate = (Pattern) objectInputStream.readObject(); + + if (objectInputStream.readBoolean()) + dateRangeFrom = (Date) objectInputStream.readObject(); + + if (objectInputStream.readBoolean()) + dateRangeTo = (Date) objectInputStream.readObject(); + + if (objectInputStream.readBoolean()) + event = (CalendarEvent) objectInputStream.readObject(); + } + + /** + * Checks if a given pattern string has other charactars than whitespaces inside or not. + * @param sRegexp Specifies the pattern string to check against. + * @return Returns true if the pattern string only contains whitespaces. Else, false will be returned. + */ + private boolean isEmptyPattern(String sRegexp) { + return !emptyPattern.matcher(sRegexp).find(); + } + + /** + * This method checks if the request's passphrase is correct or not. + * @param sPassphrase Specifies the server passphrase to chack against the request passphrase. + * @return Returns true if the passphrases equal. Else, false will be returned. + */ + public boolean checkPassphrase(String sPassphrase) { + return this.sPassphrase.equals(sPassphrase); + } + + /** + * This method returns a representation the object as a string. + * @return Returns the object represented as a string. + */ + public String toString() { + return + "Action : " + iAction + "\n" + + "NumEvents : " + iNumEventsToRequest + "\n" + + "MainRegexp : " + bMainRegexp + "\n" + + "patAll : " + patAll + "\n" + + "patCategory : " + patCategory + "\n" + + "patDescription: " + patDescription + "\n" + + "patDate : " + patDate + "\n" + + "dateRangeFrom : " + dateRangeFrom + "\n" + + "dateRangeTo : " + dateRangeTo + "\n" + + "modifiedEvent :\n" + event+ "\n"; + } +} diff --git a/shared/remotecall/RemoteCall.java b/shared/remotecall/RemoteCall.java new file mode 100644 index 0000000..5accf28 --- /dev/null +++ b/shared/remotecall/RemoteCall.java @@ -0,0 +1,29 @@ +package shared.remotecall; + +import java.io.*; + +/** + * This is the abstract base class of all other classes of the shared.remotecall package. + * Its defining some common methods. + * @author buetow + * + */ +public abstract class RemoteCall { + /** + * This is a help method for writeObject of the child classes, needed for ojbect serialization (sending part). + * It checks if object is defined. If yes, it will be written to the given object output stream with a leading + * flag with the value true. Otherwise only the false flag will be written to the object output stream. + * @param objectOutputStream Specifies the output stream. + * @throws IOException + */ + protected final void writeObjectIfDefined(ObjectOutputStream objectOutputStream, Object object) + throws IOException { + if (object == null) { + objectOutputStream.writeBoolean(false); + + } else { + objectOutputStream.writeBoolean(true); + objectOutputStream.writeObject(object); + } + } +} diff --git a/shared/remotecall/ServerResponse.java b/shared/remotecall/ServerResponse.java new file mode 100644 index 0000000..d2990bc --- /dev/null +++ b/shared/remotecall/ServerResponse.java @@ -0,0 +1,53 @@ +package shared.remotecall; + +import java.io.*; +import java.util.Vector; + +/** + * This class represents a server response. A server response will sent from the calendar + * server to the calendar client if the client has sent a client request. + * @author buetow + * + */ +public final class ServerResponse extends RemoteCall implements Serializable { + private static final long serialVersionUID = 1L; + private Vector vecEvents = null; + + /** + * Simple constructor, creates a server response which can be sent to the calendar client. + * @param vecEvents Specifies all calendar events to be sent to the calendar client. + */ + public ServerResponse(Vector vecEvents) { + this.vecEvents = vecEvents; + } + + /** + * Needed for ojbect serialization (sending part). + * @param objectOutputStream Specifies the output stream. + * @throws IOException + */ + private void writeObject(ObjectOutputStream objectOutputStream) + throws IOException { + super.writeObjectIfDefined(objectOutputStream, vecEvents); + } + + /** + * Needed for object serialization (recieving part). + * @param objectInputStream Specifies the input stream. + * @throws IOException + * @throws ClassNotFoundException + */ + private void readObject(ObjectInputStream objectInputStream) + throws IOException, ClassNotFoundException { + if (objectInputStream.readBoolean()) + vecEvents = (Vector) objectInputStream.readObject(); + } + + /** + * This method returns a vector of all requested calendar events. + * @return Returns a Vector of all requested CalendarEvent objects. + */ + public Vector getEvents() { + return vecEvents; + } +} |
