Synology DownloadStation with JDownloader click’n'load

Since a few months, I am a proud owner of a Synology NAS (211j). It has many useful features and works like a charme. One important feature is the DownloadStation which supports downloading from many different hosters even with using premium accounts.
Although synology provides software to redirect downloads from your browser to the DownloadStation, I was missing a special feature: Many sites offer support for JDownloader’s click’n'load feature which adds a list of URLs to be downloaded to the JDownloader application. Because I was not able to find a plugin or application capable of decrypting and adding download URLs to the Synology DownloadStation, I decided to create it on my own.

First, I created a library (synolib) that encapsulates all the HTTP communication to the DownloadRedirector API (CGI) and provides a nice Java interface for use in application. It currently supports login, adding a download URL and retrieving a list of all current downloads.
The main program is called JdAdapter – a webapp that implements the click’n'load functionality of JDownloader. When clicking on a click’n'load button, it decrypts the URLs and adds them to the DownloadStation via synolib.

The software is written in plain Java and thus runs on nearly every operating system.

Requirements

  • Installed Java (JVM)
  • Enabled DownloadStation on NAS
  • NAS user with admin rights*
  • Basic HTTP frontend access (HTTPS not yet supported)

Known Issues

Known issues can be found in the board.

Get Help / Report Bugs

Please use our board to get help or report bugs.

Download

JdAdapter (Version 0.2-SNAPSHOT) (220)

Sources (SVN)

Weiterlesen

Simple edge detection invented “from scratch”.

As I am mostly working on middlewares and webapplications at work, I decided to try out something different this weekend. A long time ago I had the idea of writing a software that is able to recognize license plates. Today I know that this is not a trivial task – but just to be sure, I tried something like that:

Before you can start to analyze the content of a picture, you often have to detect edges in it. So a simple edge detection was my main target for today. As you can see in the following pictures, it works quite well:

You can see four images in the application screenshot – the whole process of my edge detection:

  • Top left: Original image
  • Top right: Greyscale version of the image
  • Bottom left: Gaussian blur on greyscale image (reduces noise)
  • Bottom right: Edge detection applied

Another example picture:

As you can see, the edge detection currently is rather inaccurate but maybe I will find some time and motivation to improve it.

For now, the code looks like this:

Create greyscale copy of the image

BufferedImage src = (BufferedImage) srcImage;
BufferedImage targetImg = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
 
for (int x = 0; x < src.getWidth(); x++) {
    for (int y = 0; y < src.getHeight(); y++) {
        Color srcCol = new Color(src.getRGB(x, y));
        int greyVal = (int) (0.2989 * srcCol.getRed() + 0.5870 * srcCol.getGreen() + 0.1140 * srcCol.getBlue());
        targetImg.getRaster().setSample(x, y, 0, greyVal);
    }
}
 
return targetImg;

Applying gaussian blur

final BufferedImage src = (BufferedImage) srcImage;
final int srcWidth = src.getWidth();
final int srcHeight = src.getHeight();
long startAt = System.currentTimeMillis();
 
int[][] matrix = {{1,2,1},
                  {2,4,2},
                  {1,2,1}};
 
Raster raster = src.getRaster();
BufferedImage targetImg = new BufferedImage(srcWidth, srcHeight, BufferedImage.TYPE_BYTE_GRAY);
 
for (int x = 0; x < srcWidth; x++) {
    for (int y = 0; y < srcHeight; y++) {
 
        int factor = 0;
        int pixelSum = 0;
        for (int ix = 0; ix < matrix.length; ix++) {
            for (int iy = 0; iy < matrix.length; iy++) {
                int xRead = x - 2 + ix;
                int yRead = y - 2 + iy;
 
                if (xRead >= 0 && yRead >= 0 && xRead < srcWidth && yRead < srcHeight) {
                    int weight = matrix[ix][iy];
                    pixelSum = pixelSum + (weight * raster.getSample(xRead, yRead, 0));
                    factor += weight;
                }
            }
        }
        int pixelRgbVal = pixelSum / factor;
        targetImg.getRaster().setSample(x, y, 0, pixelRgbVal);
    }
}
 
long stopAt = System.currentTimeMillis();        
System.out.println("Duration for blur: " + (stopAt - startAt) + " ms");
 
return targetImg;

Detect edges (primitive way)

        final BufferedImage srcImg = (BufferedImage) src;
final int srcWidth = srcImg.getWidth();
final int srcHeight = srcImg.getHeight();
 
BufferedImage targetImg = new BufferedImage(srcWidth, srcHeight, BufferedImage.TYPE_INT_RGB);
Raster srcRaster = srcImg.getRaster();
 
for (int x = 0; x < srcWidth; x++) {
    for (int y = 0; y < srcHeight; y++) {
        if (x + 1 < srcImg.getWidth()) {
            if (Math.abs(srcRaster.getSample(x, y, 0) - srcRaster.getSample(x +1, y, 0)) > schwelle) {
                targetImg.setRGB(x, y, Color.WHITE.getRGB());
            }
        }
        if (y + 1 < srcImg.getHeight()) {
            if (Math.abs(srcRaster.getSample(x, y, 0) - srcRaster.getSample(x, y + 1, 0)) > schwelle) {
                targetImg.setRGB(x, y, Color.WHITE.getRGB());
            }
        }
    }
}
 
