Monday, February 4, 2013

Light reader of www.alexa.com rank

Alexa is a good site to check you rank, unfortunately it's does not store statistic for the sites that have less than 100,000 rank.

You could buy account, for store such statistic for you own site.

Sometime you need to look for the statistic of your competitors, that are lower than 100,000.

I create a little program that allow you to gather statistic for any site that is on the www.alexa.com.

You need to put URL in to the properties file, run program and look in to the resulting json.

input example

url.1=http://www.alexa.com/siteinfo/championselect.net
url.2=http://www.alexa.com/siteinfo/elohell.net
url.3=http://www.alexa.com/siteinfo/lolcounter.com
url.4=http://www.alexa.com/siteinfo/lolcounterpicks.com
url.5=http://www.alexa.com/siteinfo/counterlol.org
url.6=http://www.alexa.com/siteinfo/picklol.net
url.7=http://www.alexa.com/siteinfo/counterpicker.com

result example

{
  "http://www.alexa.com/siteinfo/championselect.net" : "10,546",
  "http://www.alexa.com/siteinfo/elohell.net" : "16,323",
  "http://www.alexa.com/siteinfo/lolcounter.com" : "16,487",
  "http://www.alexa.com/siteinfo/lolcounterpicks.com" : "462,863",
  "http://www.alexa.com/siteinfo/counterlol.org" : "4,722,060",
  "http://www.alexa.com/siteinfo/picklol.net" : "7,679,714",
  "http://www.alexa.com/siteinfo/counterpicker.com" : "12,461,834"
}

Wednesday, October 17, 2012

xPage: Optimize Uploaded Image

I had a task to upload images in xPage. The next one is to optimize image lossless. User upload the image in to the Domino media library and the image optimizing on the fly.

Unfortunately there is no good Java solution for lossless optimization of images. There are set of solution to use third party command line programs and run it from java. The problem is that you need to install this program on the server, many of them supports only one OS, so if you have Domino server on the windows and then would move to the Linux (or vice verse) you got a problem.

I decide to use online optimizer. It looks like there is no good paid online services with a good API. So I start from the free one. It is well known Yahoo! Smush.it.

Smush.it has no API, but there is a guy who create stand alone java API for Smush.it service. He did it in the way of command line tool, but it could be used as API in your application.

I like it! The only one problem is that program out process information (log) directly in to the System.out. I need some information to be printed in to my log.nsf and some information to be returned to the user. So I add ability to put StringBuilder object in to the Smush.it API.  

Code example:

//log and statistic contains information 
//about process and compression result 
// 
//file - file to optimize, 
//generally opt rewrite file, but not in all cases. 
//Look "Important" section 
// 
//opt - optimized file

StringBuilder log = new StringBuilder();
StringBuilder statistic = new StringBuilder();

SmushIt smushIt = new SmushIt();
smushIt.setVerbose(log);
smushIt.setVerboseStatistic(statistic);     
smushIt.addFile(file.getCanonicalPath());
List<smushitresultvo> smushItResultVos = smushIt.smush();

ImageDownloader imageDownloader = 
 new ImageDownloader(file.getParent());
imageDownloader.setVerbose(log);

File opt = imageDownloader.download(smushItResultVos.get(0));      

StringBuilder log variable after running code:

Smushing files:

C:\Windows\Temp\notesE3A053\xspupload\0001.jpg

Adding file:C:\Windows\Temp\notesE3A053\xspupload\0001.jpg
{"src":"0b2c68eb%2F0001.jpg","src_size":40895,
"dest":"http:\/\/ysmushit.zenfs.com\
/results\/0b2c68eb%2Fsmush%2F0001.jpg",
"dest_size":38749,
"percent":"5.25","id":""}

Downloaded smushed image - 
http://ysmushit.zenfs.com/results/0b2c68eb%2Fsmush%2F0001.jpg
Saved image - C:\Windows\TEMP\notesE3A053\xspupload\0001.jpg

StringBuilder statistic variable after running code:

Source Image:0001.jpg
Source image size:40895
Smushed image size:38749
Percentage saving:5.25

Projects on github:
https://github.com/andriykuba/smushit
https://github.com/abhirama/smushit

