Skip to content

Commit

Permalink
Merge remote-tracking branch 'awesome/master'
Browse files Browse the repository at this point in the history
Conflicts:
	build.properties
  • Loading branch information
betelgeuse committed Apr 2, 2012
2 parents 19049e4 + 30b3023 commit 7e7c84d
Show file tree
Hide file tree
Showing 12 changed files with 194 additions and 35 deletions.
2 changes: 1 addition & 1 deletion doc/sql/rename-anony-tables.sql
@@ -1,7 +1,7 @@
-- Rename anonymous tables back to original
-- Its a temporary solution, Todo: write a script to go information_schema.tables and rename it
-- Used the following statement to create this file
-- select concat ('RENAME TABLE agilefant.anonym_', table_name, ' TO agilefant.', table_name, ';') FROM information_schema.tables WHERE table_schema = 'agilefant' INTO OUTFILE 'path';



RENAME TABLE agilefant.anonym_agilefant_revisions TO agilefant.agilefant_revisions;
Expand Down
Expand Up @@ -216,6 +216,26 @@ public int compare(Scheduled o1, Scheduled o2) {
for (LeafStoryContainer container : backlogs.values()) {
Collections.sort(container.getLeafStories(), comparator);
}

// Added standalone iterations
List<Iteration> standAloneIterations = new ArrayList<Iteration>(iterationBusiness.retrieveAllStandAloneIterations());
List<IterationTO> standIter = new ArrayList<IterationTO>();

for(Iteration iter :standAloneIterations ){
IterationTO iterTo = transferObjectBusiness.constructIterationTO(iter);

// Added storyTo object as well
List<Story> standAloneStories = storyBusiness.retrieveStoriesInIteration(iter);
List<StoryTO> standAloneStoriesTo = new ArrayList<StoryTO>();
for(Story s : standAloneStories){
standAloneStoriesTo.add(transferObjectBusiness.constructStoryTO(s));
}

iterTo.setRankedStories(standAloneStoriesTo);
standIter.add(iterTo);
}

root.setStandaloneIterations(standIter);
return root;
}