return targetImg;

DynamicProxies – The magic behind OR-mappers and mocking frameworks

Did you ever wonder how mocking frameworks “create” instances of you interfaces? Or how OR-mappers like Hibernate give you entities with lazily loaded references to another of your entities that throw the well known LazyInitializationException when the session is already closed?

The answer is: Dynamic proxies.

As part of the reflection package in the JDK, the classes around java.lang.reflect.Proxy allow you to create instances of interfaces – even if there is no implementation of that interface present in the classpath. These instances are called “proxy-instances”.

Each proxy-instance has assigned an implementation of the interface java.lang.reflect.InvocationHandler. The handler gets informed about every method that is called on the proxy-instance (including arguments, return types etc.). This allows you to dynamically create “runtime implementations” of interfaces, giving them a custom behavior (testing frameworks like JUnit – record, replay, etc.) or just to intercept/modify calls to a “real” instance (AOP-like behavior).

Here is an example to get an idea of how (easy) it works:

Main class

package de.perdoctus.examples;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
 
/**
 * This class contains a main method that creates a dynamic proxy.
 * 
 * @author Christoph Giesche
 */
public class ProxySample {
 
    public static void main(String[] args) {
 
        //Create an instance of our InvocationHandler
        InvocationHandler handler = new UselessHandler();
 
        //Create a "dynamic proxy" of our useless interface
        Object proxy = Proxy.newProxyInstance(
                Useless.class.getClassLoader(), 
                new Class[] {Useless.class}, 
                handler);
 
        //Cast the proxy instance to our Useless interface
        Useless uselessProxy = (Useless) proxy;
 
        //Call some methods on our instance
        uselessProxy.getStatus();
        uselessProxy.setSomeValue("foobar");
        uselessProxy.toString();
    }
}

Interface that is used to create proxy-instance

package de.perdoctus.examples;
 
/**
 * Just a useless interface to demonstrate dynamic proxies.
 * 
 * @author Christoph Giesche
 */
public interface Useless {
    void getStatus();
    void setSomeValue(String value);
}

An invocation handler telling you what is going on

package de.perdoctus.examples;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
/**
 * UselessHandler will handle all method calls to our dynamic proxy. This
 * handler can be assigned to different proxy instances.
 * 
 * @author Christoph Giesche
 */
public class UselessHandler implements InvocationHandler {
 
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 
        StringBuilder sb = new StringBuilder();
 
        sb.append("Method '")
          .append(method.getName())
          .append("' was called ");
 
        if (args != null) {
            sb.append("with arguments:");
            for (Object arg : args) {
                sb.append('\n');
                sb.append(arg.getClass().getSimpleName())
                  .append(" = ")
                  .append(arg.toString());
            }
        } else {
            sb.append("without arguments.");
        }
 
        sb.append("\nThe method has the return type '")
          .append(method.getReturnType())
          .append("'\n");
 
        System.out.println(sb.toString());
        return null;
    }
 
}

Result when running main class

Method 'getStatus' was called without arguments.
The method has the return type 'void'

Method 'setSomeValue' was called with arguments:
String = foobar
The method has the return type 'void'

Method 'toString' was called without arguments.
The method has the return type 'class java.lang.String'

How to REST – Useful articles

If you are planning to use REST in your projects, I strongly recommend you to get in touch with it’s principles. As REST makes excessive use of the standard HTTP protocol, aspects like caching can be delegated to one of the various HTTP caching products.

Below, you can find some very useful articles about the principles of REST including versioning and common mistakes when implementing a REStful service.

After having read all of those articles, you may have a more precise understanding of what RESTful interfaces should look like and what advantages you have due to the fact that it is based on HTTP.

Evaluating JavaScript from within your Java application

Sometimes you may wish to include JavaScript, Groovy or other scripting languages features within your Java application. The package javax.script offers an API for exactly that purpose.

The JRE provides a JavaScript engine (Mozilla’s Rhino) by default. Additional engines are listed here.

A simple example of how to evaluate a JavaScript in Java is shown below. If needed, you have access to the complete Java API from within your script.

package de.perdoctus.examples;
 
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
 
/**
 * @author Christoph Giesche
 */
public class ScriptManagerExample {
 
    public static void main(String[] args) {
        //create a ScriptEngineManager
        ScriptEngineManager sem = new ScriptEngineManager();
 
        //obtain a JavaScript engine from the manager
        ScriptEngine engine = sem.getEngineByName("JavaScript");
 
        //put some attributes to the engine's context
        ScriptContext context = engine.getContext();
        context.setAttribute("netPrice", 10.92, ScriptContext.ENGINE_SCOPE);
        context.setAttribute("vat", 19, ScriptContext.ENGINE_SCOPE);
 
        //Execute some JavaScript using our attributes.
        try {
            engine.eval("var price = netPrice + (netPrice * vat / 100)");
        } catch (ScriptException ex) {
            System.err.println(ex);
        }
 
        //retrieve attribute "price" from engine's context
        Double price = (Double) context.getAttribute("price");
 
        System.out.println("Price including vat: " + price);
    }
}