/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package services; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import org.oasisopen.sca.annotation.Init; import org.oasisopen.sca.annotation.Property; import com.example.ipo.jaxb.Item; import com.example.ipo.jaxb.JiraData; import com.example.ipo.jaxb.Milestone; import com.example.ipo.jaxb.Plan; import com.example.ipo.jaxb.RSS; import com.example.ipo.jaxb.WorkItem; public class PlanViewImpl implements PlanView { static String rssPrefix = "http://issues.apache.org/jira/si/jira.issueviews:issue-xml/"; @Property public String planFile = "src/main/resources/jiraSideBand.xml"; Map msmap = null; Map wimap = null; Map wi2msmap = null; @Init public void init() { } private Plan getPlan() { Plan p = null; try { p = readPlan(); augmentPlan(p); scanPlan(p); writePlan(p); // writes cached augmentations from jira system, allowing for getLite() } catch (Exception e) { e.printStackTrace(); } return p; } private void scanPlan(Plan plan) { msmap = new HashMap(); wimap = new HashMap(); wi2msmap = new HashMap(); for(Milestone m : plan.getMilestone()) { msmap.put(m.getID(), m); for (WorkItem wi: m.getWorkItem()) { wimap.put(wi.getID(), wi); wi2msmap.put(wi.getID(), m); } } } private void augmentPlan(Plan plan) { for(Milestone m : plan.getMilestone()) { for (WorkItem wi: m.getWorkItem()) { augmentWorkItem(wi); } } } private void augmentWorkItem(WorkItem wi) { String jira = wi.getJira(); if(jira != null) { JiraData jd = new JiraData(); wi.setJiraData(jd); jd.setID(jira); try { JAXBContext jaxbContext = JAXBContext .newInstance("com.example.ipo.jaxb"); Unmarshaller m2 = jaxbContext.createUnmarshaller(); InputStream is = null; RSS jfeed = null; try{ URL url = new URL("http://issues.apache.org/jira/si/jira.issueviews:issue-xml/"+jira+"/"+jira+".xml"); is = url.openStream(); jfeed = ((JAXBElement) m2.unmarshal(is)).getValue(); } catch (FileNotFoundException e) { String note = wi.getNote(); note += ": attempt to reference non-existent JIRA " + jira; wi.setNote(note); wi.setJira(null); wi.setJiraData(null); } finally { if(is != null) is.close(); } if(jfeed != null) { Item i = jfeed.getChannel().getItem(); List> c = i.getContent(); // TODO see if there's a better way to get this data out for (JAXBElement element : c) { if("title".equals(element.getName().getLocalPart())) { String jtitle = (String)element.getValue(); jd.setTitle(jtitle.substring(jtitle.indexOf(']')+1, jtitle.length())); } else if("status".equals(element.getName().getLocalPart())){ jd.setStatus((String)element.getValue()); } else if("assignee".equals(element.getName().getLocalPart())) { jd.setAssignedTo((String)element.getValue()); } } } } catch (Exception e) { e.printStackTrace(); } finally { } } } public Plan get() { Plan p = getPlan(); return p; } public Plan getLite() { Plan p = readPlan(); scanPlan(p); return p; } private Milestone getMS(Plan p, String id) { Milestone rv = null; if(msmap.containsKey(id)) { rv = msmap.get(id); } return rv; } public void postNewWorkItem(String msid, String jira) { Plan p = getPlan(); Milestone m = getMS(p,msid); WorkItem wi = new WorkItem(); wi.setJira(jira); augmentWorkItem(wi); m.getWorkItem().add(wi); writePlan(p); } public void postNewMilestone(String msid) { Plan p = getPlan(); if(getMS(p, msid) == null) { List mis = p.getMilestone(); Milestone newm = new Milestone(); newm.setID(msid); mis.add(newm); writePlan(p); } } private void writePlan(Plan p) { FileOutputStream fos = null; String dbPath = null; File existingFile = null; File newFile= null; String backupPath = null; try { JAXBContext jaxbContext = JAXBContext .newInstance("com.example.ipo.jaxb"); Marshaller m = jaxbContext.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); existingFile = new File(planFile).getAbsoluteFile(); dbPath = existingFile.getAbsolutePath(); String tempPath = dbPath.substring(0,dbPath.indexOf(".xml"))+".tmp.xml"; backupPath = dbPath.substring(0,dbPath.indexOf(".xml")); DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss"); String timestamp = df.format(Calendar.getInstance().getTime()); backupPath+= timestamp; backupPath+=".xml"; newFile = new File(tempPath).getAbsoluteFile(); fos = new FileOutputStream(newFile); m.marshal(p, fos); } catch (Exception e) { e.printStackTrace(); } finally { } if(fos!=null) try { fos.close(); new File(dbPath).renameTo(new File(backupPath)); newFile.renameTo(new File(dbPath)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private Plan readPlan() { Plan p = null; try { JAXBContext jaxbContext = JAXBContext .newInstance("com.example.ipo.jaxb"); Unmarshaller m = jaxbContext.createUnmarshaller(); File inputFile = new File(planFile).getAbsoluteFile(); if(!inputFile.exists()){ // start afresh Plan newPlan = new Plan(); writePlan(newPlan); inputFile = new File(planFile).getAbsoluteFile(); } p = (Plan)m.unmarshal(inputFile); } catch(Exception e) { throw new IllegalStateException("Failed to read plan file",e); } return p; } public Plan updateWI(String wiID, String jira, String note, String link, String msID) { Plan p = getLite(); WorkItem wi = null; boolean newMS = false; boolean newWI = false; boolean changedMS = false; // existing or new WI if(wimap.containsKey(wiID)) { wi = wimap.get(wiID); } else if("_new_".equals(wiID)) { newWI = true; wi = new WorkItem(); p.setMaxWorkItemID(p.getMaxWorkItemID()+1); // Note concurrency issue possibility. No mutex around this wi.setID("wi"+p.getMaxWorkItemID()); wiID = wi.getID(); // TODO ensure wi2msmap updated below } else { throw new IllegalStateException("Work Item not known: " + wiID); } Milestone ms = null; if(msID == null || "".equals(msID)) { msID = "unassigned"; } if(msmap.containsKey(msID)) { ms = getMS(p, msID); } else { newMS = true; ms = new Milestone(); ms.setID(msID);;; } if(!newWI && !msID.equals(wi2msmap.get(wiID).getID())) { changedMS = true; } wi.setJira(jira); wi.setNote(note); wi.setLink(link); augmentWorkItem(wi); if(newMS) { p.getMilestone().add(ms); } if(newWI) { ms.getWorkItem().add(wi); } if(changedMS) { Milestone oldms = wi2msmap.get(wi.getID()); oldms.getWorkItem().remove(wi); ms.getWorkItem().add(wi); } writePlan(p); return p; } private WorkItem getWorkItem(String wiID) { return wimap.get(wiID); } }