Expand Down
60 changes: 37 additions & 23 deletions src/fi/hut/soberit/agilefant/db/export/DbBackupStreamGenerator.java
Expand Up @@ -19,6 +19,7 @@ public class DbBackupStreamGenerator {
private String dbPassword;
private String dbHost;
private String dbName;
private boolean anonymouse=false;
private String errorMessage;
private ByteArrayOutputStream zippedDbOutputStream;

Expand All @@ -30,26 +31,26 @@ public class DbBackupStreamGenerator {
* @param dbPassword Database password, e.g. "secret"
*/
public DbBackupStreamGenerator(String dbName, String dbHost, String dbUsername, String dbPassword) {

this.dbLogin = dbUsername;
this.dbName = dbName;
this.dbPassword = dbPassword;
this.dbHost = dbHost;

this.errorMessage = "";
this.zippedDbOutputStream = new ByteArrayOutputStream();
}


/**
* Returns dumped database as zipped ByteArrayOutputStream. It's
* usually a good idea to call generate first
*/
public ByteArrayOutputStream getZippedDbOutputStream() {
return this.zippedDbOutputStream;
}


/**
* Calls mysqldump and generates zipped stream returns 0 if backup was
* saved correctly, -1 if try fails, and >1 are sql errors
Expand All @@ -59,76 +60,89 @@ public int generateZippedDbOutputStream() {
String dumpcommand = ("mysqldump" + " -h " + dbHost + " -u " + dbLogin + " -p" + dbPassword + " " + dbName);
return executeDumpCmd(dumpcommand, "fantbackup.sql");
}

/**
* Calls mysqldump and generates zipped stream returns 0 if backup was
* saved correctly, -1 if try fails, and >1 are sql errors
* Only generate anonymous data
*/
public int generateZippedAnonymousDbOutputStream(ArrayList<String> excludedTables) {

String dumpcommand = ("mysqldump" + " -h " + dbHost + " -u " + dbLogin + " -p" + dbPassword + " " + dbName);

// ignore original tables
for(int i=0; i< excludedTables.size(); i++ )
{
dumpcommand += " --ignore-table=" + dbName + "." + excludedTables.get(i);
}
anonymouse=true;
return executeDumpCmd(dumpcommand, "AnonymousFantBackup.sql");
}

public int executeDumpCmd(String dumpcommand, String fileName)
{

try {
Runtime dbb = Runtime.getRuntime();
Process process = dbb.exec(dumpcommand);

InputStream in = process.getInputStream();

zippedDbOutputStream = new ByteArrayOutputStream();
ZipOutputStream outzip = new ZipOutputStream(zippedDbOutputStream);
int len;
if (anonymouse==true) {
Sqlfilecontentgenerator sqlscript = new Sqlfilecontentgenerator();
outzip.putNextEntry(new ZipEntry("importscript.sql"));
InputStream inscript = sqlscript.getScriptByteStream();

while ((len = inscript.read()) != -1) {
outzip.write(len);
}
outzip.closeEntry();
}

outzip.putNextEntry(new ZipEntry(fileName));

// loop through the inputstream that contains mysqldump output and zip it
int ch;
while ((ch = in.read()) != -1) {
outzip.write(ch);

while ((len = in.read()) != -1) {
outzip.write(len);
}

in.close();
outzip.closeEntry();
outzip.close();

// read the error stream to a field
this.readProcessErrors(process);

// 0 means success, 1+ are mysqldump error codes
int exitval = process.exitValue();
return exitval;

} catch (Throwable t) {
t.printStackTrace();
}
return -1; // return -1 if try didn't finish
}

/**
* Stores error messages from process's error stream for later access
* @param stdErr
* @throws IOException
*/
private void readProcessErrors(Process process) throws IOException {

InputStream stdErr = process.getErrorStream();

InputStreamReader stdErrReader = new InputStreamReader(stdErr);
BufferedReader bufferedStdErrReader = new BufferedReader(stdErrReader);

String line = null;
while ((line = bufferedStdErrReader.readLine()) != null) {
this.errorMessage = this.errorMessage + line;
}
}


/**
* Shows error message generated by mysqldump Returns errormessage
Expand Down
@@ -0,0 +1,65 @@
package fi.hut.soberit.agilefant.db.export;

import java.util.ArrayList;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import fi.hut.soberit.agilefant.util.DbConnectionInfo;


public class Sqlfilecontentgenerator
{
// private static final String dbinfo = null;
private ArrayList<String> listOfTables = new ArrayList<String>();
private DbConnectionInfo dbinfo;
private Connection connection = null;
private String sqlscript= "";
public Sqlfilecontentgenerator() throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException
{
this.dbinfo = new DbConnectionInfo();
getdbtables();
generateScriptString();
}



private void getdbtables() throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException
{

PreparedStatement ps = null;
String sqlConnection = this.dbinfo.getUrl();
Class.forName(dbinfo.getDriver()).newInstance();
connection = DriverManager.getConnection(sqlConnection, dbinfo.getUsername(), dbinfo.getPassword());
String query = "select table_name FROM information_schema.tables WHERE table_schema = 'agilefant' AND table_name LIKE 'anonym_%'";
ps = connection.prepareStatement(query);
ResultSet s = ps.executeQuery();
while(s.next())
{
listOfTables.add(s.getString("table_name"));
}

}
private void generateScriptString()
{

int tablesize=listOfTables.size();
int counter=0;
while (tablesize>counter)
{
sqlscript= sqlscript + "RENAME TABLE "+ listOfTables.get(counter) + " TO " + listOfTables.get(counter).substring(listOfTables.get(counter).indexOf('_')+1)+ ";" + System.getProperty("line.separator");
counter++;
}
}


public InputStream getScriptByteStream()
{
InputStream sqlscriptstream = new ByteArrayInputStream(sqlscript.getBytes());
return sqlscriptstream;
}
}
8 changes: 8 additions & 0 deletions src/fi/hut/soberit/agilefant/transfer/ProductTO.java
Expand Up @@ -11,6 +11,8 @@ public class ProductTO extends Product implements LeafStoryContainer {
private List<StoryTO> leafStories = new ArrayList<StoryTO>();
private List<ProjectTO> childProjects = new ArrayList<ProjectTO>();

private List<IterationTO> standaloneIterations = new ArrayList<IterationTO>();

public ProductTO() {};
public ProductTO(Product product) {
BeanCopier.copy(product, this);
Expand All @@ -27,4 +29,10 @@ public List<ProjectTO> getChildProjects() {
public void setChildProjects(List<ProjectTO> childProjects) {
this.childProjects = childProjects;
}
public List<IterationTO> getStandaloneIterations() {
return standaloneIterations;
}
public void setStandaloneIterations(List<IterationTO> standaloneIterations) {
this.standaloneIterations = standaloneIterations;
}
}
@@ -1,6 +1,7 @@
package fi.hut.soberit.agilefant.business;

import static org.easymock.EasyMock.expect;
import java.util.List;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
Expand Down Expand Up @@ -234,6 +235,8 @@ public void testRetrieveLeafStoriesOnly() {
Arrays.asList(productStory, projectStory, iterationStory,
iterationStory2));

List<Iteration> iters = new ArrayList<Iteration>();
expect(iterationBusiness.retrieveAllStandAloneIterations()).andReturn(iters);
expect(transferObjectBusiness.getBacklogScheduleStatus(project)).andReturn(ScheduleStatus.FUTURE);
expect(transferObjectBusiness.getBacklogScheduleStatus(iteration)).andReturn(ScheduleStatus.PAST);

Expand Down Expand Up @@ -292,6 +295,8 @@ public void testRetrieveLeafStoriesOnly_backlogOrder() {
expect(productDAO.retrieveLeafStories(product)).andReturn(
new ArrayList<Story>());

List<Iteration> iters = new ArrayList<Iteration>();
expect(iterationBusiness.retrieveAllStandAloneIterations()).andReturn(iters);
expect(transferObjectBusiness.getBacklogScheduleStatus(project1)).andReturn(ScheduleStatus.ONGOING);
expect(transferObjectBusiness.getBacklogScheduleStatus(project2)).andReturn(ScheduleStatus.PAST);
expect(transferObjectBusiness.getBacklogScheduleStatus(project3)).andReturn(ScheduleStatus.FUTURE);
Expand Down
7 changes: 6 additions & 1 deletion web/WEB-INF/jsp/dbExportError.jsp
Expand Up @@ -3,7 +3,12 @@
<struct:htmlWrapper navi="">

<h2>An error occurred</h2>
<p>The database export connection could not be established, please consult the administrator.<a
<p>The database export connection could not be established. Most likely
your Agilefant installation's database connection is configured
differently from what is described in the installation guide. Please
contact the person who is responsible for your Agilefant
installation.
<br/><a
href="javascript:history.back(-1)">Try again</a>
<p><ww:actionerror /> <ww:fielderror /> <ww:actionmessage />

Expand Down
6 changes: 5 additions & 1 deletion web/WEB-INF/jsp/editProduct.jsp
Expand Up @@ -20,7 +20,7 @@ pageContext.setAttribute("defaultEndDate", now.plusMonths(3));
border: 1px dashed #ccc;
}
.widgetContainer {
width: 33% !important;
width: 25% !important;
}
.widget {
min-width: 200px !important;
Expand Down Expand Up @@ -73,6 +73,7 @@ pageContext.setAttribute("defaultEndDate", now.plusMonths(3));

<jsp:body>


<aef:backlogBreadCrumb backlog="${product}" />

<div class="structure-main-block" id="backlogInfo">
Expand Down Expand Up @@ -320,5 +321,8 @@ $(document).ready(function() {
</div>


<div class="iterationStoryToolTip">
<span>Stories in an iteration can't have child stories.</span>
</div>
</jsp:body>
</struct:htmlWrapper>
3 changes: 3 additions & 0 deletions web/WEB-INF/jsp/editProject.jsp
Expand Up @@ -107,5 +107,8 @@ $(document).ready(function() {
<img src="drawProjectBurnup.action?backlogId=${project.id}" id="bigChart" width="780" height="600" />
</p>

<div class="iterationStoryToolTip">
<span>Stories in an iteration can't have child stories.</span>
</div>
</jsp:body>
</struct:htmlWrapper>
21 changes: 20 additions & 1 deletion web/WEB-INF/jsp/fragments/productBacklogView.jsp
Expand Up @@ -22,7 +22,6 @@ $(document).ready(function() {
</script>



<div class="widgetContainer">
<h3>Product</h3>
<ul class="widgetList">
Expand Down Expand Up @@ -82,5 +81,25 @@ $(document).ready(function() {
</ul>
</div>

<div class="widgetContainer">
<h3>Standalone Iterations</h3>
<ul class="widgetList">
<c:forEach items="${product.standaloneIterations}" var="iteration">
<li class="widget iterationWidget droppableWidget scheduled staticWidget" backlogid="${iteration.id}">
<struct:widget name="${iteration.name}" widgetId="-1" backlogId="${iteration.id}">
<div class="timeframe">Timeframe: <span><joda:format value="${iteration.startDate}" pattern="YYYY-MM-dd" /></span> to <span><joda:format value="${iteration.endDate}" pattern="YYYY-MM-dd" /></span></div>
<input type="hidden" name="startDate" value='<joda:format value="${iteration.startDate}" pattern="YYYY-MM-dd" />' />
<input type="hidden" name="endDate" value='<joda:format value="${iteration.endDate}" pattern="YYYY-MM-dd" />' />
<ul class="storyList" style="min-height: 20px;">
<c:forEach items="${iteration.leafStories}" var="story">
<li storyId="${story.id}"><aef:storyTreeField story="${story}" type="state" /> ${story.name}</li>
</c:forEach>
</ul>
</struct:widget>
</li>
</c:forEach>
</ul>
</div>

<div style="width: 100%; clear: both;">&nbsp;</div>

0 comments on commit 7e7c84d

Please sign in to comment.