relative links not working in CruiseControl.NET HtmlReportPlugin - iis

I have a merge task in the publisher area of my CruiseControl.NET project that successfully copies a collection of html and png files to the artifacts directory. I've enabled the HtmlReportPlugin in the dashboard like this:
<buildPlugins>
<buildReportBuildPlugin>
<xslFileNames>
<xslFile>xsl\header.xsl</xslFile>
<xslFile>xsl\compile.xsl</xslFile>
<xslFile>xsl\modifications.xsl</xslFile>
<xslFile>xsl\MsTestSummary2010.xsl</xslFile>
</xslFileNames>
</buildReportBuildPlugin>
<buildLogBuildPlugin />
<xslReportBuildPlugin description="MSTest2010 Report" actionName="MSTestBuildReport2010" xslFileName="xsl\MsTestReport2010.xsl"></xslReportBuildPlugin>
<xslReportBuildPlugin description="MSTest Coverage 2010" actionName="MSTestBuildCoverReport2010" xslFileName="xsl\MsTestCover2010.xsl"></xslReportBuildPlugin>
<htmlReportPlugin description="Html Report" actionName="HtmlReport" htmlFileName="index.html" />
</buildPlugins>
The index.html is served just fine, but relative links within index.html don't seem to work. Here's the source to index.html:
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Frameset//EN'
'http://www.w3.org/TR/html4/frameset.dtd'>
<html><head><title>
all.cov
</title>
<meta http-equiv=Content-Type content='text/html;charset=utf-8'>
</head>
<frameset cols='25%,75%'>
<frame src=nav-folder.html>
<frame name=right src=p0.html>
<noframes>
<p>Your browser does not support frames. See <a href=nav-folder.html>nav-folder.html</a>
</noframes>
</frameset>
</html>
And here's one of the errors that I get when loading index.html (replace 'nav-folder' with 'p0' for the other error message):
Server Error in '/' Application.
Unknown object name : nav-folder
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: System.ApplicationException: Unknown object name :
nav-folder
Source Error:
An unhandled exception was generated during the execution of the
current web request. Information regarding the origin and location of
the exception can be identified using the exception stack trace below.
Stack Trace:
[ApplicationException: Unknown object name : nav-folder]
Objection.ObjectionStore.GetByName(String name) +307
ThoughtWorks.CruiseControl.WebDashboard.MVC.Cruise.CruiseActionFactory.CreateHandler(String
actionName) +231
ThoughtWorks.CruiseControl.WebDashboard.MVC.Cruise.CruiseActionFactory.Create(IRequest
request) +38
ThoughtWorks.CruiseControl.WebDashboard.MVC.RequestController.Do()
+155 ThoughtWorks.CruiseControl.WebDashboard.MVC.ASPNET.HttpHandler.ProcessRequest(HttpContext
context) +651
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
+625 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +27
If I use RetrieveBuildFile.aspx on either of the reference files (for example, http://localhost/server/local/project/Code_Coverage/build/log20120809181334Lbuild.168.xml/RetrieveBuildFile.aspx?file=p0.html), the files load without a problem, but as in the first example, any relative files will fail to load.
Is there something I have to do in my CruiseControl.NET web.config to get IIS to correctly resolve relative file paths? I am using CruiseControl.NET 1.8.0 and I am running IIS 7 running on Windows 2008, and I have verified that the same issue occurs on a CruiseControl.NET 1.6?? on IIS running on Windows 7.

Unfortunately HTML tidy didn't like the Bullseye CodeCoverage HTML as it contains invalid HTML. So that solution won't work.
CruiseControl uses a regular expression to find source links, but this isn't perfect because it misses the case where HTML attributes don't have quotes and it could match string fragments that are not HTML attributes. I've modified the CruiseControl.NET source code to use the HtmlAgilityPack to parse the HTML and this seems to work very well (at least on my test cases.)

If you need to solve this problem (without looking on your own where CCnet parses html). I'm using ReportGenerator with CCnet. Here's an example:
In class:
BuildFileDownload (namespace ThoughtWorks.CruiseControl.WebDashboard.Plugins.BuildReport)
Modify Execute procedure by using this code:
HtmlDocument doc = new HtmlDocument();
doc.OptionAddDebuggingAttributes = false;
doc.OptionAutoCloseOnEnd = false;
doc.OptionCheckSyntax = false;
doc.OptionFixNestedTags = false;
doc.OptionOutputOptimizeAttributeValues = false;
doc.LoadHtml(htmlData);
var nodes = doc.DocumentNode.SelectNodes("//a[#href]");
if (nodes != null)
{
foreach (var link in nodes)
{
HtmlAttribute att = link.Attributes["href"];
if (!att.Value.StartsWith("data:") && !att.Value.StartsWith("#") && !att.Value.StartsWith("http://"))
att.Value = #"RetrieveBuildFile.aspx?file=coverageReport\" + att.Value;
}
htmlData = doc.DocumentNode.WriteTo();
}
nodes = doc.DocumentNode.SelectNodes("//link[#href]");
if (nodes != null)
{
foreach (var link in nodes)
{
HtmlAttribute att = link.Attributes["href"];
if (!att.Value.StartsWith("data:") && !att.Value.StartsWith("#") && !att.Value.StartsWith("http://"))
att.Value = #"RetrieveBuildFile.aspx?file=coverageReport\" + att.Value;
}
htmlData = doc.DocumentNode.WriteTo();
}
Remember to get rid of old regEx parsing first. It's a sample code but it fits all my needs. This solution uses HtmlAgilityPack. Note that path given as a prefix for new attribute value may differ.

The issue was that CruiseControl.NET doesn't like HTML with attributes with values that aren't quoted. I'm using output generated by Bullseye CodeCoverage and that output has attributes with values that aren't quoted. I'm using HTML Tidy to add quotes.

Related

why images are not loaded despite of correct url in IIS 7?

this is the code to read the complete path with name of all files (images) from the folder inside the project
#{ string[] imgfiles = Directory.GetFiles(#"D:\MVClearningProjects\Demo\Demo\Property_Data\Images\" + item.Property_ID, "*.*");}
this code is to load the first image to cshtml view file
<img src="#Url.Content(imgfiles[0])" alt="carousel bootstrap first" readonly style="width:200px; height:120px;" />
//not allowed local resources when I run this project usig ISS
Like the error message is telling you, you are not allowed to do that. Due to security reasons, most browsers simply will not allow the use of file://. You need to host it with your application and load it from the web server.
Have a look at this great SO answer for an explanation and proposed solution to the problem.
This error was due to using the .physical path instead of virtual in following code
#{ string[] imgfiles = Directory.GetFiles(#"D:\MVClearningProjects\Demo\Demo\Property_Data\Images\" + item.Property_ID, "*.*");}
<img src="#Url.Content(imgfiles[0])" alt="carousel bootstrap first" readonly style="width:200px; height:120px;" />
I fixed it by replacing the physical path with virtual
#{ string[] imgfiles = Directory.GetFiles(#"D:\MVClearningProjects\Demo\Demo\Property_Data\Images\" + item.Property_ID, "*.*");
for (int i = 0; i < imgfiles.Length; i++)
{//converting physical address into virtual
imgfiles[i]= imgfiles[i].Replace(#"D:\MVClearningProjects\Demo\Demo", "~").Replace(#"\", "/");
}
}
<img src="#Url.Content(imgfiles[0])" alt="carousel bootstrap first" readonly style="width:200px; height:120px;" />

Automatically open the printer dialog after providing PDF download

I am currently opening a pdf file in a new tab in my browser but I need to know how to open a printer dialog to print the pdf jasper report after pressing a commandButton
This is the method that open the pdf in a new tab:
public void printJasper() {
JasperReport compiledTemplate = null;
JRExporter exporter = null;
ByteArrayOutputStream out = null;
ByteArrayInputStream input = null;
BufferedOutputStream output = null;
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
try {
List<String> sampleList = new ArrayList<String>();
sampleList.add("Fist sample string");
sampleList.add("Second sample string");
JRBeanCollectionDataSource beanCollectionDataSource = new JRBeanCollectionDataSource(sampleList);
Map<String, Object> reportValues = new HashMap<String, Object>();
reportValues.put("anyTestValue", "test value");
facesContext = FacesContext.getCurrentInstance();
externalContext = facesContext.getExternalContext();
response = (HttpServletResponse) externalContext.getResponse();
FileInputStream file = new FileInputStream("/any_dir/sample.jasper");
compiledTemplate = (JasperReport) JRLoader.loadObject(file);
out = new ByteArrayOutputStream();
JasperPrint jasperPrint = JasperFillManager.fillReport(compiledTemplate, reportValues, beanCollectionDataSource);
exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
exporter.exportReport();
input = new ByteArrayInputStream(out.toByteArray());
response.reset();
response.setHeader("Content-Type", "application/pdf");
response.setHeader("Content-Length", String.valueOf(out.toByteArray().length));
response.setHeader("Content-Disposition", "inline; filename=\"fileName.pdf\"");
output = new BufferedOutputStream(response.getOutputStream(), Constants.DEFAULT_BUFFER_SIZE);
byte[] buffer = new byte[Constants.DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
output.flush();
} catch (Exception exception) {
/* ... */
} finally {
try {
if (output != null) {
output.close();
}
if (input != null) {
input.close();
}
} catch (Exception exception) {
/* ... */
}
}
facesContext.responseComplete();
}
This is the button that open the pdf file:
<p:commandButton action="#{sampleBB.printJasper}"
ajax="false" onclick="this.form.target='_blank'"
value="#{msg['generate.report']}" />
What I need to do?
With JasperReports
When using JasperReports, simply add this parameter to JasperReports exporter:
exporter.setParameter(JRPdfExporterParameter.PDF_JAVASCRIPT, "this.print();");
This basically instructs Adobe Acrobat to execute the script this.print() when opening the PDF. See also page 79-80 of Adobe Acrobat Scripting Guide. Below is an extract of relevance:
Printing PDF Documents
It is possible to use Acrobat JavaScript to specify whether a PDF document is sent to a
printer or to a PostScript file. In either case, to print a PDF document, invoke the doc
object’s print method. [...]
Without JasperReports
If you don't have control over generation of PDFs and thus can't manipulate it to add the mentioned script, an alternative is to change all the Java/JSF code accordingly so that the PDF file is idempotently available (i.e. the PDF file must be available by just a GET request rather than a POST request). This allows you to embed it in an <iframe> for which it's in turn possible to print its content by JavaScript during onload (keep CORS in mind though).
Simply put, the enduser must be able to download the desired PDF file by just entering its URL in browser's address bar. You can of course make use of GET request query string to specify parameters, allowing a bit more dynamicness. If it's "very large" data, then you can always let JSF put it in the HTTP session or DB and then pass an unique identifier around as request parameter so that the servlet can in turn obtain it from the very same HTTP session or DB.
Whilst possible with some nasty hacks, a JSF backing bean is simply insuitable for the job of idempotently serving a non-JSF response. You'd better use a "plain vanilla" servlet for this. You'll end up with much simpler code. Here's a kickoff example of such a servlet:
#WebServlet("/pdf")
public class PdfServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String foo = request.getParameter("foo");
String bar = request.getParameter("bar");
// ...
// Now just use the same code as in your original bean *without* FacesContext.
// Note that the HttpServletResponse is readily available as method argument!
response.setContentType("application/pdf");
// ...
}
}
With this setup, it's available by http://localhost:8080/context/pdf?foo=abc&bar=xyz.
Once you get that part to work, then you just have to reference it in an <iframe> which uses JavaScript to print its own content window during its load event. You can do this in a JSF page, e.g. /pdf.xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
>
<h:head>
<style>html, body { height: 100%; margin: 0; overflow: hidden; }</style>
</h:head>
<h:body>
<iframe src="#{request.contextPath}/pdf?#{request.queryString}"
width="100%" height="100%" onload="this.contentWindow.print()" />
</h:body>
</html>
All you need to do in your JSF backing bean is to send a redirect to that page, if necessary with parameters in request query string (which will end up in #{request.queryString} so that the servlet can obtain them via request.getParameter(...)).
Here's a kickoff example:
<h:form target="_blank">
<h:commandButton value="Generate report" action="#{bean.printPdf}" />
</h:form>
public String printPdf() {
// Prepare params here if necessary.
String foo = "abc";
String bar = "xyz";
// ...
return "/pdf?faces-redirect=true"
+ "&foo=" + URLEncoder.encode(foo, "UTF-8")
+ "&bar=" + URLEncoder.encode(bar, "UTF-8");
}
There is a <p:printer> Primefaces's component for that purpose.
Something like this might work, not tested though.
<h:form>
<h:commandButton value="Print" type="button" icon="ui-icon-print">
<p:printer target="pdf" />
</h:commandButton>
<p:media style="display:none;" id="pdf" value="/aPDF.pdf" />
</h:form>
Note :
<p:media> does have a print button to print the displayed pdf.
Edit :
You have to embed the pdf file inside an iframe and use the JavaScript print() function on it, or you can activate the auto-print function in the PDF itself. But it is definitely possible.
See this question on SO : Can a PDF file's print dialog be opened with Javascript?
How to Use JavaScript to Print a PDF
You can't print a URL directly from JavaScript, you can only open the print dialog for the existing page - article and print API.
PDF is generated on the server and sent to the web-browser (as a separate "page") which has to decide how to process it - the user is usually asked if it wants to display or save the PDF.
To "automatically print" (i.e. open a print dialog) an HTML page you would just have something like this:
window.onload = function() {
window.print();
};
But that can't be done for a PDF since it's not an HTML page.
To "automatically print" something other than an HTML page you would need to have a web-browser plug-in to handle PDFs from your server.
Another posibility is to write a GreaseMonkey user-script that would react on *.myserver.com/**.pdf and have it printed. Note: GreaseMonkey is a Mozilla Firefox plug-in.
Heavy weight option
You could accomplish your task by adding print support to your server application. Application requirements:
It would have to be an Intranet application (self-hosted inside the user's network),
Admin user would need to register network printers accessible from the server via a JSP page,
A "print dialog" page where you would select a registered printer and on clicking the "Print" button send a "print" request, for example:
/print?printer=printer1&doc=/reports/report1
I have seen a Java web application that supported this, but as you can see, it's not an easy task.
#Sujan Sivagurunathan
I tried combining the p:printer and p:media by replacing the image on the p:printer demo page with the PDF file from the p:media demo page:
// Replace this line:
<img id="j_idt18:image" src="/showcase/images/nature1.jpg?pfdrid_c=true" alt="">
// With this one:
<object **id="j_idt18:image"** style="display:none;" type="application/pdf" data="/showcase/resources/other/guide.pdf?pfdrid_c=true">Undefined</object>
When you click the Print button you get an empty page. If you omit the style="display:none;" and leave the PDF's height="300px" width="100%" you will get a small rectangle on the page print preview.
Eidt
Thank you, BalusC and Sujan. I agree, there is an option of embedding JavaScript inside the PDF, but that's usually disabled for security reasons.
I suppose the most browser-compatible and user-friendly way is to have a dedicated Print Preview pop-up window with an iframe showing the given PDF via GET request and a Print button to invoke the IFRAME's contentWindow.print().
It is generally a bad idea to just print a document without letting the user select the printer and configure it.

Accessing HTML controls inside iFrame

How do you access html controls inside an iframe from javascript in CRM?
I have:
var height = document.getElementById("IFRAME_TransactionProduct_RA").contentWindow.document.getElementById("txt").value;
but that results in "Error on page" and the content is not loaded.
The element I want to access is an html input with id of 'txt':
<input id="txt" type="hidden" />
Here's an example how you copy a value from a CRM field to a control in an embedded HTML control in an IFRAME. I'm assuming the names of the web resource and the field. You'll have to adapt those. You also might throw in a try-catch in case CRM throws in en exception (got the joke?) and please mind that I'm typing the code on my phone so there might be a typo somewhere (auto-correction, yey).
var source = Xrm.Page.data.entity.attributes.get("oneCoolField")
var information = source.getValue();
var customHtml = Xrm.Page.ui.controls.get("WebResource_EmbeddedHtmlContent");
var destination = customHtml.getObject().contentWindow.document;
if(destination) {
var customControl = destination.getElementById("elementToAccess");
if(customControl) {
customControl.value = information;
}
}
EDIT:
This gets you to the web resource.
var customHtml = Xrm.Page.ui.controls.get("WebResource_EmbeddedHtmlContent");
This gets you to the DOM of the IFRAME.
var destination = customHtml.getObject().contentWindow.document;
This gets you to the control on the custom page.
var customControl = destination.getElementById("elementToAccess");
This gets you the contents of the control.
var contents = customControl.innerHTML;
Which part fails on your computer?
With jQuery:
$(Xrm.Page.ui.controls.get('IFRAME_TransactionProduct_RA').getObject()).contents().find('#txt').val();
Pure JS:
Xrm.Page.ui.controls.get('IFRAME_TransactionProduct_RA').getObject().contentWindow.document.getElementById('txt').value;
http://msdn.microsoft.com/en-us/library/gg334266.aspx#BKMK_getObject

Apache Pivot: Unable to render HelloBxml example

I'm just beginning out with Apache Pivot and started with Hello BXML example on their site. The applet just displays a grey rectangle and nothing more. I've deployed the application under tomcat with following structure:
hellopivot
lib/pivot-*.jar
org.apache.pivot.tutorials.HelloBxml
scripts/deployJava.js
index.html
hello.bxml
index.html:
<script type="text/javascript">var attributes = {
code : "org.apache.pivot.wtk.BrowserApplicationContext$HostApplet",
width : "240",
height : "80"
};
var libraries = [];
libraries.push("lib/pivot-core-2.0.jar");
libraries.push("lib/pivot-wtk-2.0.jar");
libraries.push("lib/pivot-wtk-terra-2.0.jar");
libraries.push("lib/pivot-web-2.0.jar");
libraries.push("lib/pivot-web-server-2.0.jar");
attributes.archive = libraries.join(",");
var parameters = {
codebase_lookup : false,
application_class_name : 'org.apache.pivot.tutorials.HelloBxml'
};
var javaArguments = [ "-Dsun.awt.noerasebackground=true",
"-Dsun.awt.erasebackgroundonresize=true" ];
parameters.java_arguments = javaArguments.join(" ");
deployJava.runApplet(attributes, parameters, "1.6");
</script>
hello.bxml
<Window title="Hello BXML!" maximized="true"
xmlns:bxml="http://pivot.apache.org/bxml"
xmlns="org.apache.pivot.wtk">
<Label text="Hello BXML!"
styles="{font:'Arial bold 24', color:'#ff0000',
horizontalAlignment:'center', verticalAlignment:'center'}"/>
</Window>
HelloBxml.java
#Override
public void startup(Display display, Map<String, String> properties)
throws Exception {
BXMLSerializer bxmlSerializer = new BXMLSerializer();
window = (Window)bxmlSerializer.readObject(HelloBxml.class, "hello.bxml");
window.open(display);
}
What am I doing wrong?
(Disclosure - Apache Pivot PMC member)
How are you attempting to view the applet?
Which OS, JVM, browser etc are you using?
Are you able to view the hosted version of that applet using the same client configuration as the failing 'local' version?
HelloBXML at offical Apache Pivot site
Do you have problems viewing any of the other Pivot applets hosted at the official site? (Demos or Tutorials?)
Issues with applets in linux environments have been reported that sound similar to your experience.
Try adding the "lib/pivot-tutorials-2.0.jar" to your libraries list. That is where the 'org.apache.pivot.tutorials.HelloBxml' class file lives.

Dynamically setting the ListId in the <SharePoint:ListView> control

Is there a way to dynamically set the ListId field in the ListView control. We cannot guarantee that the list we are interested in has a consistent GUID between installations (The list is deployed as part of a site template that we do not control). I've tried using the PreInit event to set a variable (see the list guid: section. If I remove the ListView tag, I see the proper GUID printed out. So I'm collecting the GUID correctly. However, The listview control errors out with the following message "Guid should contain 32 digits with 4 dashes". This tells me that the tag is not getting the variable set. Is this correct? Is there another way to specify the list to use?
Can this be done?
Sample code follows:
<%# Register TagPrefix="Sharepoint" ...details deleted.. %>
<br>
...stuff deleted.
<br>
<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">
... more stuff deleted...
<p>list guid: <%=ListGuid %>
<Sharepoint:ListView ListId="<%=ListGuid %>" Enabled="true" runat="server" />
<p>
</asp:Content>
<script runat="server">
string ListGuid = string.Empty;
protected void Page_PreInit(object sender, EventArgs e)
{
SPSite Site = SPContext.Current.Site;
using (SPWeb HelpDesk = Site.OpenWeb("HelpDesk"))
{
SPList list = HelpDesk.Lists["Charge Numbers"];
ListGuid = list.ID.ToString();
}
}
</script>
Having server-side code like you do that gets injected into more server side code is a little weird and seems unlikely to work. What does the SharePoint log say about the list ID that it's trying to load? My guess is that it's not really trying to load the list represented by the GUID that you're setting in your ListGuid variable.
Instead of trying to force some global ListGuid variable to have the correct guid, why not just set the control's ListId property inside your application page's Load event handler?
In the aspx file:
<SharePoint:ListView Id="lv" runat="server" />
In the application page's codebehind:
protected ListView lv
In the Load event:
SPList list = HelpDesk.Lists["Charge Numbers"];
Guid myguid = list.ID;
lv.ListId = myguid.ToString();
I think the error message you are receiving is telling you what's going wrong... the ToString() is converting the GUID to an invalid format. There is an overload for the tostring
list.ID.ToString("N");
list.ID.ToString("D"); (this is the default)
list.ID.ToString("B");
list.ID.ToString("P");
... Try them all

Resources