Thursday, October 11, 2012

Custom File Upload in the xPage. Java. Backend.

There are a lot of articles about custom file upload with xPages. Most of them are about JavaScript. They use Java classes, so convert that code in to the Java is not problematic.

It's very easy to do in backend java code within xPages. The only one miss is that we could not write to the file attachment directly from the request. We still need to use a file. Thanks to xPage - it handle server temp files himself.

The code:

public void process() throws Exception {
 HttpServletRequest request = getRequest();
 
 Document document =
  getEs().createDocument().getDocument();
 document.replaceItemValue("Form", "picture");

 Map parameters = request.getParameterMap();
 UploadedFile uploadedFile=
  (UploadedFile) parameters.get("upload");
 document.replaceItemValue(
  "FileName",
  uploadedFile.getClientFileName());
 
 File tmpFile = uploadedFile.getServerFile();
 File fileToUpload = new File(
   tmpFile.getParentFile().getAbsolutePath().
   concat(java.io.File.separator).
   concat(uploadedFile.getClientFileName())); 
 
 boolean success = tmpFile.renameTo(fileToUpload); 
 addAttachment(document, success?fileToUpload:tmpFile);
 fileToUpload.renameTo(tmpFile);
 
 document.save(true, true);
}

private void addAttachment(Document document, File file)
 throws Exception{
 RichTextItem item = document.createRichTextItem("Body");
 item.embedObject(
  EmbeddedObject.EMBED_ATTACHMENT,
  "", 
  file.getCanonicalPath(), null);   
}

Look http://lotusandjava.blogspot.com/2012/09/accessing-xpages-global-objects-in-java.html to find how to get request

Saturday, October 6, 2012

It looks like Planet Lotus users are more familar with programming languages than with natural.

True code header have better rate:



CKFinder for Domino. Downloading

CKFinder have two options to download files (images) - by request to the server "connector" command processor and by direct downloading.

Request to the "connector" ("ckfinder-connector-url\connector.xsp?command=Download...") is not accessible for Domino.

For direct download CKFinder use file(image) link with the "?download" command. Let's modify this way for allowing CKFinder to "download" files from the Domino server.

Browser would download file in the case if "content-disposition" header available (and filled). We need to have ability to open file (no "content-disposition" header) and to download file ("content-disposition" header present). Let assume we have some database with web view "web-files" for open files on the web. Then we will need another one, completely the same, view "web-download" for downloading files and HTTP response headers rule for  adding "content-disposition" header.

