/* * Created on 16.03.2005 */ package jplagWebService.serverAccess; import java.io.File; import java.io.FileInputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import jplagWebService.server.Submission; import jplagWebService.serverImpl.JPlagCentral; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class ResultAdmin { public static final int SEARCH_ENTRIES=1; public static final int SEARCH_RESULTS=2; public static final int SEARCH_ALL=SEARCH_ENTRIES | SEARCH_RESULTS; private File usersDataFile=null; private Document doc=null; private Element entryRoot=null; private Element resultRoot=null; private Element rootElement=null; private int lastSubmissionID=1000000000; public ResultAdmin(String jplagHome) { usersDataFile=new File(jplagHome + File.separator + "usersdata.xml"); if(!usersDataFile.exists()) create(); else parse(); } /** * Writes the "user submission database" to an XML file */ private void writeXMLFile() { try { // Prepare the DOM document for writing Source source = new DOMSource(doc); // Prepare the output file Result result = new StreamResult(usersDataFile); // Write the DOM document to the file Transformer xformer = TransformerFactory.newInstance().newTransformer(); xformer.transform(source, result); } catch (TransformerConfigurationException e) { e.printStackTrace(); } catch (TransformerException e) { e.printStackTrace(); } } /** * Creates a new "user submission database" XML file */ private void create() { DocumentBuilderFactory docBFac; DocumentBuilder docBuild; try { docBFac=DocumentBuilderFactory.newInstance(); docBuild = docBFac.newDocumentBuilder(); doc = docBuild.newDocument(); } catch(Exception ex) { ex.printStackTrace(); return; } rootElement=doc.createElement("jplagData"); lastSubmissionID=1000000000; rootElement.setAttribute("lastSubID",lastSubmissionID+""); entryRoot=doc.createElement("EntriesQueue"); resultRoot=doc.createElement("ResultData"); rootElement.appendChild(entryRoot); rootElement.appendChild(resultRoot); doc.appendChild(rootElement); writeXMLFile(); } /** * Loads an existing "user submission database" into memory */ private void parse() { try { FileInputStream xmlStream=new FileInputStream(usersDataFile); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setIgnoringComments(true); DocumentBuilder builder=factory.newDocumentBuilder(); doc=builder.parse(xmlStream); xmlStream.close(); rootElement=doc.getDocumentElement(); lastSubmissionID=Integer.parseInt( rootElement.getAttribute("lastSubID")); System.out.println("lastSubmissionID="+lastSubmissionID); NodeList entriesList=doc.getElementsByTagName("EntriesQueue"); entryRoot=(Element) entriesList.item(0); entriesList=doc.getElementsByTagName("ResultData"); resultRoot=(Element) entriesList.item(0); } catch(javax.xml.parsers.ParserConfigurationException e) { System.out.println("Failed to create DocumentBuilder!"); e.printStackTrace(); } catch(org.xml.sax.SAXException e) { System.out.println("Error parsing users.xml!"); e.printStackTrace(); } catch(Exception e) { System.out.println("File error!"); e.printStackTrace(); } } /** * @return Next available submission ID */ public synchronized String getNextSubmissionID() { lastSubmissionID++; rootElement.setAttribute("lastSubID",lastSubmissionID+""); writeXMLFile(); return lastSubmissionID+""; } /** * Adds a new submission to the entry queue * @param struct Submission to be queued */ public synchronized void addEntry(AccessStructure struct) { entryRoot.appendChild(struct.toXMLEntryElement(doc)); writeXMLFile(); } public synchronized int getNumEntries() { NodeList list=entryRoot.getElementsByTagName("entry"); return list.getLength(); } public synchronized AccessStructure getNextEntry() { if(!entryRoot.hasChildNodes()) return null; return AccessStructure.fromXMLEntryElement( (Element) entryRoot.getFirstChild()); } public synchronized AccessStructure getAccessStruct(String subID, int searchFlags) { NodeList list; if((searchFlags & SEARCH_ENTRIES)!=0) { list=entryRoot.getElementsByTagName("entry"); for(int i=0;i<list.getLength();i++) { Element entry=(Element) list.item(i); if(entry.getAttribute("id").equals(subID)) { AccessStructure struct = AccessStructure.fromXMLEntryElement(entry); struct.getDecorator().setProgress(i); // set queue pos return struct; } } } if((searchFlags & SEARCH_RESULTS)!=0) { list=resultRoot.getElementsByTagName("result"); for(int i=0;i<list.getLength();i++) { Element submission=(Element) list.item(i); if(submission.getAttribute("id").equals(subID)) { return AccessStructure.fromXMLResultElement(submission); } } } return null; } /** * Adds a completed submission to the resultRoot and removes the first * submission from the elementRoot */ public synchronized void addResult(AccessStructure struct) { NodeList usersList=resultRoot.getElementsByTagName("user"); Element founduser=null; for(int i=0;i<usersList.getLength();i++) { Element user=(Element) usersList.item(i); if(user.getAttribute("username").equals(struct.getUsername())) { founduser=user; break; } } if(founduser==null) { founduser=doc.createElement("user"); founduser.setAttribute("username",struct.getUsername()); resultRoot.appendChild(founduser); } founduser.appendChild(struct.toXMLResultElement(doc)); // XXX: Check whether the first is the right one Node firstEntry=entryRoot.getFirstChild(); entryRoot.removeChild(firstEntry); writeXMLFile(); } /** * Removes a given ready to be processed submission from the database * @return True, when it was successfully deleted. * False, if the submission wasn't found. */ public synchronized boolean deleteEntry(String username, String submissionID) { NodeList list=entryRoot.getElementsByTagName("entry"); for(int i=0;i<list.getLength();i++) { Element entry=(Element) list.item(i); if(entry.getAttribute("id").equals(submissionID)) { if(!entry.getAttribute("username").equals(username)) return false; entryRoot.removeChild(entry); writeXMLFile(); return true; } } return false; } /** * Removes a given completed submission from the database * @return True, when it was successfully deleted. * False, if the submission wasn't found. */ public synchronized boolean deleteResult(String username, String submissionID) { NodeList usersList = resultRoot.getElementsByTagName("user"); int numusers = usersList.getLength(); for(int i=0; i<numusers; i++) { Element user = (Element) usersList.item(i); if(user.getAttribute("username").equals(username)) { NodeList subList = user.getElementsByTagName("result"); int numresults = subList.getLength(); for(int j=0; j<numresults; j++) { Element elem = (Element) subList.item(j); if(elem.getAttribute("id").equals(submissionID)) { user.removeChild(elem); if(numresults==1) // removed last result? resultRoot.removeChild(user); // remove user entry writeXMLFile(); return true; } } } } return false; } /** * Deletes an submission from the database * @param struct: Submission to be deleted * @return true, if everything's alright */ public synchronized boolean deleteSubmission(AccessStructure struct) { if(struct.getState()<300) return deleteEntry(struct.getUsername(),struct.getSubmissionID()); else return deleteResult(struct.getUsername(),struct.getSubmissionID()); } /** * @return String array containing all usernames */ public synchronized String[] usersList() { NodeList usersList= doc.getElementsByTagName("user"); String [] result = new String [usersList.getLength()]; for(int i=0;i<usersList.getLength();i++) { Element user=(Element) usersList.item(i); result[i]=user.getAttribute("username"); } return result; } /** * @return The number of waiting submissions for a given user */ public synchronized int getNumUserEntries(String username) { NodeList list=entryRoot.getElementsByTagName("entry"); int numentries=0; for(int j=0;j<list.getLength();j++) { Element entry=(Element) list.item(j); if(entry.getAttribute("username").equals(username)) numentries++; } return numentries; } /** * @return The number of finished submissions for a given user */ public synchronized int getNumUserResults(String username) { NodeList usersList=doc.getElementsByTagName("user"); for(int i=0;i<usersList.getLength();i++) { Element user=(Element) usersList.item(i); if(user.getAttribute("username").equals(username)) { NodeList subList=user.getElementsByTagName("result"); return subList.getLength(); } } return 0; } /** * @return A list of Submission objects belonging to a given user */ public synchronized Submission[] listSubmissions(String username) { NodeList usersList=doc.getElementsByTagName("user"); for(int i=0;i<usersList.getLength();i++) { Element user=(Element) usersList.item(i); if(user.getAttribute("username").equals(username)) { NodeList list=entryRoot.getElementsByTagName("entry"); int numentries=0; for(int j=0;j<list.getLength();j++) { Element entry=(Element) list.item(j); if(entry.getAttribute("username").equals(username)) numentries++; } NodeList subList = user.getElementsByTagName("result"); Submission[] subArray = new Submission[numentries+subList.getLength()]; int subind=0; for(int j=0;j<list.getLength();j++) { Element entry=(Element) list.item(j); if(entry.getAttribute("username").equals(username)) { String subID=entry.getAttribute("id"); int state=JPlagCentral.getStateIfActive(username,subID); subArray[subind++]=new Submission(subID, entry.getAttribute("title"),new java.util.Date( Long.parseLong(entry.getAttribute("date"))) .toString(),state); } } for(int j=0;j<subList.getLength();j++) { Element elem=(Element) subList.item(j); int laststate; try { laststate=Integer.parseInt( elem.getAttribute("laststate")); } catch(NumberFormatException e) { laststate=499; } subArray[subind++]=new Submission(elem.getAttribute("id"), elem.getAttribute("title"), new java.util.Date( Long.parseLong(elem.getAttribute("date"))) .toString(), laststate); } return subArray; } } return new Submission[0]; } /** * @return A list of AccessStructure objects belonging to a given user */ public synchronized AccessStructure[] listAccessStructures(String username) { NodeList usersList=doc.getElementsByTagName("user"); for(int i=0;i<usersList.getLength();i++) { Element user=(Element) usersList.item(i); if(user.getAttribute("username").equals(username)) { NodeList list=entryRoot.getElementsByTagName("entry"); int numentries=0; for(int j=0;j<list.getLength();j++) { Element entry=(Element) list.item(j); if(entry.getAttribute("username").equals(username)) numentries++; } NodeList subList=user.getElementsByTagName("result"); AccessStructure[] structArray=new AccessStructure[ numentries+subList.getLength()]; int subind=0; for(int j=0;j<list.getLength();j++) { Element entry=(Element) list.item(j); if(entry.getAttribute("username").equals(username)) structArray[subind++] = AccessStructure.fromXMLEntryElement(entry); } for(int j=0;j<subList.getLength();j++) { Element elem=(Element) subList.item(j); structArray[subind++] = AccessStructure.fromXMLResultElement(elem); } return structArray; } } return new AccessStructure[0]; } }