HTTP response headers rule:
Incoming URL pattern: */web-download/*
Custom headers:
            Name: content-disposition 
            Value: attachment

Now, when you will open file "web-files/companylogo.jpg", then browser will show it, and when you open file "web-files/companylogo.jpg", then browser will ask to save it.

Domino configured. Now we need to modify ckfinder.js to allow it to load files from another url. I am using "url" attribute of "ResourceType" tag in the response of "Init" command to put files url. So I  add "download" attribute to the "ResourceType" tag to put files download url.

ckfinder.js with modification that supports "download" attribute: 

p.resourceTypes.push(new a.aL.ResourceType(p, {
 name: t.getNamedItem('name').value,
 url: t.getNamedItem('url').value,
 
 //Modification
 download: t.getNamedItem('download').value,
 
 hasChildren: t.getNamedItem('hasChildren').value,
 allowedExtensions: 
  t.getNamedItem('allowedExtensions').value,
 deniedExtensions: 
  t.getNamedItem('deniedExtensions').value,
 acl: t.getNamedItem('acl').value,
 hash: t.getNamedItem('hash').value,
 maxSize: t.getNamedItem('maxSize').value
}));

And

a.aL.ResourceType = function (q, r) {
 var s = this;
 s.app = q;
 s.name = r.name;
 s.url = r.url;
 
 //Modification
 s.download = r.download;
 
 s.hasChildren = r.hasChildren === 'true';
 s.defaultView = 'Thumbnails';
 s.allowedExtensions = r.allowedExtensions;
 s.deniedExtensions = r.deniedExtensions;
 s.oT = p(r.allowedExtensions);
 s.ms = p(r.deniedExtensions);
 s.nS = r.acl;
 s.hash = r.hash;
 s.maxSize = r.maxSize;
};

Now we need to change generation of download url in he CKFinder:

if (R.config.directDownload){
 //Modification
 var filename = encodeURIComponent(S.name);
 
 var basenanme = 
 filename.substring(0, filename.lastIndexOf('.'));
 
 T = S.folder.getResourceType().download + 
 basenanme+'/$file/'+filename;

 //original CKFinder String
 //T = S.folder.getUrl() + S.name + '?download';
}

That's all.

Friday, October 5, 2012

CKFinder for Domino. Images (and Files)

CKFinder open an image in the same way as a thumbnail. So we have exactly the same problem like for thumbnails in Domino.

CKFinder construct link to the file like "base-file-url\filename". In Domino, we have access to the attachment with the help of "\$file\" path. So we must to have URL like:
"base-file-url\filename\$file\filename." or "base-file-url\filename\filename" in the case of substitution.

You need to find in the ckfinder.js string like
J.push('<a href="', D.folder.getUrl(), 
encodeURIComponent(C[K].name), 
'" title="', C[K].name, '" rel="', E, '">a</a>'); 
and change it with
if (!F || F(C[K])) {   
 var filename = encodeURIComponent(C[K].name);
 var basenanme = filename.substring(0, 
  filename.lastIndexOf('.'));
 var url = D.folder.getResourceType().url 
  + basenanme+'/$file/'+filename;
 
 J.push('<a href="', url, '" title="', C[K].name, 
  '" rel="', E, '">a</a>');                    
 if (C[K].isSameFile(D)) H = I;
 I++;
}
That will change image url. You also need to change File url. Find
if (!W.open(S.folder.getUrl() + 
 encodeURIComponent(S.name), '_blank', V)) 
 R.msgDialog('', R.lang.ErrorMsg.oo);

and change it with

var filename = encodeURIComponent(S.name);
var basenanme = filename.substring(0, filename.lastIndexOf('.'));
var url = S.folder.getResourceType().download + basenanme+
 '/$file/'+filename;
if (!W.open(url, '_blank', V)) 
 R.msgDialog('', R.lang.ErrorMsg.oo);

CKFinder for Domino. Thumbnails.

CKFinder have two options to show thumbnails - by request to the server "connector" command processor and by direct downloading.

Request to the "connector" ("ckfinder-connector-url\connector.xsp?command=Thumbnails...") is not accessible for Domino. Reading thumbnail attachment on the server and return data as result of the command is expensive operation for the server.

CKFinder construct direct download like "thumb-base-url\filename?hash=.....". In Domino, we have access to the attachment with the help of "\$file\" path. So we must to have URL like:
"thumb-bas-url\filename\$file\filename?Open&hash=....." 

Or better:
"thumb-bas-url\filename-thumb-without-ext\$file\filename-thumb?Open&hash=....." 

In the case if will use substitution rules for fine url:
"thumb-bas-url\filename-thumb-without-ext\filename-thumb?Open&hash=....." 

You need to find in the ckfinder.js  "getThumbnailUrl" function and modify code in the
"L && N.config.thumbsDirectAccess"
condition:

if (L && N.config.thumbsDirectAccess) {
     var filename = encodeURIComponent(M);
     var dotIndex = filename.lastIndexOf('.');
     var ext = filename.substring(dotIndex+1);
     var basenanme = filename.substring(0, dotIndex);
     return N.config.thumbsUrl + basenanme 
         + '-thumb/$file/'
         + basenanme + '-thumb.' + ext
         + (!K ? '' : '?Open&hash='
         + N.getResourceType(R.folder.type).hash
         + '&fileHash=' + P);
}

Wednesday, October 3, 2012

xPage java.lang.NoClassDefFoundError

Suddenly got "java.lang.NoClassDefFoundError" error on my xPage for the class from "Java" design area. The day before it works without problems.

Project clean, rebuild does not help.  Server restart does not help. I read that Recompile code when opening in designer (xPages) solution helps for someone, unfortunately not for me.

The only one solution helps is to rename class that was not found. I am lucky to have only one such class and I am afraid to get this error again for all of them.


... maybe I will try to move code to the WEB-INF/src ...

My Client version is "20120703.0900-T00099SHF-FP2 (Release 8.5.3FP2 SHF99) "

Friday, September 28, 2012

CKFinder for Domino. First step.

I am trying to get CKFinder to work with Domino.

I saw the post "ckeditor 3.2, ckfinder 1.4.3 and Domino" but it is unavailable 2nd day, so I am looking himself in to this point.

First problem

CKFinder add some command to the end of it's URL, that domino server do not like:
 "?t=XYZ".  

Just remove it:
open ckfinder.js, look for something like "f={jY:'C7OA1WG',_:{}," and replace it on "f={_:{}," (delete jY:'C7OA1WG')

CKFinder also use command syntax like "?command=..". It's also a little trouble for domino.

Replace "?command=.." to "?Open&command=.." in the ckfinder.js

Second problem

I am trying to create server side command handlers for CKFinder.
"INIT" command example"

<?xml version="1.0" encoding="utf-8"?>
<Connector>
<Error number="0" />
<ConnectorInfo enabled="true" s="" c="" thumbsEnabled="true"  
thumbsUrl="/userfiles/_thumbs/" thumbsDirectAccess="false" />
<ResourceTypes>
<ResourceType name="Files" url="/userfiles/files/" 
allowedExtensions="7z,aiff,asf,avi,bmp,csv,doc,fla,flv,gif" 
deniedExtensions="" defaultView="Thumbnails" hash="654e8f3600949355"  
hasChildren="true" acl="17" />
<ResourceType name="Images" url="/userfiles/images/"  
allowedExtensions="bmp,gif,jpeg,jpg,png" 
deniedExtensions="" defaultView="Thumbnails" hash="4d8ddfd385d0952b" 
hasChildren="true" acl="17" />
<ResourceType name="Flash" url="/userfiles/flash/"  
allowedExtensions="swf,flv" 
deniedExtensions="" defaultView="Thumbnails" hash="a2d473ff04429cc5" 
hasChildren="true" acl="17" />
</ResourceTypes>
</Connector>

This example born errors in real life:

Error:
TypeError: t.selectSingleNode(v + "@imgWidth") is null

Fix:
"Connector/ConnectorInfo" node must have "imgWidth" attribute (as well as "imgHeight") in the command "init" resonse

Error:
TypeError: t.getNamedItem("maxSize") is null

Reason:
"Connector/ResourceTypes/ResourceType" node must have "maxSize" attribute in the command "init" resonse

So the correct "INIT" response must be like

<?xml version="1.0" encoding="utf-8"?>
<Connector>
<Error number="0" />
<ConnectorInfo imgHeight="100" imgWidth="100" enabled="true" s="" c=""  
thumbsEnabled="true" thumbsUrl="/userfiles/_thumbs/" 
thumbsDirectAccess="false" />
<ResourceTypes>
<ResourceType name="Files" url="/userfiles/files/"  
allowedExtensions="7z,aiff,asf,avi,bmp,csv,doc,fla,flv,gif" 
deniedExtensions="" defaultView="Thumbnails" hash="654e8f3600949355"  
hasChildren="true" acl="17"  maxSize="100"/>
<ResourceType name="Images" url="/userfiles/images/"  
allowedExtensions="bmp,gif,jpeg,jpg,png" 
deniedExtensions="" defaultView="Thumbnails" hash="4d8ddfd385d0952b" 
hasChildren="true" acl="17" maxSize="100"/>
<ResourceType name="Flash" url="/userfiles/flash/" 
allowedExtensions="swf,flv" 
deniedExtensions="" defaultView="Thumbnails" hash="a2d473ff04429cc5"  
hasChildren="true" acl="17" maxSize="100"/>
</ResourceTypes>
</Connector>

Thursday, September 27, 2012

CKFinder in Domino

I need to add some image library to use it with CKEditor in domino.

The best I found is CKFinder (it is not free). I did not find a good media library for build it up on the Domino.

CKFinder also have some troubles in the case of  work with Domino.

Do someone know a good media library?  I would prefer some client side library that communicate with server through  JSON or XML (like CKFinder).

Maybe some one have a nice experience with CKFinder on Domino ?